Project import generated by Copybara.

GitOrigin-RevId: 1215ec3b34818127b1eb745b7d89624888a35282
diff --git a/mass_storage/mkisofs-1.11.3/Android.mk b/mass_storage/mkisofs-1.11.3/Android.mk
new file mode 100644
index 0000000..eeda739
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE:= mkisofs
+LOCAL_SHARED_LIBRARIES := libcutils libc
+LOCAL_SRC_FILES:= mkisofs.c \
+		  tree.c \
+		  write.c \
+		  hash.c \
+		  rock.c \
+		  exclude.c \
+		  multi.c \
+		  files.c \
+		  match.c \
+		  name.c \
+		  fnmatch.c \
+		  eltorito.c
+include $(BUILD_EXECUTABLE)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/mass_storage/mkisofs-1.11.3/COPYING b/mass_storage/mkisofs-1.11.3/COPYING
new file mode 100644
index 0000000..946cb19
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/COPYING
@@ -0,0 +1,345 @@
+ The GPL below is copyrighted by the Free Software
+ Foundation, but the instance of code that it refers to (the mkisofs
+ utility is copyrighted by Yggdrasil Computing, Incorporated).
+
+----------------------------------------
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/mass_storage/mkisofs-1.11.3/ChangeLog b/mass_storage/mkisofs-1.11.3/ChangeLog
new file mode 100644
index 0000000..8c17768
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/ChangeLog
@@ -0,0 +1,863 @@
+Wed Nov  5 10:46:29 1997  Andreas Buschmann US/EC4 60/1F/110 #40409  <buschman@lts.sel.alcatel.de>
+
+	Circumvent a bug in the SunOS / Solaris CD-ROM driver (and maybe HP/UX, too).
+       
+       * mkisofs.8 (-S): Document switch.
+       *  mkisofs.c (split_SL_field): new Variable, new switch -S.
+       *  mkisofs.h (split_SL_field): new Variable.
+       * rock.c (generate_rock_ridge_attributes): only split SL field,
+       when split_SL_field is set.
+ 
+Tue Jun  3 15:32:21 1997  Andreas Buschmann <buschman@lts.sel.alcatel.de>
+ 
+       Circumvent a bug in the SunOS CD-ROM driver (and maybee HP/UX, too).
+ 
+       * mkisofs.8 (-s): Document switch.
+       * mkisofs.c (split_SL_component): new Variable, new switch -s.
+       * mkisofs.h (split_SL_component): new Variable.
+       * rock.c (generate_rock_ridge_attributes): only split SL
+       components, when split_SL_component is set.
+       
+       * defaults.h: Added SunOS string.
+       
+
+Wed Mar 19 16:50:17 1997  Fred Fish  <fnf@ninemoons.com>
+
+	* Makefile.in (CFLAGS): Let configure set basic flags.  Move
+	compilation option -c to actual CC commands.
+	(LDFLAGS): Let configure set basic flags.
+	(Makefile): Depends upon config.status, not configure.
+	Regenerate if necessary from Makefile.in using config.status.
+	(configure): Cd to srcdir before running autoconf.
+	* acconfig.h: New file to hold nonstandard entries used in
+	config.h.in.  Used by autoheader to generate config.h.in.
+	* config.h.in: Regenerated with autoheader.
+	* configure.in: Check for existance of sbrk() function.
+	* configure: Regenerated with autoconf 2.12.
+	* fnmatch.c (FMN_FILE_NAME): Define if not already defined.
+	(FNM_LEADING_DIR): Ditto.
+	(FNM_CASEFOLD): Ditto.
+	* mkisofs.c (main): Only use sbrk() if system supports it.
+
+Fri Mar 14 21:54:37 1997  Eric Youngdale  <eric@andante.jic.com>
+
+	* Bump version number to 1.10, public release.
+
+	* Put entire thing under RCS.  History is buried there now.
+
+	* Fix bug involving empty directories, translation tables and
+	malloc(0).
+
+Mon Feb 17 12:44:03 1997  Eric Youngdale  <eric@andante.jic.com>
+
+	* Bump version number to 1.10b7.
+
+	* Makefile.in, configure.in, config.in: Change to use GNU autoconf.
+
+	* Configure: Delete old configuration script.
+
+	* tree.c: Fix bug where we had a rename limit of 1000 files
+	instead of 0x1000.
+
+	* mkisofs.c: Fix sign of timezone offset.  Linux iso filesystem
+	also need to be fixed, unfortunately.
+	
+Tue Dec  3 22:21:21 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+	Fixed a couple of multi-session bugs.  Discs now seem to
+	work on both Solaris and Windows-NT.
+
+	* Bump version number to 1.10b6.
+
+Tue Dec  3 22:21:21 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+	Multi-session stuff *almost* there.  Discs seem to work
+	under Linux without any problem, but under DOS only
+	the first session is seen.  The patch to write.c
+	inspired by disc written by Windows generated multi-session
+	disc, which will hopefully make the discs usable under
+	DOS as well.
+	
+	* Bump version number to 1.10b5.
+
+	* write.c: use size of new session, not total of all sessions
+	in volume_space_size field.
+
+	* mkisofs.8: Update with current location of cdwrite.
+
+Mon Nov  4 23:45:01 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+	* Bump version number to 1.10b4.
+
+	* Add cdwrite.c.diff file, which provides a very crude, minimal
+	interface between mkisofs and cdwrite.  It should be enough to
+	generate a multi-session disc, but it hasn't been tested yet.
+
+Thu Oct 17 00:39:52 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+	* Bump version number to 1.10b3.
+
+Wed Oct 16 23:40:44 1996  Michael Fulbright <msf@redhat.com>
+
+	Add support for 'El Torito' specification which allows for bootable
+	cdroms.
+
+	* Makefile.in: Add eltorito.[c,o].
+
+	* defaults.h: Add default settings for El Torito related things.
+
+	* iso9660.h: Add structure definitions for El Torito.
+
+	* mkisofs.8: Document new options.
+
+	* mkisofs.c: Add support for new options related to El Torito.
+
+	* mkisofs.h: Add definitions, prototypes as required.
+
+	* tree.c: Add search_tree_file function to search for a specified
+	file.
+
+	* write.c: Add support for writing special records for El Torito.
+
+	* eltorito.c: New file.
+
+	
+Wed Oct 16 23:40:44 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+	* rock.c: Fix bug whereby we made assumptions about how
+	dev_t was split into major/minor.  Use major() and minor()
+	macros to do this for us, since each system should
+	do this correctly.
+
+	* write.c: Fix bug whereby abstract, copyright and appid
+	strings were not properly filled if application ID weren't
+	in use.
+
+Sun Sep 29 10:05:10 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+	* Bump version number to 1.10b2.  Minor bug fixes here
+	and there.
+
+Sun Sep 15 18:54:05 1996  Eric Youngdale  <eric@sub2317.jic.com>
+
+	* Bump version number to 1.10b1.  Major new functionality is
+	support for multi-session.  Still a bit preliminary, but
+	most of the pieces are there now.
+
+Wed Dec 20 16:44:44 1995  Eric Youngdale  (eric@andante.aib.com)
+
+        * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.05.
+
+	* rock.c: Bugfix for cases where sizeof(int) == 4 and
+	sizeof(dev_t) > 4.
+
+	* rock.c: Bugfix for long symbolic links ('/' characters were
+	being dropped).
+
+	Patches from Peter Miller <pmiller@agso.gov.au>:
+
+	* mkisofs.8: Documentation fix (some versions of nroff don't
+	like '.' in column 1 if it is not a nroff command).
+
+	* mkisofs.c: Add support for 'rationalize' option.
+	Similar to rock ridge, except echos of development environment
+	are removed.
+
+	* write.c Status indicator now indicates percent finished, and
+	estimated time of completion.
+
+Sun Feb 26 01:52:06 1995  Eric Youngdale  (eric@largo)
+
+	* Add patches from Ross Biro to allow you to merge arbitrary
+	trees into the image.  This is not compiled in by default but
+	you need to add -DADD_FILES when compiling.
+
+Fri Feb 17 02:29:03 1995  Paul Eggert  <eggert@twinsun.com>
+
+	* tree.c: Port to Solaris 2.4.  Prefer <sys/mkdev.h> if
+	HASMKDEV.  Cast unknown integer types to unsigned long and
+	print them with %lu or %lx.
+
+Thu Jan 26 15:25:00 1995  H. Peter Anvin  (hpa@yggdrasil.com)
+
+	* mkisofs.c: Substitute underscore for leading dot in non-Rock
+	Ridge filenames, since MS-DOS cannot read files whose names
+	begin with a period.
+
+Mon Jan 16 18:31:41 1995  Eric Youngdale  (eric@aib.com)
+
+	* rock.c (generate_rock_ridge_attributes): Only use ROOT
+	record for symlinks if we are at the start of the symlink.
+	Otherwise just generate an empty entry.
+
+Mon Jan 16 16:19:50 1995  Eric Youngdale  (eric@aib.com)
+
+	* diag/isodump.c: Use isonum_733 instead of trying to dereference
+	pointers when trying to decode 733 numbers in the iso9660 image.
+
+	* diag/isovfy.c: Likewise.
+
+	* write.c: Always assign an extent number, even for zero length
+	files.  A zero length file with a NULL extent is apparently dropped
+	by many readers.
+
+Wed Jan 11 13:46:50 1995  Eric Youngdale  (eric@aib.com)
+
+	* mkisofs.c: Modify extension record to conform to IEEE P1282
+	specifications.  This is commented out right now, but a trivial
+	change to a #define enables this.   I need to see the specs
+	to see whether anything else changed before this becomes final.
+
+	* write.c (FDECL4): Fix so that we properly determine error
+	conditions.
+
+	* mkisofs.h: Change rr_attributes to unsigned.
+
+	* tree.c(increment_nlink): Change pnt since rr_attributes is now
+	  unsigned.
+
+	Ultrix patches from petav@argon.e20.physik.tu-muenchen.de (Peter Averkamp)
+
+	* rock.c: Fix for ultrix systems, we have 64 bit device numbers.
+	Type cast when generating file size.  Change rr_attributes to
+	unsigned.
+
+	* mkisofs.c: For ultrix systems, define our own function
+	for strdup.  
+
+	* mkisofs.c: Fix usage() since some compilers do not concatenate
+	strings properly (i.e. ultrix).
+
+	Bugs found with Sentinel II:
+
+	* write.c: Fix a couple of memory leaks.
+
+	* mkisofs.c: Bugfix - always put a zero byte at end of name
+	for ".." entry.
+
+	* tree.c: Set isorec.date from fstatbuf.st_ctime, not current_time,
+	  since current_time might not be set.
+
+Sat Dec  3 14:55:42 1994  Eric Youngdale  (eric@andante)
+
+	* mkisofs.c: When returning entry for ".." file, set second byte
+	to 0.
+
+	* write.c: Free name and rr_attributes fields when writing.
+
+Mon Nov 28 13:36:27 1994  Eric Youngdale  (eric@andante)
+
+	* mkisofs.h: Change rr_attributes to unsigned.
+
+	* rock.c: Ditto.  Work around >>32 bug in ultrix for 64 bit data types.
+
+	* mkisofs.c (usage): Fix for ultrix - use continuation lines
+	instead of assuming that strings are catenated by the compiler.
+
+Mon Jun 20 20:25:26 1994  Eric Youngdale  (eric@esp22)
+
+        * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to pre-1.02.
+
+	* mkisofs.h: Fix declaration of e_malloc to use DECL macros.
+
+	* tree.c: Fix bug in previous change.
+
+	* diag/*.c: Add appropriate copyright notices.
+
+Sat Apr  9 13:30:46 1994  Eric Youngdale  (ericy@cais.com)
+
+        * Configure: New file - shell script that determines a bunch of
+	things to properly build mkisofs.
+
+	* Makefile.in: New file - copy of Makefile, but Configure sets a
+	few things up for it.
+
+	* tree.c: Do not depend upon opendir to return NULL if we cannot
+	open a directory - actually try and read the first entry.  The
+	foibles of NFS seem to require this.
+
+	* write.c: Fix definition of xfwrite (Use FDECL4)
+
+	Add some changes to allow more configurability of some of the
+	volume header fields:
+
+	* mkisofs.8: Document new configuration options.
+
+	* mkisofs.c: Add variables to hold new fields.  Add function to
+	read .mkisofsrc files.
+
+	* defaults.h: Another way of configuring the same things.
+
+	Add some changes from Leo Weppelman leo@ahwau.ahold.nl.
+
+	* mkisofs.c:  Allow -A to specify application ID.  Fix usage(),
+	getopt and add case switch.
+
+	* rock.c: Fix handling of device numbers (dev_t high should only
+	be used when sizeof(dev_t) > 32 bits).
+
+	Add a bunch of changes from Manuel Bouyer.
+
+	* diag/Makefile: New file.
+
+	* diag/dump.c, diag/isodump.c: Use termios if system supports it.
+
+	* (throughout): Replace all occurences of "malloc" with e_malloc.
+
+	* mkisofs.c:  For NetBSD, attempt to increase the rlimit for
+	the size of the data segment to about 33 Mb.
+
+	* mkisofs.c (e_malloc): New function.  Calls malloc, and prints
+	nice error message and exits if NULL is returned.
+
+Sun Jan 23 19:23:57 1994  Eric Youngdale  (eric@esp22)
+
+        * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.01.
+
+    Add a bunch of stuff so that mkisofs will work on a VMS system.
+
+	* (ALL): Change any direct use of the "st_ino" field from
+	the statbuf to use a macro.
+
+	* mkisofs.h: Define appropriate macros for both VMS and unix.
+
+	* (ALL): Add type casts whenever we use the UNCACHED_DEV macro.
+
+	* rock.c: Wrap a #ifndef VMS around block and character device
+	stuff.
+
+	* write.c: Add prototype for strdup if VMS is defined.
+
+	* make.com: Script for building mkisofs on a VMS system.
+
+	* Makefile: Include make.com in the distribution.
+
+	* mkisofs.c: Include <sys/type.h> on VMS systems.
+
+	* tree.c: Include <sys/file.h> and "vms.h" on VMS systems.
+
+	* mkisofs.h (PATH_SEPARATOR, SPATH_SEPARATOR):  New macros
+	that define the ascii character that separates the last directory
+	component from the filename.
+
+	* tree.c, mkisofs.c: Use them.
+
+	* vms.c: New file.  Contains version of getopt, strdup, opendir,
+	readdir and closedir.
+
+	* vms.h: New file.  Defines S_IS* macros.  Define gmtime as
+	localtime, since gmtime under VMS returns NULL.
+
+Sat Jan 15 13:57:42 1994  Eric Youngdale  (eric@esp22)
+
+	* mkisofs.h (transparent_compression): New prototype.
+
+	* mkisofs.c (transparent_compression): Declare, use
+	'-z' option to turn on.
+
+	* tree.c: Change TRANS.TBL;1 to TRANS.TBL (version gets
+	added later, if required).
+
+	* rock.c: If transparent compression requested, verify
+	file is really suitable (check magic numbers), and extract
+	correct file length to store in SUSP record.
+
+Sat Jan 15 01:57:42 1994  Eric Youngdale  (eric@esp22)
+
+	* write.c (compare_dirs): Bugfix for patch from Jan 6.
+
+	* mkisofs.h (struct directory_entry): Add element total_rr_attr_size.
+	(struct file_hash): Add element ce_bytes.
+
+	* write.c (iso_write): Update last_extent_written, as required,
+	and check it against last_extent as a sanity check.
+	(generate_one_directory): If ce_bytes is non-zero, allocate
+	a buffer and fill it with the CE records.  Also, update
+	the extent and offset entries in the CE SUSP field and
+	output after directory is written.
+	(assign_directory_addresses): Allow for CE sectors after each
+	directory.
+
+	* tree.c (sort_n_finish): Set field ce_bytes by summing
+	the sizes of all CE blocks in each files RR attributes.
+	Do not count these bytes for main directory.
+
+	* rock.c (generate_rock_ridge_attributes): Generate
+	CE entries to break up large records into manageable sizes.
+	Allow long names to be split, and allow long symlinks to be split.
+	Allow splitting before each SUSP field as well, to make
+	sure we do not screw outselves.
+
+Thu Jan  6 21:47:43 1994  Eric Youngdale  (eric@esp22)
+
+    Bugfix.
+
+	* write.c (compare_dirs): Only compare directory names up to
+	the ';' for the version number.
+
+    Add four new options: (1) Full 31 character filenames,
+    (2) Omit version number, (3) Omit trailing period from filenames,
+    (4) Skip deep directory relocation.
+
+	* iso9660.h: Allow 34 characters for filename.
+
+	* mkisofs.8: Update for new options.
+
+	* mkisofs.c: Add flag variables for new options.
+	Mention new options in usage(), tell getopt about
+	new options, and set appropriate flags when
+	new options are specified.
+
+	* mkisofs.c (iso9660_file_length): Implement new options.
+
+	* mkisofs.h: Declare flag variables for new options.
+
+	* tree.c (sort_n_finish): Increase declaration of newname and
+	rootname to 34 characters.  If full_iso9660_filenames in effect,
+	use different rules for making unique names.
+
+	* tree.c (scan_directory_tree): Use RR_relocation_depth instead of
+	constant for threshold for starting deep directory relocation.
+
+Wed Jan  5 01:32:34 1994  John Brezak (brezak@ch.hp.com)
+
+	* Makefile.bsd: New file.  For NetBSD.
+
+	* rock.c, tree.c: Do not include sys/sysmacros.h for NetBSD.
+
+Fri Dec 31 13:22:52 1993  Eric Youngdale  (eric@esp22)
+
+        * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.00.
+
+	* tree.c (scan_directory_tree): Handle case where we do not
+	have permissions to open a directory.
+
+	* write.c (xfwrite): New function - wrapper for fwrite,
+	except that we print message and punt if write fails.
+
+	* write.c: Move include of mkisofs.h and iso9660.h until after
+	string.h and stdlib.h is included.
+
+	* write.c: Do not attempt to use strerror on sun systems.
+
+Thu Dec 9  13:17:28 1993  R.-D. Marzusch (marzusch@odiehh.hanse.de)
+
+        * exclude.c, exclude.h: New files.  Contains list of files to
+	exclude from consideration.
+
+	* Makefile: Compile exclude.c, add dependencies to other files.
+
+	* mkisofs.8: Describe -x option.
+
+	* mkisofs.c: Include exclude.h, handle -x option.
+
+
+Fri Dec 10 01:07:43 1993  Peter van der Veen (peterv@qnx.com)
+ 
+ 	* mkisofs.c, mkisofs.h: Moved declaration of root_record.
+ 
+ 	* mkisofs.h: Added prototype for get_733().
+ 
+ 	* write.c(iso_write), tree.c, rock.c(generate_rock_ridge_attributes):
+ 	Added defines for QNX operation system
+ 
+ 	* rock.c(generate_rock_ridge_attributes): symbolic links should
+ 	not have CONTINUE component flag set unless there are multiple
+ 	component records, and mkisofs does not generate these.
+ 	st_ctime was stored as the creation time, changed to attribute time.
+ 	QNX has a creation time, so that is stored as well under QNX.
+ 
+Thu Oct 28 19:54:38 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.99.
+
+	* write.c(iso_write): Put hour, minute, second into date fields in
+	volume descriptor.
+
+	* write.c (iso_write): Set file_structure_version to 1, instead of
+	' ' (Seems to screw up Macs).
+
+Sun Oct 17 01:13:36 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.98.
+
+    Increment nlink in root directory when rr_moved directory is present.
+
+        * tree.c (increment_nlink): New function.
+
+	* tree.c (finish_cl_pl_entries): Call increment_nlink for all
+	references to the root directory.
+
+	* tree.c (root_statbuf): New variable.
+
+	* tree.c (scan_directory_tree): Initialize root_statbuf when we
+	stat the root directory.
+
+	* tree.c (generate_reloc_directory): Use root_statbuf when
+	generating the Rock Ridge stuff for the ".." entry in the
+	reloc_dir.
+
+	* tree.c (scan_directory_tree): Use root_statbuf when generating
+	the ".." entry in the root directory.
+
+Sat Oct 16 10:28:30 1993  Eric Youngdale  (eric@kafka)
+
+    Fix path tables so that they are sorted.
+
+	* tree.c (assign_directory_addresses): Move to write.c
+
+	* write.c (generate_path_tables): Create an array of pointers to
+	the individual directories, and sort it based upon the name and
+	the parent path table index.  Then update all of the indexes and
+	repeat the sort until the path table indexes no longer need to be
+	changed, and then write the path table.
+
+    Fix problem where hard links were throwing off the total extent count.
+
+	* write.c (iso_write): Call assign_file_addresses, and then
+	use last_extent to determine how big the volume is.
+
+	* write.c (generate_one_directory): Decrement n_data_extents
+	for hard links to non-directories so that the expected number
+	of extents is written correctly.
+
+	* write.c(assign_file_addresses): New function.
+
+Fri Oct 15 22:35:43 1993  Eric Youngdale  (eric@kafka)
+
+    The standard says we should do these things:
+
+	* tree.c (generate_reloc_directory): Add RR attributes to
+	the rr_moved directory.
+
+	* mkisofs.c(main): Change ER text strings back to recommended
+	values.
+
+Tue Oct 12 21:07:38 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.97.  
+
+	* tree.c (scan_directory_tree): Do not insert PL entry into
+	root directory record (i.e. !parent)
+
+	* tree.c (finish_cl_pl_entries): Do not rely upon name
+	comparison to locate parent - use d_entry->self instead,
+	which is guaranteed to be correct.
+
+	* mkisofs.h: New variable n_data_extents.
+
+	* tree.c: Declare and initialize n_data_extents to 0.
+	(scan_directory_tree) for non-directories, add
+	ROUND_UP(statbuf.st_size) to n_data_extents.
+	(sort_n_finish): Increment n_data_extents for translation tables,
+	as appropriate.
+
+	* write.c(iso_write): Add n_data_extents to the
+	volume_space_size field.
+
+	* hash.c(add_hash): If size != 0 and extent == 0, or
+	if size == 0 and extent != 0, then complain about
+	inserting this into the hash table.  Kind of a sanity check.
+
+Sat Oct  9 16:39:15 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.96.  
+
+	Numerous bugfixes, thanks to a one-off disc from rab@cdrom.com.
+
+	* write.c(generate_one_directory): Wait until after we have
+	filled in the starting_extent field to s_entry before calling
+	add_hash.  This fixes a problem where the hash table gets an
+	extent of 0 for all regular files, and this turns up when you have
+	hard links on the disc. (The hash table allows us to have each
+	hard link point to the same extent on the cdrom, thereby saving
+	some space).
+
+	* tree.c(scan_directory_tree): Set statbuf.st_dev and
+	statbuf.st_ino to the UNCACHED numbers for symlinks that we
+	are not following.  This prevents the function find_hash from
+	returning an inode that cooresponds to the file the symlink points
+	to, which in turn prevents generate_one_directory from filling in
+	a bogus file length (should be zero for symlinks).
+
+	* tree.c(scan_directory_tree): Always call lstat for the file
+	so that non-RockRidge discs get correct treatment of symlinks.
+	Improve error message when we ignore a symlink on a non-RR disc.
+	
+	* write.c(generate_one_directory): Set fields for starting_extent
+	and size in the "." and ".." entries before we add them to the
+	file hash.  Fixes problems with incorrect backlinks for second
+	level directories.
+
+Wed Oct  6 19:53:40 1993  Eric Youngdale  (eric@kafka)
+
+	* write.c (write_one_file): Print message and punt if we are
+	unable to open the file.
+
+	* tree.c(scan_directory_tree): For regular files, use the access
+	function to verify that the file is readable in the first place.
+	If not, issue a warning and skip it.  For directories, it probably
+	does not matter, since we would not be able to descend into them
+	in the first place.
+
+Wed Sep 29 00:02:47 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.95.
+
+	* write.c, tree.c: Cosmetic changes to printed information.
+
+        * tree.c(scan_directory_tree): Set size to zero for
+	special stub entries that correspond to the
+	relocated directories.  Hopefully last big bug.
+
+	* mkisofs.h: Change TABLE_INODE, UNCACHED_* macros
+	to be 0x7fff... to be compatible with signed datatypes.
+
+Mon Sep 27 20:14:49 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.94.
+
+	* write.c (write_path_tables): Actually search the
+	directory for the matching entry in case we renamed
+	the directory because of a name conflict.
+
+	* tree.c(scan_directory_tree): Take directory_entry pointer
+	as second argument so that we can create a backpointer
+	in the directory structure that points back to the original
+	dir.
+
+	* mkisofs.c: Fix call to scan_directory_tree to use new calling
+	sequence.
+
+	* write.c(generate_one_directory): Punt if the last_extent counter
+	ever exceeds 700Mb/2048.  Print name of responsible file,
+	extent counter, and starting extent.  Perhaps we can catch it in
+	the act.
+
+Sun Sep 26 20:58:05 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.93.
+
+	* tree.c(scan_directory_tree): Handle symlinks better.  Either
+	leave them as symlinks, or erase any trace that they were a
+	symlink but do not do it 1/2 way as before.  Also, watch for
+	directory loops created with symlinks.
+
+	* mkisofs.h: Add new flag follow_links.
+
+	* mkisofs.c: Add command line switch "-f" to toggle follow_links.
+
+	* mkisofs.8: Document new switch.
+
+	* tree.c: Add code to handle symlinks using new flag.
+
+	* hash.c: Add add_directory_hash, find_directory_hash functions.
+
+	* mkisofs.h: Add prototypes.
+
+Sat Sep 25 14:26:31 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.92.
+
+	* mkisofs.c: Make sure path is an actual directory before trying
+	to scan it.
+
+	* mkisofs.h: Add DECL and FDECL? macros for sparc like systems.
+	Do proper define of optind and optarg under SVr4.
+
+	* tree.c: Change translation table name from YMTRANS.TBL to TRANS.TBL.
+
+	* mkisofs.c: Neaten up message in extension record when RRIP is
+	in use.
+
+	* Throughout - change all function declarations so that
+	traditional C compilers (i.e. sparc) will work.
+
+	* Makefile: Change to use system default C compiler.
+
+	* mkisofs.c: Add some stuff so that this will compile under VMS.
+	Many things missing for VMS still.
+
+	* iso9660.h: Do not use zero length array in struct definition.
+
+	* tree.c (sort_n_finish): Account for this.
+
+	* Change copyright notice.
+
+
+Wed Aug 25 08:06:51 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.91.
+
+	* mkisofs.h: Only  include sys/dir.h for linux.  Other systems
+	will need other things.
+
+	* mkisofs.c,  tree.c: Include unistd.h.
+
+	* Makefile:  Use OBJS to define list of object files.
+
+Sun Aug 22 20:55:17 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.9.
+
+	* write.c (iso_7*): Fix so that they work properly  on Motorola
+	systems. 
+
+Fri Aug 20 00:14:36 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.8.
+
+	* rock.c: Do not mask off write permissions from posix file modes.
+
+Wed Aug 18 09:02:12 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.7.
+
+        *  rock.c: Do not  write  NM field  for . and .. (redundant and a
+	waste of space).
+
+	* mkisofs.c: Take -P and -p options for publisher and preparer id
+	fields.
+
+	* write.c: Store  publisher and preparer id  in  volume
+	descriptor.
+
+	* rock.c: Write  optional  SP field to identify  SUSP.  Write
+	optional CE field to point to the extension header.
+
+	* tree.c: Request  SP and  CE fields be added to root directory.
+
+        * tree.c: Fix bug in name conflict resolution.
+
+        * write.c: Fill in date fields in the  colume descriptor.
+
+        * write.c (write_one_file): If the file is large enough, write  in
+	chunks of 16 sectors to improve performance.
+
+	* hash.c (add_hash, find_hash, etc): Do  not hash s_entry, instead
+	store relevant info in hash structure (we free s_entry  structs as
+	we write files, and we need to have access to the hash table  the
+	whole  way through.
+
+	* write.c: Add a few statistics about directory sizes, RR sizes,
+	translation table sizes, etc.
+
+	* tree.c: Use major, not MAJOR.  Same for minor.  Define S_ISSOCK
+	and S_ISLNK if not defined.
+
+	* rock.c: Define S_ISLNK if not defined.
+
+	* mkisofs.c: Print out max memory usage.  Fix bug in call to getopt.
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.6.
+
+	* tree.c: Simplify the calculation of isorec.len,  isorec.name_len
+	and the calculation of the path table sizes by doing it all at
+	one point after  conflict resolution is done.
+
+	* tree.c: scan_directory_tree is now  responsible for generating
+	the line that goes into the YMTRANS.TBL file.  These lines are
+	collected later  on into something that will be dumped to the
+	file. Correctly handle all of the special file types.
+
+Mon Aug 16 21:59:47 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.5.
+
+	* mkisofs.c: Add -a option  (to force all files to be
+	transferred).  Remove find_file_hash stuff.
+
+	* write.c: Pad length even if Rock Ridge is not in use.
+
+	* hash.c: Rewrite hash_file_* stuff so that it  can be used to
+	easily  detect (and look up) filenames that have been  accepted
+	for use  in this directory.  Used for name collision detection.
+
+	* tree.c (sort_n_finish): If two names collide, generate a unique
+	one (verified with the hash routines).  Change the lower priority
+	name if there is a difference.
+
+
+
+Sat Aug 14 13:18:21 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.4.
+
+	* tree.c (load_translation_table): New  function - read
+	YMTRANS.TBL.  (scan_directory_tree) Call it.
+
+	* mkisofs.c (iso9660_file_length): Call find_file_hash to see
+	if translated name is specified.  If so, use it.
+
+	* hash.c (name_hash, add_file_hash, find_file_hash,
+	flush_file_hash): New functions for hashing stuff from
+	YMTRANS.TBL.
+
+	* mkisofs.h: Add a bunch of prototypes for the new functions.
+
+	* mkisofs.8: Update.
+
+        * mkisofs.c, Makefile (version_string): Bump to 0.3.
+
+        * Makefile: Add version number to tar file in dist target.
+
+	* mkisofs.c: Call finish_cl_pl_entries() after directories have
+	been generated, and extent numbers assigned.
+
+	* write.c (generate_one_directory): Update s_entry->size  for
+	directories (as well as isorec.size).
+
+	* rock.c:  Add  code to generate CL, PL, and RE entries.  The
+	extent numbers for the CL and PL  entries are  NULL, and these
+	are filled in  later once we know where they actually belong.
+
+	* mkisofs.h: Add parent_rec to directory_entry.  Used to fix CL/PL
+	stuff.
+
+	* tree.c (scan_directory_tree): Set  flag to generate  CL/PL/RE
+	entries  as required, update sizes as well.
+
+Fri Aug 13 19:49:30 1993  Eric Youngdale  (eric@kafka)
+
+        * mkisofs.c (version_string): Bump to 0.2.
+
+	* hash.c: Do not use entries with inode  == 0xffffffff or dev  ==
+	0xffff.
+
+	* write.c (write_path_tables):  Strip leading directory specifications.
+
+	* mkisofs.h: Add  definition for reloc_dir symbol.  Add prototype
+	for sort_n_finish, add  third parameter  to  scan_directory_tree
+	(for true parent, when directories are relocated).
+
+	* mkisofs.c (main): Modify call to scan_directory_tree.  Call
+	sort_n_finish for reloc_dir.
+
+	* tree.c (sort_n_finish): New function - moved code from
+	scan_directory_tree. 
+
+	* tree.c (generate_reloc_directory): New function.  Generate
+	directory to hold relocated directories.
+
+	* tree.c (scan_directory_tree): Strip leading directories when
+	generating this_dir->name.  If depth is  too great,  then move
+	directory to reloc_dir (creating if it does not exist, and leave
+	a dummy (non-directory) entry  in the regular directory  so that
+	we can eventually add the required Rock Ridge record.
+
+	* tree.c (scan_directory_tree): Use s_entry instead of sort_dir,
+	assign to this_dir->contents sooner.
+
+Thu Aug 12 22:38:17 1993  Eric Youngdale  (eric@kafka)
+
+	* mkisofs.c (usage): Fix syntax.
+
+	* mkisofs.c (main): Add new argument to scan_directory_tree
+
+	* tree.c (scan_directory_tree): If directory is at  depth 8 or
+	more, create rr_moved directory in main directory.
+
+Mon Jul 26 19:45:47 1993  Eric Youngdale  (eric@kafka)
+
+	* mkisofs v 0.1 released.
+
diff --git a/mass_storage/mkisofs-1.11.3/Makefile b/mass_storage/mkisofs-1.11.3/Makefile
new file mode 100644
index 0000000..1af9946
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/Makefile
@@ -0,0 +1,112 @@
+# Generated automatically from Makefile.in by configure.
+#
+# $Id: Makefile.in,v 1.7 1997/04/10 03:31:17 eric Rel $
+#
+## Makefile for mkisofs.
+
+#### Start of system configuration section. ####
+
+srcdir = .
+
+CC = gcc
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+
+LIBS = 
+
+prefix = /usr/local
+exec_prefix = $(prefix)
+
+bindir = $(exec_prefix)/bin
+
+# Where to put the manual pages.
+mandir = $(prefix)/man/man8
+# Extension (not including `.') for the manual page filenames.
+manext = 8
+
+#### End of system configuration section. ####
+
+CFLAGS=-g -O2 -I.
+LDFLAGS=
+OBJS=mkisofs.o tree.o write.o hash.o rock.o exclude.o multi.o \
+		files.o match.o name.o fnmatch.o eltorito.o
+
+World: mkisofs
+
+Makefile: Makefile.in config.status
+	CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
+
+config.status: configure
+	$(SHELL) config.status --recheck
+
+configure:  configure.in
+	cd $(srcdir) && autoconf
+
+mkisofs: Makefile $(OBJS) 
+	$(CC) $(LDFLAGS) -o mkisofs  $(OBJS)
+
+install: mkisofs mkisofs.8
+	[ -d $(bindir) ] || mkdir $(bindir)
+	[ -d $(mandir) ] || mkdir $(mandir)
+	$(INSTALL_PROGRAM) mkisofs $(bindir)/mkisofs
+	-$(INSTALL_DATA) $(srcdir)/mkisofs.8 $(mandir)/mkisofs.$(manext)
+
+tree.o: tree.c mkisofs.h iso9660.h exclude.h config.h Makefile
+	$(CC) -c $(CFLAGS) tree.c
+
+write.o: write.c mkisofs.h iso9660.h config.h Makefile
+	$(CC) -c $(CFLAGS) write.c
+
+hash.o: hash.c mkisofs.h  config.h Makefile
+	$(CC) -c $(CFLAGS) hash.c
+
+rock.o: rock.c mkisofs.h iso9660.h config.h Makefile
+	$(CC) -c $(CFLAGS) rock.c
+
+exclude.o: exclude.c exclude.h config.h Makefile
+	$(CC) -c $(CFLAGS) exclude.c
+
+match.o: match.c match.h config.h Makefile
+	$(CC) -c $(CFLAGS) match.c
+
+files.o: files.c iso9660.h mkisofs.h config.h Makefile
+	$(CC) -c $(CFLAGS) files.c
+
+fnmatch.o: fnmatch.c fnmatch.h config.h Makefile
+	$(CC) -c $(CFLAGS) fnmatch.c
+
+multi.o: multi.c iso9660.h mkisofs.h config.h Makefile
+	$(CC) -c $(CFLAGS) multi.c
+
+name.o: name.c iso9660.h mkisofs.h config.h Makefile
+	$(CC) -c $(CFLAGS) name.c
+
+mkisofs.o: mkisofs.c iso9660.h mkisofs.h exclude.h config.h Makefile
+	$(CC) -c $(CFLAGS) mkisofs.c
+
+eltorito.o: eltorito.c iso9660.h mkisofs.h config.h Makefile
+	$(CC) -c $(CFLAGS) eltorito.c
+
+clean:
+	/bin/rm -f *.o core mkisofs *~ #*#
+	/bin/rm -f config.status config.log config.cache config.h
+	(cd diag/; make clean)
+
+#
+# All .h files except for config.h get copied.
+#
+dist:   Makefile
+	(mydir=`basename \`pwd\``;\
+	cd .. && tar -cvvf - $$mydir/README $$mydir/README.eltorito \
+	$$mydir/configure.in $$mydir/configure $$mydir/config.h.in \
+	$$mydir/Makefile.in  $$mydir/make.com $$mydir/TODO \
+	$$mydir/COPYING $$mydir/ChangeLog $$mydir/*.8 $$mydir/*.c \
+	$$mydir/mkisofs.spec $$mydir/acconfig.h \
+	$$mydir/install-sh $$mydir/[d-z]*.h \
+	$$mydir/cdwrite.c.diff $$mydir/README.session $$mydir/diag/Makefile.in \
+	$$mydir/diag/README $$mydir/diag/*.c $$mydir/diag/isoinfo.8 \
+	| gzip -9 > $${mydir}.tar.gz)
+
+
diff --git a/mass_storage/mkisofs-1.11.3/README b/mass_storage/mkisofs-1.11.3/README
new file mode 100644
index 0000000..b1ed90f
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/README
@@ -0,0 +1,124 @@
+#	$Id: README,v 1.2 1997/02/23 15:42:18 eric Rel $	
+Note:
+	There is a feature which can be optionally compiled into
+mkisofs that allows you to merge arbitrary directory trees into the
+image you are creating.  You need to compile with -DADD_FILES for my
+changes to take effect.   Thanks to Ross Biro biro@yggdrasil.com.
+
+	This program requires a lot of virtual memory to run since it
+builds all of the directories in memory.  The exact requirements
+depend upon a lot of things, but for Rock Ridge discs 12Mb would not
+be unreasonable.  Without RockRidge and without the translation
+tables, the requirements would be considerably less.
+
+	The cdwrite utility is maintained separately from mkisofs by
+yggdrasil.com.  It is enclosed here as a convenience, since the two programs
+are often useful together.  
+
+*****************************
+Notes for version 1.10b1
+
+	Big news is that multi-session capability is very close to being
+	done.  There is still a missing interface to cdwrite that is
+	used to determine the next writable address and the sector number
+	of the last existing session.  Until we get the interface to cdwrite
+	done, this is a beta version.
+
+	Bug involving DST fixed (dates are always calculated, since some
+	files may be DST and other ones would not be).
+
+	Unfortunately the notes on some of the small patches got lost.
+
+*****************************
+Notes for version 1.06
+
+	Jan-Piet Mens <jpm@mens.de> added support for the '-m' switch. This
+	allows exclusion of shell-style globs from the CDROM.
+	See manual mkisofs.8 for more information.
+
+*****************************
+Notes for version 1.05
+
+	Added support for '-r' switch.  This is very similar to -R for
+Rock Ridge, but echos of the development environment are removed
+(i.e. uid/gid set to 0, and permissions of the files are canonicalized).
+Useful in applications where a distribution medium is being produced.
+
+*****************************
+Notes for version 1.04
+
+	No notes for 1.04.
+
+*****************************
+Notes for version 1.03
+
+	No notes for 1.03.
+
+*****************************
+Notes for version 1.02.
+
+	Minor bugfixes here and there.  Support for compiled in
+defaults for many of the text fields in the volume header are now
+present, and there is also support for a file ".mkisofsrc" that can
+also read settings for these parameters.
+
+	A short script "Configure" was added to allow us to set up special
+compile options that depend upon the system that we are running on.
+This should help stamp out the sphaghetti-isms that were starting to grow
+up in various places in the code.
+
+	You should get more meaningful error messages if you run out of
+memory.
+
+*****************************
+Notes for version 1.1.
+
+	The big news is that SUSP CE entries are now generated for
+extremely long filenames and symlink names.  This virtually guarantees
+that there is no limit (OK, well, about 600Mb) for file name lengths.
+I have tested this as well as I can, and it seems to work with linux.
+This would only be used very rarely I suspect.
+
+	Also, I believe that support for VMS is done.  You must be
+careful, because only Stream-LF and FIxed length record files can be
+recorded.  The rest are rejected with error messages.  Perhaps I am
+being too severe here.
+
+	There is a bugfix in the sorting of entries on the disc - we
+need to stop comparing once we reach the ';' character.
+
+	There are four new options -z -d -D -l -V.  Some of these tell
+mkisofs to relax some of the iso9660 restrictions, and many systems
+apparently do not really seem to mind.  Use these with caution.
+
+	Some diagnostic programs to scan disc images are in the diag
+directory.  These are not as portable as mkisofs, and may have some
+bugs.  Still they are useful because they can check for bugs that I might
+have introduced as I add new features.
+
+*****************************
+Notes for version 1.0.
+
+	In version 1.0, the date fields in the TF fields were fixed -
+previously I was storing st_ctime as the file creation time instead of
+the file attribute change time.  Thanks to Peter van der Veen for
+pointing this out.  I have one slight concern with this change,
+however.  The Young Minds software is definitely supplying 3 dates
+(creation, modification and access), and I would strongly suspect that
+they are incorrectly putting the file attribute change time in the
+file creation slot.  I would be curious to see how the different RRIP
+filesystems treat this.  Anyway, this is something to keep in the back
+of your mind.
+
+	The symlink handling was not quite correct in 0.99 - this is
+now fixed.  Only some systems seemed to have been affected by this bug.
+
+	A command line option is now present to allow you to
+specifically exclude certain files from the distribution.
+
+	The case where you do not have permissions to read a directory
+is now handled better by mkisofs.  The directory that cannot be opened
+is converted into a zero-length file, and processing continues normally.
+
+	A few portability things have been fixed (hopefully).
+
diff --git a/mass_storage/mkisofs-1.11.3/README.eltorito b/mass_storage/mkisofs-1.11.3/README.eltorito
new file mode 100644
index 0000000..9c1e363
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/README.eltorito
@@ -0,0 +1,97 @@
+#	$Id: README.eltorito,v 1.2 1997/02/23 15:44:59 eric Rel $	
+What is El Torito?
+------------------
+Simply put, El Torito is a specification that says how a cdrom should
+be formatted such that you can directly boot from it.
+
+The "El Torito" spec says that ANY cdrom drive should work (scsi/eide)
+as long as the BIOS supports El Torito. So far this has only been
+tested with EIDE drives because none of the scsi controllers that has
+been tested so far appears to support El Torito. The motherboard
+definately has to support El Torito. The ones that do let you choose
+booting from HD, Floppy, Network or CDROM.
+
+How To Make Bootable CDs
+------------------------
+
+For the x86 platform, many BIOS's have begun to support bootable CDs.
+The standard my patches for mkisofs is based on is called "El Torito".
+
+The "El Torito" standard works by making the CD drive appear, through BIOS
+calls, to be a normal floppy drive. This way you simply put an floppy
+size image (exactly 1440k for a 1.44 meg floppy) somewhere in the
+iso fs. In the headers of the iso fs you place a pointer to this image.
+The BIOS will then grab this image from the CD and for all purposes it
+acts as if it were booting from the floppy drive. This allows a working
+LILO boot disk, for example, to simply be used as is.
+
+It is simple then to make a bootable CD. First create a file, say "boot.img"
+which is an exact image of the boot floppu currently in use. There is
+at least one HOWTO on making bootable floppies. If you have a bootable
+floppy handy, you can make a boot image with the command
+
+dd if=/dev/fd0 of=boot.img bs=10k count=144
+
+assuming the floppy is in the A: drive.
+
+Place this image somewhere in the hierarchy which will be the source
+for the iso9660 filesystem. It is a good idea to put all boot related
+files in their own directory ("boot/" under the root of the iso9660 fs,
+for example), but this is not necessary.
+
+One caveat - Your boot floppy MUST load any initial ramdisk via LILO,
+not the kernel ramdisk driver! This is because once the linux kernel
+starts up, the BIOS emulation of the CD as a floppy disk is circumvented
+and will fail miserably. LILO will load the initial ramdisk using BIOS
+disk calls, so the emulation works as designed.
+
+The "El Torito" specification requires a "boot catalog" to be created as 
+ll.
+This is a 2048 byte file which is of no interest except it is required.
+My patches to mkisofs will cause it to automatically create the
+boot catalog. You must specify where the boot catalog will go in the
+iso9660 filesystem. Usually it is a good idea to put it the same place
+as the boot image, and a name like "boot.catalog" seems appropriate.
+
+
+So we have our boot image in the file "boot.image", and we are going to
+put it in the directory "boot/" under the root of the iso9660 filesystem.
+We will have the boot catalog go in the same directory with the name
+"boot.catalog". The command to create the iso9660 fs in the file
+bootcd.iso is then
+
+mkisofs -b boot/boot.imh -c boot/boot.catalog -o bootcd.iso .
+
+The -b option specifies the boot image to be used (note the path is
+relative to the root of the iso9660 disc), and the -c option is
+for the boot catalog file.
+
+Now burn the CD and its ready to boot!
+
+CAVEATS
+-------
+
+I don't think this will work with multisession CDs.
+
+If your bootable floppy image needs to access the boot floppy, it has
+to do so through BIOS calls. This is because if your O/S tries to talk to
+the floppy directly it will bypass the "floppy emulation" the El Torito spec
+creates through BIOS. For example, under Linux it is possible to
+have an initial RAM disk loaded when the kernel starts up. If you let the
+kernel try to read in the initial RAM disk from floppy, it will fail
+miserably because Linux is not using BIOS calls to access the floppy drive.
+Instead of seeing the floppy image on the CD, Linux will be looking at
+the actually floppy drive.
+
+The solution is to have the initial boot loader, called LILO, load your
+initial RAM disk for you.  LILO uses BIOS calls entirely for these
+operations, so it can grab it from the emulated floppy image.
+
+I don't think making a CD bootable renders it unreadable by non-El Torito
+machines. The El Torito spec uses parts of the iso9660 filesystem which
+were reserved for future use, so no existing code should care what it does.
+
+Mkisofs currently stores identification records in the iso9660 filesystem
+saying that the system is a x86 system. The El Torito spec also allows
+one to write PowerPC or Mac id's instead. If you look at the code in write.c
+you could figure out how to change what is written.
diff --git a/mass_storage/mkisofs-1.11.3/README.session b/mass_storage/mkisofs-1.11.3/README.session
new file mode 100644
index 0000000..2b305ff
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/README.session
@@ -0,0 +1,41 @@
+#	$Id: README.session,v 1.2 1997/02/23 15:45:50 eric Rel $	
+
+	This release of mkisofs has basic support completed for
+multiple sessions.  At this point, it hasn't been tested thoroughly at all -
+we still need some interaction between cdwrite and mkisofs for this to work
+correctly.
+
+	There are a few new options to mkisofs to allow for this.
+The first one is "-M /dev/scd0", and is used so that mkisofs can examine
+the entirety of the previous image so that it can figure out what additional
+files need to be written in the new session.
+
+	There is also a temporary hack in mkisofs in the form of a '-C' option.
+The -C option takes two numbers as input, which are delimited by commas.
+For example, you could specify "-C 1000,1020", but you should never just
+make up numbers to use here.  These numbers are determined from cdwrite.
+
+	There are patches to cdwrite in the file cdwrite.c.diff, which add
+a new information gathering option.  To use this, you specify '-m', and
+instead of actually writing any data, cdwrite dumps two numbers to stdout
+which are comma delimited.  These are the same numbers that mkisofs uses
+with the -C option.
+
+	Thus in practice you should in principle be able to do something like:
+
+mkisofs [other options] -C `cdwrite --device /dev/sgX --multi` \
+		-M /dev/cdblkdev
+
+to tie these things together.  Admittedly this is a very crude
+interface between the two programs right now, and this will be cleaned
+up later.  For now, it provides the minimal functionality required to write
+multiple session discs.
+
+Note: As of the 1.10b4 release, nobody has actually tried to burn any
+discs with this.  It is entirely possible that bugs exists, or that
+further tweaks will be required somewhere along the way to get things
+working correctly.  The data gathering mode of cdwrite has been
+tested, and I believe it works correctly.  Caveat Emptor.
+
+[Nov 4, 1996].
+
diff --git a/mass_storage/mkisofs-1.11.3/acconfig.h b/mass_storage/mkisofs-1.11.3/acconfig.h
new file mode 100644
index 0000000..331d08d
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/acconfig.h
@@ -0,0 +1,7 @@
+/* Definitions for mkisofs processed by autoheader. */
+
+#undef NODIR                    /* none -- don't make numbered backup files */
+
+/* This shows us where to find the major()/minor() macros */
+#undef MAJOR_IN_MKDEV
+#undef MAJOR_IN_SYSMACROS
diff --git a/mass_storage/mkisofs-1.11.3/config.h b/mass_storage/mkisofs-1.11.3/config.h
new file mode 100644
index 0000000..3bd37b3
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/config.h
@@ -0,0 +1,53 @@
+/* config.h.  Generated automatically by configure.  */
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define to empty if the keyword does not work.  */
+/* #undef const */
+
+/* Define if major, minor, and makedev are declared in <mkdev.h>.  */
+/* #undef MAJOR_IN_MKDEV */
+
+/* Define if major, minor, and makedev are declared in <sysmacros.h>.  */
+/* #undef MAJOR_IN_SYSMACROS */
+
+/* #undef NODIR */                    /* none -- don't make numbered backup files */
+
+/* This shows us where to find the major()/minor() macros */
+/* #undef MAJOR_IN_MKDEV */
+/* #undef MAJOR_IN_SYSMACROS */
+
+/* Define if you have the memmove function.  */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the sbrk function.  */
+#define HAVE_SBRK 1
+
+/* Define if you have the <dirent.h> header file.  */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <malloc.h> header file.  */
+#define HAVE_MALLOC_H 1
+
+/* Define if you have the <ndir.h> header file.  */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <sys/dir.h> header file.  */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/mkdev.h> header file.  */
+/* #undef HAVE_SYS_MKDEV_H */
+
+/* Define if you have the <sys/ndir.h> header file.  */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/sysmacros.h> header file.  */
+#define HAVE_SYS_SYSMACROS_H 1
+
+/* Define if you have the <sys/types.h> header file.  */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <termios.h> header file.  */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <unistd.h> header file.  */
+#define HAVE_UNISTD_H 1
diff --git a/mass_storage/mkisofs-1.11.3/defaults.h b/mass_storage/mkisofs-1.11.3/defaults.h
new file mode 100644
index 0000000..91e6789
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/defaults.h
@@ -0,0 +1,44 @@
+/*
+ * Header file defaults.h - assorted default values for character strings in
+ * the volume descriptor.
+ *
+ * 	$Id: defaults.h,v 1.4 1997/04/10 03:31:53 eric Rel $
+ */
+
+#define  PREPARER_DEFAULT 	NULL
+#define  PUBLISHER_DEFAULT	NULL
+#define  APPID_DEFAULT 		NULL
+#define  COPYRIGHT_DEFAULT 	NULL
+#define  BIBLIO_DEFAULT 	NULL
+#define  ABSTRACT_DEFAULT 	NULL
+#define  VOLSET_ID_DEFAULT 	NULL
+#define  VOLUME_ID_DEFAULT 	"CDROM"
+#define  BOOT_CATALOG_DEFAULT   "boot.catalog"
+#define  BOOT_IMAGE_DEFAULT     NULL
+#ifdef __QNX__
+#define  SYSTEM_ID_DEFAULT 	"QNX"
+#endif
+
+#ifdef __osf__
+#define  SYSTEM_ID_DEFAULT 	"OSF"
+#endif
+
+#ifdef __sun
+#define  SYSTEM_ID_DEFAULT 	"Solaris"
+#endif
+
+#ifdef __hpux
+#define  SYSTEM_ID_DEFAULT 	"HP-UX"
+#endif
+
+#ifdef __sgi
+#define  SYSTEM_ID_DEFAULT 	"SGI"
+#endif
+
+#ifdef _AIX
+#define  SYSTEM_ID_DEFAULT 	"AIX"
+#endif
+
+#ifndef SYSTEM_ID_DEFAULT
+#define  SYSTEM_ID_DEFAULT 	"LINUX"
+#endif
diff --git a/mass_storage/mkisofs-1.11.3/dir.h b/mass_storage/mkisofs-1.11.3/dir.h
new file mode 100644
index 0000000..31a56f3
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/dir.h
@@ -0,0 +1,27 @@
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef	_SYS_DIR_H
+#define	_SYS_DIR_H	1
+
+#include <features.h>
+
+#include <dirent.h>
+
+#define	direct	dirent
+
+#endif	/* sys/dir.h  */
diff --git a/mass_storage/mkisofs-1.11.3/eltorito.c b/mass_storage/mkisofs-1.11.3/eltorito.c
new file mode 100644
index 0000000..0ac5a12
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/eltorito.c
@@ -0,0 +1,265 @@
+/*
+ * Program eltorito.c - Handle El Torito specific extensions to iso9660.
+ * 
+
+   Written by Michael Fulbright <msf@redhat.com> (1996).
+
+   Copyright 1996 RedHat Software, Incorporated
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */
+
+
+static char rcsid[] ="$Id: eltorito.c,v 1.7 1997/05/17 15:44:31 eric Exp $";
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include "mkisofs.h"
+#include "iso9660.h"
+
+#undef MIN
+#define MIN(a, b) (((a) < (b))? (a): (b))
+
+static struct eltorito_validation_entry valid_desc;
+static struct eltorito_defaultboot_entry default_desc;
+
+/*
+ * Check for presence of boot catalog. If it does not exist then make it 
+ */
+void FDECL1(init_boot_catalog, const char *, path)
+{
+
+    int		  bcat;
+    char		* bootpath;                /* filename of boot catalog */
+    char		* buf;
+    struct stat	  statbuf;
+    
+    bootpath = (char *) e_malloc(strlen(boot_catalog)+strlen(path)+2);
+    strcpy(bootpath, path);
+    if (bootpath[strlen(bootpath)-1] != '/') 
+    {
+	strcat(bootpath,"/");
+    }
+    
+    strcat(bootpath, boot_catalog);
+    
+    /*
+     * check for the file existing 
+     */
+#ifdef DEBUG_TORITO
+    printf("Looking for boot catalog file %s\n",bootpath);
+#endif
+    
+    if (!stat_filter(bootpath, &statbuf)) 
+    {
+	/*
+	 * make sure its big enough to hold what we want 
+	 */
+	if (statbuf.st_size == 2048) 
+	{
+	    /*
+	     * printf("Boot catalog exists, so we do nothing\n"); 
+	     */
+	    free(bootpath);
+	    return;
+	}
+	else 
+	{
+	    fprintf(stderr, "A boot catalog exists and appears corrupted.\n");
+	    fprintf(stderr, "Please check the following file: %s.\n",bootpath);
+	    fprintf(stderr, "This file must be removed before a bootable CD can be done.\n");
+	    free(bootpath);
+	    exit(1);
+	}
+    }
+    
+    /*
+     * file does not exist, so we create it 
+     * make it one CD sector long
+     */
+    bcat = open(bootpath, O_WRONLY | O_CREAT, S_IROTH | S_IRGRP | S_IRWXU );
+    if (bcat == -1) 
+    {
+	fprintf(stderr, "Error creating boot catalog, exiting...\n");
+	perror("");
+	exit(1);
+    }
+    
+    buf = (char *) e_malloc( 2048 );
+    write(bcat, buf, 2048);
+    close(bcat);
+    free(bootpath);
+} /* init_boot_catalog(... */
+
+void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
+{
+    int				bootcat;
+    int				checksum;
+    unsigned char		      * checksum_ptr;
+    struct directory_entry      * de;
+    struct directory_entry      * de2;
+    int				i;
+    int				nsectors;
+    
+    memset(boot_desc, 0, sizeof(*boot_desc));
+    boot_desc->id[0] = 0;
+    memcpy(boot_desc->id2, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
+    boot_desc->version[0] = 1;
+    
+    memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof(EL_TORITO_ID));
+    
+    /*
+     * search from root of iso fs to find boot catalog 
+     */
+    de2 = search_tree_file(root, boot_catalog);
+    if (!de2) 
+    {
+	fprintf(stderr,"Uh oh, I cant find the boot catalog!\n");
+	exit(1);
+    }
+    
+    set_731(boot_desc->bootcat_ptr,
+	    (unsigned int) get_733(de2->isorec.extent));
+    
+    /* 
+     * now adjust boot catalog
+     * lets find boot image first 
+     */
+    de=search_tree_file(root, boot_image);
+    if (!de) 
+    {
+	fprintf(stderr,"Uh oh, I cant find the boot image!\n");
+	exit(1);
+    } 
+    
+    /* 
+     * we have the boot image, so write boot catalog information
+     * Next we write out the primary descriptor for the disc 
+     */
+    memset(&valid_desc, 0, sizeof(valid_desc));
+    valid_desc.headerid[0] = 1;
+    valid_desc.arch[0] = EL_TORITO_ARCH_x86;
+    
+    /*
+     * we'll shove start of publisher id into id field, may get truncated
+     * but who really reads this stuff!
+     */
+    if (publisher)
+        memcpy_max(valid_desc.id,  publisher, MIN(23, strlen(publisher)));
+    
+    valid_desc.key1[0] = 0x55;
+    valid_desc.key2[0] = 0xAA;
+    
+    /*
+     * compute the checksum 
+     */
+    checksum=0;
+    checksum_ptr = (unsigned char *) &valid_desc;
+    for (i=0; i<sizeof(valid_desc); i+=2) 
+    {
+	/*
+	 * skip adding in ckecksum word, since we dont have it yet! 
+	 */
+	if (i == 28)
+	{
+	    continue;
+	}
+	checksum += (unsigned int)checksum_ptr[i];
+	checksum += ((unsigned int)checksum_ptr[i+1])*256;
+    }
+    
+    /* 
+     * now find out the real checksum 
+     */
+    checksum = -checksum;
+    set_721(valid_desc.cksum, (unsigned int) checksum);
+    
+    /*
+     * now make the initial/default entry for boot catalog 
+     */
+    memset(&default_desc, 0, sizeof(default_desc));
+    default_desc.boot_id[0] = EL_TORITO_BOOTABLE;
+    
+    /*
+     * use default BIOS loadpnt
+     */ 
+    set_721(default_desc.loadseg, 0);
+    default_desc.arch[0] = EL_TORITO_ARCH_x86;
+    
+    /*
+     * figure out size of boot image in sectors, for now hard code to
+     * assume 512 bytes/sector on a bootable floppy
+     */
+    nsectors = ((de->size + 511) & ~(511))/512;
+    printf("\nSize of boot image is %d sectors -> ", nsectors); 
+    
+    /*
+     * choose size of emulated floppy based on boot image size 
+     */
+    if (nsectors == 2880 ) 
+    {
+	default_desc.boot_media[0] = EL_TORITO_MEDIA_144FLOP;
+	printf("Emulating a 1.44 meg floppy\n");
+    }
+    else if (nsectors == 5760 ) 
+    {
+	default_desc.boot_media[0] = EL_TORITO_MEDIA_288FLOP;
+	printf("Emulating a 2.88 meg floppy\n");
+    }
+    else if (nsectors == 2400 ) 
+    {
+	default_desc.boot_media[0] = EL_TORITO_MEDIA_12FLOP;
+	printf("Emulating a 1.2 meg floppy\n");
+    }
+    else 
+    {
+	fprintf(stderr,"\nError - boot image is not the an allowable size.\n");
+	exit(1);
+    }
+    
+    
+    /* 
+     * FOR NOW LOAD 1 SECTOR, JUST LIKE FLOPPY BOOT!!! 
+     */
+    nsectors = 1;
+    set_721(default_desc.nsect, (unsigned int) nsectors );
+#ifdef DEBUG_TORITO
+    printf("Extent of boot images is %d\n",get_733(de->isorec.extent));
+#endif
+    set_731(default_desc.bootoff, 
+	    (unsigned int) get_733(de->isorec.extent));
+    
+    /*
+     * now write it to disk 
+     */
+    bootcat = open(de2->whole_name, O_RDWR);
+    if (bootcat == -1) 
+    {
+	fprintf(stderr,"Error opening boot catalog for update.\n");
+	perror("");
+	exit(1);
+    }
+    
+    /* 
+     * write out 
+     */
+    write(bootcat, &valid_desc, 32);
+    write(bootcat, &default_desc, 32);
+    close(bootcat);
+} /* get_torito_desc(... */
diff --git a/mass_storage/mkisofs-1.11.3/exclude.c b/mass_storage/mkisofs-1.11.3/exclude.c
new file mode 100644
index 0000000..56fb8de
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/exclude.c
@@ -0,0 +1,56 @@
+/*
+ * 9-Dec-93 R.-D. Marzusch, marzusch@odiehh.hanse.de:
+ * added 'exclude' option (-x) to specify pathnames NOT to be included in 
+ * CD image.
+ */
+
+static char rcsid[] ="$Id: exclude.c,v 1.2 1997/02/23 16:12:34 eric Rel $";
+
+#include <stdio.h>
+#ifndef VMS
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+#endif
+#include <string.h>
+
+/* this allows for 1000 entries to be excluded ... */
+#define MAXEXCL 1000
+static char * excl[MAXEXCL];
+
+void exclude(fn)
+char * fn;
+{
+  register int i;
+
+  for (i=0; excl[i] && i<MAXEXCL; i++);
+  if (i == MAXEXCL) {
+    fprintf(stderr,"Can't exclude '%s' - too many entries in table\n",fn);
+    return;
+  }
+
+ 
+  excl[i] = (char *) malloc(strlen(fn)+1);
+  if (! excl[i]) {
+    fprintf(stderr,"Can't allocate memory for excluded filename\n");
+    return;
+  }
+
+  strcpy(excl[i],fn);
+}
+
+int is_excluded(fn)
+char * fn;
+{
+  /* very dumb search method ... */
+  register int i;
+
+  for (i=0; excl[i] && i<MAXEXCL; i++) {
+    if (strcmp(excl[i],fn) == 0) {
+      return 1; /* found -> excluded filenmae */
+    }
+  }
+  return 0; /* not found -> not excluded */
+}
diff --git a/mass_storage/mkisofs-1.11.3/exclude.h b/mass_storage/mkisofs-1.11.3/exclude.h
new file mode 100644
index 0000000..b9581a9
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/exclude.h
@@ -0,0 +1,10 @@
+/*
+ * 9-Dec-93 R.-D. Marzusch, marzusch@odiehh.hanse.de:
+ * added 'exclude' option (-x) to specify pathnames NOT to be included in 
+ * CD image.
+ *
+ * 	$Id: exclude.h,v 1.1 1997/02/23 15:53:19 eric Rel $
+ */
+
+void exclude();
+int is_excluded();
diff --git a/mass_storage/mkisofs-1.11.3/files.c b/mass_storage/mkisofs-1.11.3/files.c
new file mode 100644
index 0000000..2871b45
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/files.c
@@ -0,0 +1,362 @@
+/*
+ * File files.c - Handle ADD_FILES related stuff.
+
+   Written by Eric Youngdale (1993).
+
+   Copyright 1993 Yggdrasil Computing, Incorporated
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */
+
+static char rcsid[] ="$Id: files.c,v 1.5 1997/04/10 03:32:24 eric Rel $";
+
+#include <errno.h>
+#include "mkisofs.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+
+#ifdef ADD_FILES
+
+struct file_adds {
+  char *name;
+  struct file_adds *child;
+  struct file_adds *next;
+  int add_count;
+  int used;
+  union diru {
+	/*
+	 * XXX Struct dirent is not guaranteed to be any size on a POSIX
+	 * XXX compliant system.
+	 * XXX We need to allocate enough space here, to allow the hacky
+	 * XXX code in tree.c made by Ross Biro biro@yggdrasil.com
+	 * XXX to work on operating systems other than Linux :-(
+	 * XXX Changes made by Joerg Schilling joerg@schily.isdn.cs.tu-berlin.de
+	 * XXX to prevent core dumps on Solaris.
+	 * XXX Space allocated:
+	 * XXX		1024 bytes == NAME_MAX
+	 * XXX	+	2   bytes for directory record length 
+	 * XXX	+	2*8 bytes for inode number & offset (64 for future exp)
+	 */
+  	struct dirent	de;
+  	char		dspace[NAME_MAX+2+2*8];
+  } du;
+  struct {
+    char *path;
+    char *name;
+  } *adds;
+};
+extern struct file_adds *root_file_adds;
+
+/*
+ * FIXME(eric) - the file adding code really doesn't work very well
+ * at all.  We should differentiate between adding directories, and adding
+ * single files, as adding a full directory affects how we should be
+ * searching for things.  Ideally what we should do is make two passes
+ * through the local filesystem - one to figure out what trees we need
+ * to scan (and merge in any additions at that point), and the second to
+ * actually fill out each structure with the appropriate contents.
+ *
+ * 
+ */
+
+struct file_adds *root_file_adds = NULL;
+
+void
+FDECL2(add_one_file, char *, addpath, char *, path )
+{
+  char *cp;
+  char *name;
+  struct file_adds *f;
+  struct file_adds *tmp;
+
+  f = root_file_adds;
+  tmp = NULL;
+
+  name = strrchr (addpath, PATH_SEPARATOR);
+  if (name == NULL) {
+    name = addpath;
+  } else {
+    name++;
+  }
+
+  cp = strtok (addpath, SPATH_SEPARATOR);
+
+  while (cp != NULL && strcmp (name, cp)) {
+     if (f == NULL) {
+        root_file_adds = e_malloc (sizeof *root_file_adds);
+        f=root_file_adds;
+        f->name = NULL;
+        f->child = NULL;
+        f->next = NULL;
+        f->add_count = 0;
+        f->adds = NULL;
+	f->used = 0;
+     }
+    if (f->child) {
+      for (tmp = f->child; tmp->next != NULL; tmp =tmp->next) {
+         if (strcmp (tmp->name, cp) == 0) {
+           f = tmp;
+           goto next;
+         }
+      }
+      if (strcmp (tmp->name, cp) == 0) {
+          f=tmp;
+          goto next;
+      }
+      /* add a new node. */
+      tmp->next = e_malloc (sizeof (*tmp->next));
+      f=tmp->next;
+      f->name = strdup (cp);
+      f->child = NULL;
+      f->next = NULL;
+      f->add_count = 0;
+      f->adds = NULL;
+      f->used = 0;
+    } else {
+      /* no children. */
+      f->child = e_malloc (sizeof (*f->child));
+      f = f->child;
+      f->name = strdup (cp);
+      f->child = NULL;
+      f->next = NULL;
+      f->add_count = 0;
+      f->adds = NULL;
+      f->used = 0;
+
+    }
+   next:
+     cp = strtok (NULL, SPATH_SEPARATOR);
+   }
+  /* Now f if non-null points to where we should add things */
+  if (f == NULL) {
+     root_file_adds = e_malloc (sizeof *root_file_adds);
+     f=root_file_adds;
+     f->name = NULL;
+     f->child = NULL;
+     f->next = NULL;
+     f->add_count = 0;
+     f->adds = NULL;
+   }
+
+  /* Now f really points to where we should add this name. */
+  f->add_count++;
+  f->adds = realloc (f->adds, sizeof (*f->adds)*f->add_count);
+  f->adds[f->add_count-1].path = strdup (path);
+  f->adds[f->add_count-1].name = strdup (name);
+}
+
+/*
+ * Function:	add_file_list
+ *
+ * Purpose:	Register an add-in file.
+ *
+ * Arguments:
+ */
+void
+FDECL3(add_file_list, int, argc, char **,argv, int, ind)
+{
+  char *ptr;
+  char *dup_arg;
+
+  while (ind < argc) {
+     dup_arg = strdup (argv[ind]);
+     ptr = strchr (dup_arg,'=');
+     if (ptr == NULL) {
+        free (dup_arg);
+        return;
+     }
+     *ptr = 0;
+     ptr++;
+     add_one_file (dup_arg, ptr);
+     free (dup_arg);
+     ind++;
+  }
+}
+void
+FDECL1(add_file, char *, filename)
+{
+  char buff[1024];
+  FILE *f;
+  char *ptr;
+  char *p2;
+  int count=0;
+
+  if (strcmp (filename, "-") == 0) {
+    f = stdin;
+  } else {
+    f = fopen (filename, "r");
+    if (f == NULL) {
+      perror ("fopen");
+      exit (1);
+    }
+  }
+  while (fgets (buff, 1024, f)) {
+    count++;
+    ptr = buff;
+    while (isspace (*ptr)) ptr++;
+    if (*ptr==0) continue;
+    if (*ptr=='#') continue;
+
+    if (ptr[strlen(ptr)-1]== '\n') ptr[strlen(ptr)-1]=0;
+    p2 = strchr (ptr, '=');
+    if (p2 == NULL) {
+      fprintf (stderr, "Error in line %d: %s\n", count, buff);
+      exit (1);
+    }
+    *p2 = 0;
+    p2++;
+    add_one_file (ptr, p2);
+  }
+  if (f != stdin) fclose (f);
+}
+
+/* This function looks up additions. */
+char *
+FDECL3(look_up_addition,char **, newpath, char *,path, struct dirent **,de)
+{
+  char *dup_path;
+  char *cp;
+  struct file_adds *f;
+  struct file_adds *tmp = NULL;
+
+  f=root_file_adds;
+  if (!f) return NULL;
+
+  /* I don't trust strtok */
+  dup_path = strdup (path);
+
+  cp = strtok (dup_path, SPATH_SEPARATOR);
+  while (cp != NULL) {
+    for (tmp = f->child; tmp != NULL; tmp=tmp->next) {
+      if (strcmp (tmp->name, cp) == 0) break;
+    }
+    if (tmp == NULL) {
+      /* no match */
+      free (dup_path);
+      return (NULL);
+    }
+    f = tmp;
+    cp = strtok(NULL, SPATH_SEPARATOR);
+  }
+  free (dup_path);
+
+  /*
+   * If nothing, then return.
+   */
+  if (tmp == NULL) 
+    {
+      /* no match */
+      return (NULL);
+    }
+
+  /* looks like we found something. */
+  if (tmp->used >= tmp->add_count) return (NULL);
+
+  *newpath = tmp->adds[tmp->used].path;
+  tmp->used++;
+  *de = &(tmp->du.de);
+  return (tmp->adds[tmp->used-1].name);
+  
+}
+
+/* This function looks up additions. */
+void
+FDECL2(nuke_duplicates, char *, path, struct dirent **,de) 
+{
+  char *dup_path;
+  char *cp;
+  struct file_adds *f;
+  struct file_adds *tmp;
+
+  f=root_file_adds;
+  if (!f) return;
+
+  /* I don't trust strtok */
+  dup_path = strdup (path);
+
+  cp = strtok (dup_path, SPATH_SEPARATOR);
+  while (cp != NULL) {
+    for (tmp = f->child; tmp != NULL; tmp=tmp->next) {
+      if (strcmp (tmp->name, cp) == 0) break;
+    }
+    if (tmp == NULL) {
+      /* no match */
+      free (dup_path);
+      return;
+    }
+    f = tmp;
+    cp = strtok(NULL, SPATH_SEPARATOR);
+  }
+  free (dup_path);
+
+#if 0
+  /* looks like we found something. */
+  if (tmp->used >= tmp->add_count) return;
+
+  *newpath = tmp->adds[tmp->used].path;
+  tmp->used++;
+  *de = &(tmp->du.de);
+  return (tmp->adds[tmp->used-1].name);
+#endif
+  return;
+}
+
+/* This function lets us add files from outside the standard file tree.
+   It is useful if we want to duplicate a cd, but add/replace things.
+   We should note that the real path will be used for exclusions. */
+
+struct dirent *
+FDECL3(readdir_add_files, char **, pathp, char *,path, DIR *, dir){
+  struct dirent *de;
+
+  char *addpath;
+  char *name;
+
+  de = readdir (dir);
+  if (de) {
+    nuke_duplicates(path, &de);
+    return (de);
+  }
+
+  name=look_up_addition (&addpath, path, &de);
+
+  if (!name) {
+    return NULL;
+  }
+
+  *pathp=addpath;
+  
+  /* Now we must create the directory entry. */
+  /* fortuneately only the name seems to matter. */
+  /*
+  de->d_ino = -1;
+  de->d_off = 0;
+  de->d_reclen = strlen (name);
+  */
+  strncpy (de->d_name, name, NAME_MAX);
+  de->d_name[NAME_MAX]=0;
+  nuke_duplicates(path, &de);
+  return (de);
+
+}
+
+#else
+struct dirent *
+FDECL3(readdir_add_files, char **, pathp, char *,path, DIR *, dir){
+  return (readdir (dir));
+}
+#endif
diff --git a/mass_storage/mkisofs-1.11.3/fnmatch.c b/mass_storage/mkisofs-1.11.3/fnmatch.c
new file mode 100644
index 0000000..9832a47
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/fnmatch.c
@@ -0,0 +1,222 @@
+/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+NOTE: The canonical source of this file is maintained with the GNU C Library.
+Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+static char rcsid[] ="$Id: fnmatch.c,v 1.3 1997/03/22 02:53:13 eric Rel $";
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <fnmatch.h>
+
+#ifndef FNM_FILE_NAME
+#define	FNM_FILE_NAME	FNM_PATHNAME /* Preferred GNU name.  */
+#endif
+
+#ifndef FNM_LEADING_DIR
+#define	FNM_LEADING_DIR	(1 << 3) /* Ignore `/...' after a match.  */
+#endif
+
+#ifndef FNM_CASEFOLD
+#define	FNM_CASEFOLD	(1 << 4) /* Compare without regard to case.  */
+#endif
+
+
+#include <ctype.h>
+
+#if defined (STDC_HEADERS) || !defined (isascii)
+#define ISASCII(c) 1
+#else
+#define ISASCII(c) isascii(c)
+#endif
+
+#define ISUPPER(c) (ISASCII (c) && isupper (c))
+
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+   it matches, nonzero if not.  */
+int
+fnmatch (pattern, string, flags)
+     const char *pattern;
+     const char *string;
+     int flags;
+{
+  register const char *p = pattern, *n = string;
+  register char c;
+
+/* Note that this evalutes C many times.  */
+#define FOLD(c)	((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
+
+  while ((c = *p++) != '\0')
+    {
+      c = FOLD (c);
+
+      switch (c)
+	{
+	case '?':
+	  if (*n == '\0')
+	    return FNM_NOMATCH;
+	  else if ((flags & FNM_FILE_NAME) && *n == '/')
+	    return FNM_NOMATCH;
+	  else if ((flags & FNM_PERIOD) && *n == '.' &&
+		   (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+	    return FNM_NOMATCH;
+	  break;
+
+	case '\\':
+	  if (!(flags & FNM_NOESCAPE))
+	    {
+	      c = *p++;
+	      c = FOLD (c);
+	    }
+	  if (FOLD (*n) != c)
+	    return FNM_NOMATCH;
+	  break;
+
+	case '*':
+	  if ((flags & FNM_PERIOD) && *n == '.' &&
+	      (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+	    return FNM_NOMATCH;
+
+	  for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
+	    if (((flags & FNM_FILE_NAME) && *n == '/') ||
+		(c == '?' && *n == '\0'))
+	      return FNM_NOMATCH;
+
+	  if (c == '\0')
+	    return 0;
+
+	  {
+	    char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
+	    c1 = FOLD (c1);
+	    for (--p; *n != '\0'; ++n)
+	      if ((c == '[' || FOLD (*n) == c1) &&
+		  fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
+		return 0;
+	    return FNM_NOMATCH;
+	  }
+
+	case '[':
+	  {
+	    /* Nonzero if the sense of the character class is inverted.  */
+	    register int not;
+
+	    if (*n == '\0')
+	      return FNM_NOMATCH;
+
+	    if ((flags & FNM_PERIOD) && *n == '.' &&
+		(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
+	      return FNM_NOMATCH;
+
+	    not = (*p == '!' || *p == '^');
+	    if (not)
+	      ++p;
+
+	    c = *p++;
+	    for (;;)
+	      {
+		register char cstart = c, cend = c;
+
+		if (!(flags & FNM_NOESCAPE) && c == '\\')
+		  cstart = cend = *p++;
+
+		cstart = cend = FOLD (cstart);
+
+		if (c == '\0')
+		  /* [ (unterminated) loses.  */
+		  return FNM_NOMATCH;
+
+		c = *p++;
+		c = FOLD (c);
+
+		if ((flags & FNM_FILE_NAME) && c == '/')
+		  /* [/] can never match.  */
+		  return FNM_NOMATCH;
+
+		if (c == '-' && *p != ']')
+		  {
+		    cend = *p++;
+		    if (!(flags & FNM_NOESCAPE) && cend == '\\')
+		      cend = *p++;
+		    if (cend == '\0')
+		      return FNM_NOMATCH;
+		    cend = FOLD (cend);
+
+		    c = *p++;
+		  }
+
+		if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
+		  goto matched;
+
+		if (c == ']')
+		  break;
+	      }
+	    if (!not)
+	      return FNM_NOMATCH;
+	    break;
+
+	  matched:;
+	    /* Skip the rest of the [...] that already matched.  */
+	    while (c != ']')
+	      {
+		if (c == '\0')
+		  /* [... (unterminated) loses.  */
+		  return FNM_NOMATCH;
+
+		c = *p++;
+		if (!(flags & FNM_NOESCAPE) && c == '\\')
+		  /* XXX 1003.2d11 is unclear if this is right.  */
+		  ++p;
+	      }
+	    if (not)
+	      return FNM_NOMATCH;
+	  }
+	  break;
+
+	default:
+	  if (c != FOLD (*n))
+	    return FNM_NOMATCH;
+	}
+
+      ++n;
+    }
+
+  if (*n == '\0')
+    return 0;
+
+  if ((flags & FNM_LEADING_DIR) && *n == '/')
+    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
+    return 0;
+
+  return FNM_NOMATCH;
+}
+
+#endif	/* _LIBC or not __GNU_LIBRARY__.  */
diff --git a/mass_storage/mkisofs-1.11.3/fnmatch.h b/mass_storage/mkisofs-1.11.3/fnmatch.h
new file mode 100644
index 0000000..fda8418
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/fnmatch.h
@@ -0,0 +1,80 @@
+/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+
+NOTE: The canonical source of this file is maintained with the GNU C Library.
+Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * 	$Id: fnmatch.h,v 1.1 1997/02/23 15:54:20 eric Rel $
+ */
+
+#ifndef	_FNMATCH_H
+
+#define	_FNMATCH_H	1
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
+#undef	__P
+#define	__P(protos)	protos
+#else /* Not C++ or ANSI C.  */
+#undef	__P
+#define	__P(protos)	()
+/* We can get away without defining `const' here only because in this file
+   it is used only inside the prototype for `fnmatch', which is elided in
+   non-ANSI C where `const' is problematical.  */
+#endif /* C++ or ANSI C.  */
+
+
+/* We #undef these before defining them because some losing systems
+   (HP-UX A.08.07 for example) define these in <unistd.h>.  */
+#undef	FNM_PATHNAME
+#undef	FNM_NOESCAPE
+#undef	FNM_PERIOD
+
+/* Bits set in the FLAGS argument to `fnmatch'.  */
+#define	FNM_PATHNAME	(1 << 0) /* No wildcard can ever match `/'.  */
+#define	FNM_NOESCAPE	(1 << 1) /* Backslashes don't quote special chars.  */
+#define	FNM_PERIOD	(1 << 2) /* Leading `.' is matched only explicitly.  */
+
+#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE)
+#define	FNM_FILE_NAME	FNM_PATHNAME /* Preferred GNU name.  */
+#define	FNM_LEADING_DIR	(1 << 3) /* Ignore `/...' after a match.  */
+#define	FNM_CASEFOLD	(1 << 4) /* Compare without regard to case.  */
+#endif
+
+#ifndef FNM_FILE_NAME
+  /*
+   * Apparently GNU libc doesn't define this thing.
+   */
+#define	FNM_FILE_NAME	FNM_PATHNAME /* Preferred GNU name.  */
+#endif
+
+/* Value returned by `fnmatch' if STRING does not match PATTERN.  */
+#define	FNM_NOMATCH	1
+
+/* Match STRING against the filename pattern PATTERN,
+   returning zero if it matches, FNM_NOMATCH if not.  */
+extern int fnmatch __P ((const char *__pattern, const char *__string,
+			 int __flags));
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* fnmatch.h */
diff --git a/mass_storage/mkisofs-1.11.3/hash.c b/mass_storage/mkisofs-1.11.3/hash.c
new file mode 100644
index 0000000..67098d5
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/hash.c
@@ -0,0 +1,226 @@
+/*
+ * File hash.c - generate hash tables for iso9660 filesystem.
+
+   Written by Eric Youngdale (1993).
+
+   Copyright 1993 Yggdrasil Computing, Incorporated
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+static char rcsid[] ="$Id: hash.c,v 1.2 1997/02/23 16:11:15 eric Rel $";
+
+#include <stdlib.h>
+#include "mkisofs.h"
+
+#define NR_HASH 1024
+
+#define HASH_FN(DEV, INO) ((DEV + INO + (INO >> 2) + (INO << 8)) % NR_HASH)
+
+static struct file_hash * hash_table[NR_HASH] = {0,};
+
+void FDECL1(add_hash, struct directory_entry *, spnt){
+  struct file_hash * s_hash;
+  unsigned int hash_number;
+
+  if(spnt->size == 0 || spnt->starting_block == 0) 
+    if(spnt->size != 0 || spnt->starting_block != 0) {
+      fprintf(stderr,"Non zero-length file assigned zero extent.\n");
+      exit(1);
+    };
+
+  if (spnt->dev == (dev_t) UNCACHED_DEVICE || spnt->inode == UNCACHED_INODE) return;
+  hash_number = HASH_FN((unsigned int) spnt->dev, (unsigned int) spnt->inode);
+
+#if 0
+  if (verbose) fprintf(stderr,"%s ",spnt->name);
+#endif
+  s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash));
+  s_hash->next = hash_table[hash_number];
+  s_hash->inode = spnt->inode;
+  s_hash->dev = spnt->dev;
+  s_hash->starting_block = spnt->starting_block;
+  s_hash->size = spnt->size;
+  hash_table[hash_number] = s_hash;
+}
+
+struct file_hash * FDECL2(find_hash, dev_t, dev, ino_t, inode){
+  unsigned int hash_number;
+  struct file_hash * spnt;
+  hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
+  if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL;
+
+  spnt = hash_table[hash_number];
+  while(spnt){
+    if(spnt->inode == inode && spnt->dev == dev) return spnt;
+    spnt = spnt->next;
+  };
+  return NULL;
+}
+
+
+static struct file_hash * directory_hash_table[NR_HASH] = {0,};
+
+void FDECL2(add_directory_hash, dev_t, dev, ino_t, inode){
+  struct file_hash * s_hash;
+  unsigned int hash_number;
+
+  if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return;
+  hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
+
+  s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash));
+  s_hash->next = directory_hash_table[hash_number];
+  s_hash->inode = inode;
+  s_hash->dev = dev;
+  directory_hash_table[hash_number] = s_hash;
+}
+
+struct file_hash * FDECL2(find_directory_hash, dev_t, dev, ino_t, inode){
+  unsigned int hash_number;
+  struct file_hash * spnt;
+  hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
+  if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL;
+
+  spnt = directory_hash_table[hash_number];
+  while(spnt){
+    if(spnt->inode == inode && spnt->dev == dev) return spnt;
+    spnt = spnt->next;
+  };
+  return NULL;
+}
+
+struct  name_hash
+{
+  struct name_hash * next;
+  struct directory_entry * de;
+};
+
+#define NR_NAME_HASH 128
+
+static struct name_hash * name_hash_table[NR_NAME_HASH] = {0,};
+
+/*
+ * Find the hash bucket for this name.
+ */
+static  unsigned int FDECL1(name_hash, const char *, name)
+{
+  unsigned int hash = 0;
+  const char * p;
+  
+  p = name;
+  
+  while (*p) 
+    {
+      /*
+       * Don't hash the  iso9660 version number.  This way
+       * we can detect duplicates in cases where we have
+       * directories (i.e. foo) and non-directories
+       * (i.e. foo;1).
+       */
+      if( *p == ';' )
+	{
+	  break;
+	}
+      hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++;
+    }
+  return hash % NR_NAME_HASH;
+}
+
+void FDECL1(add_file_hash, struct directory_entry *, de){
+	struct name_hash  * new;
+	int hash;
+
+	new = (struct  name_hash *) e_malloc(sizeof(struct name_hash));
+	new->de = de;
+	new->next = NULL;
+	hash = name_hash(de->isorec.name);
+
+	/* Now insert into the hash table */
+	new->next = name_hash_table[hash];
+	name_hash_table[hash] = new;
+}
+
+struct directory_entry * FDECL1(find_file_hash, char *, name)
+{
+  struct name_hash  * nh;
+  char		    * p1;
+  char		    * p2;
+  
+  for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
+    {
+      p1 = name;
+      p2 = nh->de->isorec.name;
+
+      /*
+       * Look for end of string, or a mismatch.
+       */
+      while(1==1)
+	{
+	  if(    (*p1 == '\0' || *p1 == ';')
+	      || (*p2 == '\0' || *p2 == ';')
+	      || (*p1 != *p2) )
+	    {
+	      break;
+	    }
+	  p1++;
+	  p2++;
+	}
+
+      /*
+       * If we are at the end of both strings, then
+       * we have a match.
+       */
+      if(    (*p1 == '\0' || *p1 == ';')
+	  && (*p2 == '\0' || *p2 == ';') )
+	{
+	  return nh->de;
+	}
+    }
+  return NULL;
+}
+
+int FDECL1(delete_file_hash, struct directory_entry *, de){
+	struct name_hash  * nh, *prev;
+	int hash;
+
+	prev = NULL;
+	hash = name_hash(de->isorec.name);
+	for(nh = name_hash_table[hash]; nh; nh = nh->next) {
+		if(nh->de == de) break;
+		prev = nh;
+	}
+	if(!nh) return 1;
+	if(!prev)
+		name_hash_table[hash] = nh->next;
+	else
+		prev->next = nh->next;
+	free(nh);
+	return 0;
+}
+
+void flush_file_hash(){
+	struct name_hash  * nh, *nh1;
+	int i;
+
+	for(i=0; i<NR_NAME_HASH; i++) {
+		nh = name_hash_table[i];
+		while(nh) {
+			nh1 =  nh->next;
+			free(nh);
+			nh = nh1;
+		}
+		name_hash_table[i] =  NULL;
+		
+	}
+}
diff --git a/mass_storage/mkisofs-1.11.3/iso9660.h b/mass_storage/mkisofs-1.11.3/iso9660.h
new file mode 100644
index 0000000..a58f96f
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/iso9660.h
@@ -0,0 +1,157 @@
+/*
+ * Header file iso9660.h - assorted structure definitions and typecasts.
+ * specific to iso9660 filesystem.
+
+   Written by Eric Youngdale (1993).
+
+   Copyright 1993 Yggdrasil Computing, Incorporated
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * 	$Id: iso9660.h,v 1.1 1997/02/23 15:55:25 eric Rel $
+ */
+
+#ifndef _ISOFS_FS_H
+#define _ISOFS_FS_H
+
+/*
+ * The isofs filesystem constants/structures
+ */
+
+/* This part borrowed from the bsd386 isofs */
+#define ISODCL(from, to) (to - from + 1)
+
+struct iso_volume_descriptor {
+	char type[ISODCL(1,1)]; /* 711 */
+	char id[ISODCL(2,6)];
+	char version[ISODCL(7,7)];
+	char data[ISODCL(8,2048)];
+};
+
+/* volume descriptor types */
+#define ISO_VD_PRIMARY 1
+#define ISO_VD_END 255
+
+#define ISO_STANDARD_ID "CD001"
+
+#define EL_TORITO_ID "EL TORITO SPECIFICATION"
+#define EL_TORITO_ARCH_x86 0
+#define EL_TORITO_ARCH_PPC 1
+#define EL_TORITO_ARCH_MAC 2
+#define EL_TORITO_BOOTABLE 0x88
+#define EL_TORITO_MEDIA_NOEMUL 0
+#define EL_TORITO_MEDIA_12FLOP  1
+#define EL_TORITO_MEDIA_144FLOP 2
+#define EL_TORITO_MEDIA_288FLOP 3
+#define EL_TORITO_MEDIA_HD      4
+
+struct iso_primary_descriptor {
+	char type			[ISODCL (  1,   1)]; /* 711 */
+	char id				[ISODCL (  2,   6)];
+	char version			[ISODCL (  7,   7)]; /* 711 */
+	char unused1			[ISODCL (  8,   8)];
+	char system_id			[ISODCL (  9,  40)]; /* achars */
+	char volume_id			[ISODCL ( 41,  72)]; /* dchars */
+	char unused2			[ISODCL ( 73,  80)];
+	char volume_space_size		[ISODCL ( 81,  88)]; /* 733 */
+	char unused3			[ISODCL ( 89, 120)];
+	char volume_set_size		[ISODCL (121, 124)]; /* 723 */
+	char volume_sequence_number	[ISODCL (125, 128)]; /* 723 */
+	char logical_block_size		[ISODCL (129, 132)]; /* 723 */
+	char path_table_size		[ISODCL (133, 140)]; /* 733 */
+	char type_l_path_table		[ISODCL (141, 144)]; /* 731 */
+	char opt_type_l_path_table	[ISODCL (145, 148)]; /* 731 */
+	char type_m_path_table		[ISODCL (149, 152)]; /* 732 */
+	char opt_type_m_path_table	[ISODCL (153, 156)]; /* 732 */
+	char root_directory_record	[ISODCL (157, 190)]; /* 9.1 */
+	char volume_set_id		[ISODCL (191, 318)]; /* dchars */
+	char publisher_id		[ISODCL (319, 446)]; /* achars */
+	char preparer_id		[ISODCL (447, 574)]; /* achars */
+	char application_id		[ISODCL (575, 702)]; /* achars */
+	char copyright_file_id		[ISODCL (703, 739)]; /* 7.5 dchars */
+	char abstract_file_id		[ISODCL (740, 776)]; /* 7.5 dchars */
+	char bibliographic_file_id	[ISODCL (777, 813)]; /* 7.5 dchars */
+	char creation_date		[ISODCL (814, 830)]; /* 8.4.26.1 */
+	char modification_date		[ISODCL (831, 847)]; /* 8.4.26.1 */
+	char expiration_date		[ISODCL (848, 864)]; /* 8.4.26.1 */
+	char effective_date		[ISODCL (865, 881)]; /* 8.4.26.1 */
+	char file_structure_version	[ISODCL (882, 882)]; /* 711 */
+	char unused4			[ISODCL (883, 883)];
+	char application_data		[ISODCL (884, 1395)];
+	char unused5			[ISODCL (1396, 2048)];
+};
+
+/* El Torito Boot Record Volume Descriptor */
+struct eltorito_boot_descriptor {
+        char id	           		[ISODCL (  1,    1)]; /* 711 */
+	char id2			[ISODCL (  2,    6)];
+	char version			[ISODCL (  7,    7)]; /* 711 */
+	char system_id			[ISODCL (  8,   39)];
+	char unused2			[ISODCL ( 40,   71)];
+        char bootcat_ptr                [ISODCL ( 72 ,  75)];
+	char unused5			[ISODCL ( 76, 2048)];
+};
+
+/* Validation entry for El Torito */
+struct eltorito_validation_entry {
+        char headerid          		[ISODCL (  1,    1)]; /* 711 */
+	char arch			[ISODCL (  2,    2)];
+	char pad1			[ISODCL (  3,    4)]; /* 711 */
+	char id  			[ISODCL (  5,   28)];
+	char cksum			[ISODCL ( 29,   30)];
+        char key1                       [ISODCL ( 31,   31)];
+	char key2			[ISODCL ( 32,   32)];
+};
+
+/* El Torito initial/default entry in boot catalog */
+struct eltorito_defaultboot_entry {
+        char boot_id           		[ISODCL (  1,    1)]; /* 711 */
+	char boot_media			[ISODCL (  2,    2)];
+	char loadseg			[ISODCL (  3,    4)]; /* 711 */
+	char arch  			[ISODCL (  5,    5)];
+	char pad1			[ISODCL (  6,    6)];
+        char nsect                      [ISODCL (  7,    8)];
+	char bootoff			[ISODCL (  9,   12)];
+        char pad2                       [ISODCL ( 13,   32)];
+};
+
+
+/* We use this to help us look up the parent inode numbers. */
+
+struct iso_path_table{
+	unsigned char  name_len[2];	/* 721 */
+	char extent[4];		/* 731 */
+	char  parent[2];	/* 721 */
+	char name[1];
+};
+
+struct iso_directory_record {
+	unsigned char length			[ISODCL (1, 1)]; /* 711 */
+	char ext_attr_length		[ISODCL (2, 2)]; /* 711 */
+	char extent			[ISODCL (3, 10)]; /* 733 */
+	char size			[ISODCL (11, 18)]; /* 733 */
+	char date			[ISODCL (19, 25)]; /* 7 by 711 */
+	char flags			[ISODCL (26, 26)];
+	char file_unit_size		[ISODCL (27, 27)]; /* 711 */
+	char interleave			[ISODCL (28, 28)]; /* 711 */
+	char volume_sequence_number	[ISODCL (29, 32)]; /* 723 */
+	unsigned char name_len		[ISODCL (33, 33)]; /* 711 */
+	char name			[34]; /* Not really, but we need something here */
+};
+#endif
+
+
+
diff --git a/mass_storage/mkisofs-1.11.3/make.com b/mass_storage/mkisofs-1.11.3/make.com
new file mode 100644
index 0000000..6c08bdc
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/make.com
@@ -0,0 +1,19 @@
+$!
+$! $Id: make.com,v 1.1 1997/02/23 15:55:47 eric Rel $
+$!
+$! Set the def dir to proper place for use in batch. Works for interactive too.
+$flnm = f$enviroment("PROCEDURE")     ! get current procedure name
+$set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
+$!
+$!
+$if "''p1'".eqs."LINK" then goto link
+$gcc/debug mkisofs.c
+$gcc/debug write.c
+$gcc/debug tree.c
+$gcc/debug hash.c
+$gcc/debug rock.c
+$gcc/debug vms.c
+$gcc/debug exclude.c
+$link:
+$link mkisofs.obj+write.obj+tree.obj+hash.obj+rock.obj+vms.obj+exclude.obj+  -
+	gnu_cc:[000000]gcclib/lib+sys$library:vaxcrtl/lib
diff --git a/mass_storage/mkisofs-1.11.3/match.c b/mass_storage/mkisofs-1.11.3/match.c
new file mode 100644
index 0000000..0f5c7d8
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/match.c
@@ -0,0 +1,56 @@
+/*
+ * 27-Mar-96: Jan-Piet Mens <jpm@mens.de>
+ * added 'match' option (-m) to specify regular expressions NOT to be included
+ * in the CD image.
+ */
+
+static char rcsid[] ="$Id: match.c,v 1.2 1997/02/23 16:10:42 eric Rel $";
+
+#include <stdio.h>
+#ifndef VMS
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+#endif
+#include <string.h>
+#include "match.h"
+
+#define MAXMATCH 1000
+static char *mat[MAXMATCH];
+
+void add_match(fn)
+char * fn;
+{
+  register int i;
+
+  for (i=0; mat[i] && i<MAXMATCH; i++);
+  if (i == MAXMATCH) {
+    fprintf(stderr,"Can't exclude RE '%s' - too many entries in table\n",fn);
+    return;
+  }
+
+ 
+  mat[i] = (char *) malloc(strlen(fn)+1);
+  if (! mat[i]) {
+    fprintf(stderr,"Can't allocate memory for excluded filename\n");
+    return;
+  }
+
+  strcpy(mat[i],fn);
+}
+
+int matches(fn)
+char * fn;
+{
+  /* very dumb search method ... */
+  register int i;
+
+  for (i=0; mat[i] && i<MAXMATCH; i++) {
+    if (fnmatch(mat[i], fn, FNM_FILE_NAME) != FNM_NOMATCH) {
+      return 1; /* found -> excluded filenmae */
+    }
+  }
+  return 0; /* not found -> not excluded */
+}
diff --git a/mass_storage/mkisofs-1.11.3/match.h b/mass_storage/mkisofs-1.11.3/match.h
new file mode 100644
index 0000000..90def7c
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/match.h
@@ -0,0 +1,14 @@
+/*
+ * 27th March 1996. Added by Jan-Piet Mens for matching regular expressions
+ * 		    in paths.
+ * 
+ */
+
+/*
+ * 	$Id: match.h,v 1.1 1997/02/23 15:56:12 eric Rel $
+ */
+
+#include "fnmatch.h"
+
+void add_match();
+int matches();
diff --git a/mass_storage/mkisofs-1.11.3/mkisofs.8 b/mass_storage/mkisofs-1.11.3/mkisofs.8
new file mode 100644
index 0000000..d6dd155
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/mkisofs.8
@@ -0,0 +1,429 @@
+#
+# $Id: mkisofs.8,v 1.5.1.3 1998/06/02 03:36:16 eric Exp $
+#
+.\" -*- nroff -*-
+.TH MKISOFS 8 "12 Oct 1997" "Version 1.11.3"
+.SH NAME
+mkisofs \- create a iso9660 filesystem with optional Rock Ridge attributes.
+.SH SYNOPSIS
+.B mkisofs
+[
+.B \-a
+]
+[
+.B \-b
+.I boot_image
+]
+[
+.B \-c
+.I boot_catalog
+]
+[
+.B \-A
+.I application_id
+]
+[
+.B \-f
+]
+[
+.B \-d
+]
+[
+.B \-D
+]
+[
+.B \-i
+.I include-list
+]
+[
+.B \-l
+]
+[
+.B \-L
+]
+[
+.B \-L
+]
+[
+.B \-p
+.I preparer
+]
+[
+.B \-P
+.I publisher
+]
+[
+.B \-r
+]
+[
+.B \-R
+]
+[
+.B \-T
+]
+[
+.B \-v
+]
+[
+.B \-V
+]
+[
+.B \-V
+.I volid
+]
+[
+.B \-x
+.I path
+]
+[
+.B \-z
+]
+[
+.B \-m
+.I glob
+]
+.B \-o
+.I filename
+.I path
+.SH DESCRIPTION
+.B mkisofs
+is effectively a pre-mastering program to generate the iso9660 filesystem - it
+takes a snapshot of a given directory tree, and generates a binary image which
+will correspond to an iso9660 filesystem when written to a block device.
+.PP
+.B mkisofs
+is also capable of generating the System Use Sharing Protocol records specified
+by the Rock Ridge Interchange Protocol.  This is used to further describe the
+files in the iso9660 filesystem to a unix host, and provides information such
+as longer filenames, uid/gid, posix permissions, and block and character
+devices.
+.PP
+Each file written to the iso9660 filesystem must have a filename in the 8.3
+format (8 characters, period, 3 characters, all upper case), even if Rock Ridge
+is in use.  This filename is used on systems that are not able to make use of
+the Rock Ridge extensions (such as MS-DOS), and each filename in each directory
+must be different from the other filenames in the same directory.
+.B mkisofs
+generally tries to form correct names by forcing the unix filename to upper
+case and truncating as required, but often times this yields unsatisfactory
+results when there are cases where the
+truncated names are not all unique.
+.B mkisofs
+assigns weightings to each filename, and if two names that are otherwise the
+same are found the name with the lower priority is renamed to have a 3 digit
+number as an extension (where the number is guaranteed to be unique).  An
+example of this would be the files foo.bar and
+foo.bar.~1~ - the file foo.bar.~1~ would be written as FOO.000;1 and the file
+foo.bar would be written as FOO.BAR;1
+.PP
+Note that
+.B mkisofs
+is not designed to communicate with the writer directly.  Most writers
+have proprietary command sets which vary from one manufacturer to
+another, and you need a specialized tool to actually burn the disk.
+The
+.B cdwrite
+utility is one such tool that runs under Linux and performs this task.
+The latest version of
+.B cdwrite
+is capable of communicating with Phillips/IMS/Kodak, HP and Yamaha drives.
+Most writers come with some version of DOS software that allows a direct image
+copy of an iso9660 image to the writer.  The current version of
+.B cdwrite
+is available from sunsite.unc.edu: /utils/disk-management/cdwrite-2.0.tar.gz
+.PP
+Also you should know that most cd writers are very particular about timing.
+Once you start to burn a disc, you cannot let their buffer empty before you
+are done, or you will end up with a corrupt disc.  Thus it is critical
+that you be able to maintain an uninterrupted data stream to the writer
+for the entire time that the disc is being written.
+.PP
+.br
+.B path
+is the path of the directory tree to be copied into the iso9660 filesystem.
+.SH OPTIONS
+.TP
+.I \-a
+Include all files on the iso9660 filesystem.  Normally files that contain the
+characters '~' or '#' will not be included (these are typically backup files
+for editors under unix).
+.TP
+.I \-A application_id
+Specifies a text string that will be written into the volume header.
+This should describe the application that will be on the disc.  There
+is space on the disc for 128 characters of information.  This parameter can
+also be set in the file
+.I \&.mkisofsrc
+with APPI=id.
+If specified in both places, the command line version is used.
+.TP
+.I \-b boot_image
+Specifies the path and filename of the boot image to be used when making
+an "El Torito" bootable CD. The pathname must be relative to the source
+path specified to
+.B mkisofs.
+This option is required to make a bootable CD.
+The boot image must be exactly the size of either a 1.2, 1.44, or a 2.88
+meg floppy, and
+.B mkisofs
+will use this size when creating the output iso9660
+filesystem. It is assumed that the first 512 byte sector should be read
+from the boot image (it is essentially emulating a normal floppy drive).
+This will work, for example, if the boot image is a LILO based boot floppy.
+.TP
+.I \-c boot_catalog
+Specifies the path and filename of the boot catalog to be used when making
+an "El Torito" bootable CD. The pathname must be relative to the source
+path specified to
+.B mkisofs.
+This option is required to make a bootable CD.
+This file will be created by
+.B mkisofs
+in the source filesystem, so be
+sure the specified filename does not conflict with an existing file, as
+it will be quietly overwritten! Usually a name like "boot.catalog" is
+chosen.
+.TP
+.I \-d
+Omit trailing period from files that do not have a period.  This violates the
+ISO9660 standard, but it happens to work on many systems.  Use with caution.
+.TP
+.I \-D
+Do not use deep directory relocation, and instead just pack them in the
+way we see them.  This violates the ISO9660 standard, but it works on many
+systems.  Use with caution.
+.TP
+.I \-f
+Follow symbolic links when generating the filesystem.  When this option is not
+in use, symbolic links will be entered using Rock Ridge if enabled, otherwise
+the file will be ignored.
+.TP
+.I \-i include-list
+Use the specified file as a list of files to add to the directory tree.
+This is useful for quickly repacking a CD while adding files to it.
+The format of this file is path1/file=path2 where path1 is the directory
+in the ISO9660 file system where file should appear and path2 is the
+where to find the file.  NOTE: This option doesn't work well, and
+needs to be compltely redone so that integration with the rest of mkisofs
+is handled in a cleaner fashion.
+.TP
+.I \-l
+Allow full 32 character filenames.  Normally the ISO9660 filename will be in an
+8.3 format which is compatible with MS-DOS, even though the ISO9660 standard
+allows filenames of up to 32 characters.  If you use this option, the disc may
+be difficult to use on a MS-DOS system, but this comes in handy on some other
+systems (such as the Amiga).  Use with caution.
+.TP
+.I \-L
+Allow filenames to begin with a period.  Usually, a leading dot is
+replaced with an underscore in order to maintain MS-DOS compatibility.
+.TP
+.I \-m glob
+Exclude
+.I glob
+from being written to CDROM.
+.I glob
+is a shell wild-card-style pattern that must match part of the filename (not 
+the path as with option
+.BR -x ).
+Technically
+.I glob
+is matched against the
+.I d->d_name
+part of the directory entry.
+Multiple globs may be excluded (up to 1000).
+Example:
+
+mkisofs \-o rom \-m '*.o' \-m core \-m foobar
+
+would exclude all files ending in ".o", called "core" or "foobar" to be
+copied to CDROM. Note that if you had a directory called "foobar" it too (and
+of course all its descendants) would be excluded.
+.TP
+.I \-M path
+Specifies path to existing iso9660 image to be merged.  The output
+of 
+.B mkisofs
+will be a new session which should get written to the end of the
+image specified in -M.  Typically this requires multi-session capability
+for the recorder and cdrom drive that you are attempting to write this
+image to.  Support for this is not yet 100% complete, because some handshaking
+is required between mkisofs and cdwrite in order to determine the next
+writable address on the cdrom.
+.TP
+.I \-N
+Omit version numbers from ISO9660 file names.  This may violate the ISO9660
+standard, but no one really uses the version numbers anyway.  Use with caution.
+.TP
+.I \-o filename
+is the name of the file to which the iso9660 filesystem image should be
+written.  This can be a disk file, a tape drive, or it can correspond directly
+to the device name of the optical disc writer.  If not specified, stdout is
+used.  Note that the output can also be a block special device for a regular
+disk drive, in which case the disk partition can be mounted and examined to
+ensure that the premastering was done correctly.
+.TP
+.I \-P publisher_id
+Specifies a text string that will be written into the volume header.
+This should describe the publisher of the CDROM, usually with a
+mailing address and phone number.  There is space on the disc for 128
+characters of information.  This parameter can also be set in the file
+.I \&.mkisofsrc
+with PUBL=.
+If specified in both places, the command line version is used.
+.TP
+.I \-p preparer_id
+Specifies a text string that will be written into the volume header.
+This should describe the preparer of the CDROM, usually with a mailing
+address and phone number.  There is space on the disc for 128
+characters of information.  This parameter can also be set in the file
+.I \&.mkisofsrc
+with PREP=.
+If specified in both places, the command line version is used.
+.TP
+.I \-R
+Generate SUSP and RR records using the Rock Ridge protocol to further describe
+the files on the iso9660 filesystem.
+.TP
+.I \-r
+This is like the \-R option, but file ownership and modes are set to
+more useful values.  The uid and gid are set to zero, because they are
+usually only useful on the author's system, and not useful to the
+client.  All the file read bits are set true, so that files and
+directories are globally readable on the client.  If any execute bit is
+set for a file, set all of the execute bits, so that executables are
+globally executable on the client.  If any search bit is set for a
+directory, set all of the search bits, so that directories are globally
+searchable on the client.  All write bits are cleared, because the
+CD-Rom will be mounted read-only in any case.  If any of the special
+mode bits are set, clear them, because file locks are not useful on a
+read-only file system, and set-id bits are not desirable for uid 0 or
+gid 0.
+.TP
+.I \-T
+Generate a file TRANS.TBL in each directory on the CDROM, which can be used
+on non-Rock Ridge capable systems to help establish the correct file names.
+There is also information present in the file that indicates the major and
+minor numbers for block and character devices, and each symlink has the name of
+the link file given.
+.TP
+.I \-V volid
+Specifies the volume ID to be written into the master block.  This
+parameter can also be set in the file
+.I \&.mkisofsrc
+with VOLI=id.
+If specified in both places, the command line version is used.
+.TP
+.I \-v
+Verbose execution.
+.TP
+.I \-x path
+Exclude
+.I path
+from being written to CDROM.
+.I path
+must be the complete pathname that results from concatenating the pathname
+given as command line argument and the path relative to this directory.
+Multiple paths may be excluded (up to 1000).
+Example: 
+
+mkisofs \-o cd \-x /local/dir1 \-x /local/dir2 /local
+.TP
+.I \-z
+Generate special SUSP records for transparently compressed files.  This is
+only of use and interest for hosts that support transparent decompression.
+This is an experimental feature, and no hosts yet support this, but there
+are ALPHA patches for Linux that can make use of this feature.
+.SH CONFIGURATION
+.B mkisofs
+looks for the
+.IR \&.mkisofsrc
+file,
+first in the current working directory,
+then in the user's home directory,
+and then in the directory in which the
+.B mkisofs
+binary is stored.  This file is assumed to contain a series of lines
+of the form "TAG=value", and in this way you can specify certain
+options.
+The case of the tag is not significant.
+Some fields in the volume header
+are not settable on the command line, but can be altered through this
+facility.
+Comments may be placed in this file,
+using lines which start with a hash (#) character.
+.TP
+APPI
+The application identifier
+should describe the application that will be on the disc.
+There is space on the disc for 128 characters of information.
+May be overridden using the \-A command line option.
+.TP
+COPY
+The copyright information,
+often the name of a file on the disc containing the copyright notice.
+There is space in the disc for 37 characters of information.
+.TP
+ABST
+The abstract information,
+often the name of a file on the disc containing an abstract.
+There is space in the disc for 37 characters of information.
+.TP
+BIBL
+The bibliographic information,
+often the name of a file on the disc containing a bibliography.
+There is space in the disc for 37 characters of information.
+.TP
+PREP
+This should describe the preparer of the CDROM,
+usually with a mailing address and phone number.
+There is space on the disc for 128 characters of information.
+May be overridden using the \-p command line option.
+.TP
+PUBL
+This should describe the publisher of the CDROM,
+usually with a mailing address and phone number.
+There is space on the disc for 128 characters of information.
+May be overridden using the \-P command line option.
+.TP
+SYSI
+The System Identifier.
+There is space on the disc for 32 characters of information.
+.TP
+VOLI
+The Volume Identifier.
+There is space on the disc for 32 characters of information.
+May be overridden using the \-V command line option.
+.TP
+VOLS
+The Volume Set Name.
+There is space on the disc for 278 characters of information.
+.PP
+.B mkisofs
+can also be configured at compile time with defaults for many of these fields.
+See the file defaults.h.
+.SH AUTHOR
+.B mkisofs
+is not based on the standard mk*fs tools for unix, because we must generate
+a complete  copy of an existing filesystem on a disk in the  iso9660
+filesystem.  The name mkisofs is probably a bit of a misnomer, since it
+not only creates the filesystem, but it also populates it as well.
+.PP
+.br
+Eric Youngdale <ericy@gnu.ai.mit.edu> or <eric@andante.jic.com> wrote both the
+Linux isofs9660 filesystem and the mkisofs utility, and is currently
+maintaining them.  The copyright for the mkisofs utility is held by
+Yggdrasil Computing, Incorporated.
+.SH BUGS
+Any files that have hard links to files not in the tree being copied to the
+iso9660 filessytem will have an incorrect file reference count.
+.PP
+There may be some other ones.  Please, report them to the author.
+.SH FUTURE IMPROVEMENTS
+Allow specification of multiple paths on the command line to be included in
+iso9660 filesystem.  Can be tricky - directory entries in the root directory
+need to be properly sorted.
+.SH AVAILABILITY
+.B mkisofs
+is available for anonymous ftp from tsx-11.mit.edu in
+/pub/linux/packages/mkisofs and many other mirror sites.
diff --git a/mass_storage/mkisofs-1.11.3/mkisofs.c b/mass_storage/mkisofs-1.11.3/mkisofs.c
new file mode 100644
index 0000000..a2e2d18
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/mkisofs.c
@@ -0,0 +1,660 @@
+/*
+ * Program mkisofs.c - generate iso9660 filesystem  based upon directory
+ * tree on hard disk.
+
+   Written by Eric Youngdale (1993).
+
+   Copyright 1993 Yggdrasil Computing, Incorporated
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+static char rcsid[] ="$Id: mkisofs.c,v 1.10.1.3 1998/06/02 03:36:16 eric Exp $";
+
+/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */
+
+#include <errno.h>
+#include "mkisofs.h"
+#include "config.h"
+
+#ifdef linux
+#include <getopt.h>
+#endif
+
+#include "iso9660.h"
+#include <ctype.h>
+
+#ifndef VMS
+#include <time.h>
+#else
+#include <sys/time.h>
+#include "vms.h"
+#endif
+
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#ifndef VMS
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#endif
+
+#include "exclude.h"
+
+#ifdef __NetBSD__
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+
+struct directory * root = NULL;
+
+static char version_string[] = "mkisofs v1.11.3";
+
+FILE * discimage;
+unsigned int next_extent = 0;
+unsigned int last_extent = 0;
+unsigned int session_start = 0;
+unsigned int path_table_size = 0;
+unsigned int path_table[4] = {0,};
+unsigned int path_blocks = 0;
+struct iso_directory_record root_record;
+char * extension_record = NULL;
+int extension_record_extent = 0;
+static  int extension_record_size = 0;
+
+/* These variables are associated with command line options */
+int use_eltorito = 0;
+int use_RockRidge = 0;
+int verbose = 0;
+int all_files  = 0;
+int follow_links = 0;
+int rationalize = 0;
+int generate_tables = 0;
+char * preparer = PREPARER_DEFAULT;
+char * publisher = PUBLISHER_DEFAULT;
+char * appid = APPID_DEFAULT;
+char * copyright = COPYRIGHT_DEFAULT;
+char * biblio = BIBLIO_DEFAULT;
+char * abstract = ABSTRACT_DEFAULT;
+char * volset_id = VOLSET_ID_DEFAULT;
+char * volume_id = VOLUME_ID_DEFAULT;
+char * system_id = SYSTEM_ID_DEFAULT;
+char * boot_catalog = BOOT_CATALOG_DEFAULT;
+char * boot_image = BOOT_IMAGE_DEFAULT;
+
+int omit_period = 0;             /* Violates iso9660, but these are a pain */
+int transparent_compression = 0; /* So far only works with linux */
+int omit_version_number = 0;     /* May violate iso9660, but noone uses vers*/
+int RR_relocation_depth = 6;     /* Violates iso9660, but most systems work */
+int full_iso9660_filenames = 0;  /* Used with Amiga.  Disc will not work with
+				  DOS */
+int allow_leading_dots = 0;	 /* DOS cannot read names with leading dots */
+
+struct rcopts{
+  char * tag;
+  char ** variable;
+};
+
+struct rcopts rcopt[] = {
+  {"PREP", &preparer},
+  {"PUBL", &publisher},
+  {"APPI", &appid},
+  {"COPY", &copyright},
+  {"BIBL", &biblio},
+  {"ABST", &abstract},
+  {"VOLS", &volset_id},
+  {"VOLI", &volume_id},
+  {"SYSI", &system_id},
+  {NULL, NULL}
+};
+
+#if defined(ultrix) || defined(_AUX_SOURCE)
+char *strdup(s)
+char *s;{char *c;if(c=(char *)malloc(strlen(s)+1))strcpy(c,s);return c;}
+#endif
+
+void FDECL1(read_rcfile, char *, appname)
+{
+  FILE * rcfile;
+  struct rcopts * rco;
+  char * pnt, *pnt1;
+  char linebuffer[256];
+  static char rcfn[] = ".mkisofsrc";
+  char filename[1000];
+  int linum;
+
+  strcpy(filename, rcfn);
+  rcfile = fopen(filename, "r");
+  if (!rcfile && errno != ENOENT)
+    perror(filename);
+
+  if (!rcfile)
+    {
+      pnt = getenv("MKISOFSRC");
+      if (pnt && strlen(pnt) <= sizeof(filename))
+	{
+	  strcpy(filename, pnt);
+	  rcfile = fopen(filename, "r");
+	  if (!rcfile && errno != ENOENT)
+	    perror(filename);
+	}
+    }
+
+  if (!rcfile)
+    {
+      pnt = getenv("HOME");
+      if (pnt && strlen(pnt) + strlen(rcfn) + 2 <= sizeof(filename))
+	{
+	  strcpy(filename, pnt);
+	  strcat(filename, "/");
+	  strcat(filename, rcfn);
+	  rcfile = fopen(filename, "r");
+	  if (!rcfile && errno != ENOENT)
+	    perror(filename);
+	}
+    }
+  if (!rcfile && strlen(appname)+sizeof(rcfn)+2 <= sizeof(filename))
+    {
+      strcpy(filename, appname);
+      pnt = strrchr(filename, '/');
+      if (pnt)
+	{
+	  strcpy(pnt + 1, rcfn);
+	  rcfile = fopen(filename, "r");
+	  if (!rcfile && errno != ENOENT)
+	    perror(filename);
+	}
+    }
+  if (!rcfile)
+    return;
+  fprintf(stderr, "Using \"%s\"\n", filename);
+  /* OK, we got it.  Now read in the lines and parse them */
+  linum = 0;
+  while (fgets(linebuffer, sizeof(linebuffer), rcfile))
+    {
+      char *name;
+      char *name_end;
+      ++linum;
+      /* skip any leading white space */
+	pnt = linebuffer;
+      while (*pnt == ' ' || *pnt == '\t')
+	++pnt;
+      /* If we are looking at a # character, this line is a comment. */
+	if (*pnt == '#')
+	  continue;
+      /* The name should begin in the left margin.  Make sure it is in
+	 upper case.  Stop when we see white space or a comment. */
+	name = pnt;
+      while (*pnt && isalpha(*pnt))
+	{
+	  if(islower(*pnt))
+	    *pnt = toupper(*pnt);
+	  pnt++;
+	}
+      if (name == pnt)
+	{
+	  fprintf(stderr, "%s:%d: name required\n", filename, linum);
+	  continue;
+	}
+      name_end = pnt;
+      /* Skip past white space after the name */
+      while (*pnt == ' ' || *pnt == '\t')
+	pnt++;
+      /* silently ignore errors in the rc file. */
+      if (*pnt != '=')
+	{
+	  fprintf(stderr, "%s:%d: equals sign required\n", filename, linum);
+	  continue;
+	}
+      /* Skip pas the = sign, and any white space following it */
+      pnt++; /* Skip past '=' sign */
+      while (*pnt == ' ' || *pnt == '\t')
+	pnt++;
+
+      /* now it is safe to NUL terminate the name */
+
+	*name_end = 0;
+
+      /* Now get rid of trailing newline */
+
+      pnt1 = pnt;
+      while (*pnt1)
+	{
+	  if (*pnt1 == '\n')
+	    {
+	      *pnt1 = 0;
+	      break;
+	    }
+	  pnt1++;
+	};
+      /* OK, now figure out which option we have */
+      for(rco = rcopt; rco->tag; rco++) {
+	if(strcmp(rco->tag, name) == 0)
+	  {
+	    *rco->variable = strdup(pnt);
+	    break;
+	  };
+      }
+      if (rco->tag == NULL)
+	{
+	  fprintf(stderr, "%s:%d: field name \"%s\" unknown\n", filename, linum,
+		  name);
+	}
+     }
+  if (ferror(rcfile))
+    perror(filename);
+  fclose(rcfile);
+}
+
+char * path_table_l = NULL;
+char * path_table_m = NULL;
+int goof = 0;
+
+void usage(){
+	fprintf(stderr,"Usage:\n");
+	fprintf(stderr,
+"mkisofs [-o outfile] [-R] [-V volid] [-v] [-a] \
+[-T]\n [-l] [-d] [-V] [-D] [-L] [-p preparer]"
+#ifdef ADD_FILES
+"[-i file] \n"
+#endif
+"[-P publisher] [ -A app_id ] [-z] \n \
+[-b boot_image_name] [-c boot_catalog-name] \
+[-x path -x path ...] path\n");
+	exit(1);
+}
+
+
+/* 
+ * Fill in date in the iso9660 format 
+ *
+ * The standards  state that the timezone offset is in multiples of 15
+ * minutes, and is what you add to GMT to get the localtime.  The U.S.
+ * is always at a negative offset, from -5h to -8h (can vary a little
+ * with DST,  I guess).  The Linux iso9660 filesystem has had the sign
+ * of this wrong for ages (mkisofs had it wrong too for the longest time).
+ */
+int FDECL2(iso9660_date,char *, result, time_t, ctime){
+  struct tm *local;
+  local = localtime(&ctime);
+  result[0] = local->tm_year;
+  result[1] = local->tm_mon + 1;
+  result[2] = local->tm_mday;
+  result[3] = local->tm_hour;
+  result[4] = local->tm_min;
+  result[5] = local->tm_sec;
+
+  /* 
+   * Must recalculate proper timezone offset each time,
+   * as some files use daylight savings time and some don't... 
+   */
+  result[6] = local->tm_yday;	/* save yday 'cause gmtime zaps it */
+  local = gmtime(&ctime);
+  local->tm_year -= result[0];
+  local->tm_yday -= result[6];
+  local->tm_hour -= result[3];
+  local->tm_min -= result[4];
+  if (local->tm_year < 0) 
+    {
+      local->tm_yday = -1;
+    }
+  else 
+    {
+      if (local->tm_year > 0) local->tm_yday = 1;
+    }
+
+  result[6] = -(local->tm_min + 60*(local->tm_hour + 24*local->tm_yday)) / 15;
+
+  return 0;
+}
+
+
+extern char * cdwrite_data;
+
+int FDECL2(main, int, argc, char **, argv){
+  char * outfile;
+  struct directory_entry de;
+  unsigned long mem_start;
+  struct stat statbuf;
+  char * scan_tree;
+  char * merge_image = NULL;
+  struct iso_directory_record * mrootp = NULL;
+  int c;
+#ifdef ADD_FILES
+  char *add_file_file = NULL;
+#endif
+
+  if (argc < 2)
+    usage();
+
+  /* Get the defaults from the .mkisofsrc file */
+  read_rcfile(argv[0]);
+
+  outfile = NULL;
+  while ((c = getopt(argc, argv, "i:o:V:RrfvaTp:P:b:c:x:dDlLNzA:M:m:C:")) != EOF)
+    switch (c)
+      {
+      case 'C':
+	/*
+	 * This is a temporary hack until cdwrite gets the proper hooks in
+	 * it.
+	 */
+	cdwrite_data = optarg;
+	break;
+      case 'a':
+	all_files++;
+	break;
+      case 'b':
+	use_eltorito++;
+	boot_image = optarg;  /* pathname of the boot image on cd */
+	if (boot_image == NULL) {
+	        fprintf(stderr,"Required boot image pathname missing\n");
+		exit(1);
+	}
+	break;
+      case 'c':
+	use_eltorito++;
+	boot_catalog = optarg;  /* pathname of the boot image on cd */
+	if (boot_catalog == NULL) {
+	        fprintf(stderr,"Required boot catalog pathname missing\n");
+		exit(1);
+	}
+	break;
+      case 'A':
+	appid = optarg;
+	if(strlen(appid) > 128) {
+		fprintf(stderr,"Application-id string too long\n");
+		exit(1);
+	};
+	break;
+      case 'd':
+	omit_period++;
+	break;
+      case 'D':
+	RR_relocation_depth = 32767;
+	break;
+      case 'f':
+	follow_links++;
+	break;
+      case 'i':
+#ifdef ADD_FILES
+	add_file_file = optarg;
+	break;
+#else
+	usage();
+	exit(1);
+#endif
+      case 'l':
+	full_iso9660_filenames++;
+	break;
+      case 'L':
+        allow_leading_dots++;
+        break;
+      case 'M':
+	merge_image = optarg;
+	break;
+      case 'N':
+	omit_version_number++;
+	break;
+      case 'o':
+	outfile = optarg;
+	break;
+      case 'p':
+	preparer = optarg;
+	if(strlen(preparer) > 128) {
+		fprintf(stderr,"Preparer string too long\n");
+		exit(1);
+	};
+	break;
+      case 'P':
+	publisher = optarg;
+	if(strlen(publisher) > 128) {
+		fprintf(stderr,"Publisher string too long\n");
+		exit(1);
+	};
+	break;
+      case 'R':
+	use_RockRidge++;
+	break;
+      case 'r':
+	rationalize++;
+	use_RockRidge++;
+	break;
+      case 'T':
+	generate_tables++;
+	break;
+      case 'V':
+	volume_id = optarg;
+	break;
+      case 'v':
+	verbose++;
+	break;
+      case 'z':
+#ifdef VMS
+	fprintf(stderr,"Transparent compression not supported with VMS\n");
+	exit(1);
+#else
+	transparent_compression++;
+#endif
+	break;
+      case 'm':
+        add_match(optarg);
+	break;
+      case 'x':
+        exclude(optarg);
+	break;
+      default:
+	usage();
+	exit(1);
+      }
+#ifdef __NetBSD__
+    {
+	int resource;
+    struct rlimit rlp;
+	if (getrlimit(RLIMIT_DATA,&rlp) == -1) 
+		perror("Warning: getrlimit");
+	else {
+		rlp.rlim_cur=33554432;
+		if (setrlimit(RLIMIT_DATA,&rlp) == -1)
+			perror("Warning: setrlimit");
+		}
+	}
+#endif
+#ifdef HAVE_SBRK
+  mem_start = (unsigned long) sbrk(0);
+#endif
+
+  if(verbose) fprintf(stderr,"%s\n", version_string);
+
+  if(     (cdwrite_data != NULL && merge_image == NULL)
+       || (cdwrite_data == NULL && merge_image != NULL) )
+    {
+      fprintf(stderr,"Multisession usage bug - both -C and -M must be specified.\n");
+      exit(0);
+    }
+
+  /*  The first step is to scan the directory tree, and take some notes */
+
+  scan_tree = argv[optind];
+
+#ifdef ADD_FILES
+  if (add_file_file) {
+    add_file(add_file_file);
+  }
+  add_file_list (argc, argv, optind+1);
+#endif
+
+  if(!scan_tree){
+	  usage();
+	  exit(1);
+  };
+
+#ifndef VMS
+  if(scan_tree[strlen(scan_tree)-1] != '/') {
+    scan_tree = (char *) e_malloc(strlen(argv[optind])+2);
+    strcpy(scan_tree, argv[optind]);
+    strcat(scan_tree, "/");
+  };
+#endif
+
+  if(use_RockRidge){
+#if 1
+	extension_record = generate_rr_extension_record("RRIP_1991A",
+				       "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
+				       "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE.  SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.", &extension_record_size);
+#else
+	extension_record = generate_rr_extension_record("IEEE_P1282",
+				       "THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
+				       "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION.", &extension_record_size);
+#endif
+  }
+
+  /*
+   * See if boot catalog file exists in root directory, if not
+   * we will create it.
+   */
+  if (use_eltorito)
+    init_boot_catalog(argv[optind]);
+
+  /*
+   * Find the device and inode number of the root directory.
+   * Record this in the hash table so we don't scan it more than
+   * once.
+   */
+  stat_filter(argv[optind], &statbuf);
+  add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
+
+  memset(&de, 0, sizeof(de));
+
+  de.filedir = root;  /* We need this to bootstrap */
+
+  if( merge_image != NULL )
+    {
+      mrootp = merge_isofs(merge_image);
+      if( mrootp == NULL )
+	{
+	  /*
+	   * Complain and die.
+	   */
+	  fprintf(stderr,"Unable to open previous session image %s\n",
+		  merge_image);
+	  exit(1);
+	}
+
+      memcpy(&de.isorec.extent, mrootp->extent, 8);      
+    }
+
+  /*
+   * Scan the actual directory (and any we find below it)
+   * for files to write out to the output image.
+   */
+  if (!scan_directory_tree(argv[optind], &de, mrootp))
+    {
+      exit(1);
+    }
+
+  /*
+   * Fix a couple of things in the root directory so that everything
+   * is self consistent.
+   */
+  root->self = root->contents;  /* Fix this up so that the path tables get done right */
+
+  if(reloc_dir) sort_n_finish(reloc_dir);
+
+  if (goof) exit(1);
+  
+  /*
+   * OK, ready to write the file.  Open it up, and generate the thing.
+   */
+  if (outfile){
+	  discimage = fopen(outfile, "w");
+	  if (!discimage){
+		  fprintf(stderr,"Unable to open disc image file\n");
+		  exit(1);
+
+	  };
+  } else
+	  discimage =  stdout;
+
+  /* Now assign addresses on the disc for the path table. */
+
+  path_blocks = (path_table_size + (SECTOR_SIZE - 1)) >> 11;
+  if (path_blocks & 1) path_blocks++;
+
+  path_table[0] = session_start + 0x10 + 2 + (use_eltorito ? 1 : 0);
+  path_table[1] = 0;
+  path_table[2] = path_table[0] + path_blocks;
+  path_table[3] = 0;
+
+  last_extent += path_table[2] - session_start + path_blocks;  
+		/* The next free block */
+
+  /* The next step is to go through the directory tree and assign extent
+     numbers for all of the directories */
+
+  assign_directory_addresses(root);
+
+  if(extension_record) {
+	  struct directory_entry * s_entry;
+	  extension_record_extent = last_extent++;
+	  s_entry = root->contents;
+	  set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 24,
+		  extension_record_extent);
+	  set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 8,
+		  extension_record_size);
+  };
+
+  if (use_RockRidge && reloc_dir)
+	  finish_cl_pl_entries();
+
+  /* Now we generate the path tables that are used by DOS to improve directory
+     access times. */
+  generate_path_tables();
+
+  /* Generate root record for volume descriptor. */
+  generate_root_record();
+
+  if (verbose)
+    dump_tree(root);
+
+  if( in_image != NULL )
+    {
+      fclose(in_image);
+    }
+
+  iso_write(discimage);
+
+#ifdef HAVE_SBRK
+  fprintf(stderr,"Max brk space used %x\n", 
+	  (unsigned int)(((unsigned long)sbrk(0)) - mem_start));
+#endif
+  fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9);
+#ifdef VMS
+  return 1;
+#else
+  return 0;
+#endif
+}
+
+void *
+FDECL1(e_malloc, size_t, size)
+{
+void* pt = 0;
+	if( (size > 0) && ((pt=malloc(size))==NULL) ) {
+		fprintf(stderr, "Not enough memory\n");
+		exit (1);
+		}
+return pt;
+}
diff --git a/mass_storage/mkisofs-1.11.3/mkisofs.h b/mass_storage/mkisofs-1.11.3/mkisofs.h
new file mode 100644
index 0000000..91d74d9
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/mkisofs.h
@@ -0,0 +1,339 @@
+/*
+ * Header file mkisofs.h - assorted structure definitions and typecasts.
+
+   Written by Eric Youngdale (1993).
+
+   Copyright 1993 Yggdrasil Computing, Incorporated
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * 	$Id: mkisofs.h,v 1.5 1997/05/17 15:50:28 eric Exp $
+ */
+
+/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */
+
+#include <stdio.h>
+
+/* This symbol is used to indicate that we do not have things like
+   symlinks, devices, and so forth available.  Just files and dirs */
+
+#ifdef VMS
+#define NON_UNIXFS
+#endif
+
+#ifdef DJGPP
+#define NON_UNIXFS
+#endif
+
+#ifdef VMS
+#include <dir.h>
+#define dirent direct
+#else
+#include <dirent.h>
+#endif
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef linux
+#include <dir.h>
+#endif
+
+#ifdef ultrix
+extern char *strdup();
+#endif
+
+#ifdef __STDC__
+#define DECL(NAME,ARGS) NAME ARGS
+#define FDECL1(NAME,TYPE0, ARG0) \
+	NAME(TYPE0 ARG0)
+#define FDECL2(NAME,TYPE0, ARG0,TYPE1, ARG1) \
+	NAME(TYPE0 ARG0, TYPE1 ARG1)
+#define FDECL3(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2) \
+	NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2)
+#define FDECL4(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3) \
+	NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3)
+#define FDECL5(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4) \
+	NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3, TYPE4 ARG4)
+#define FDECL6(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4, TYPE5, ARG5) \
+	NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3, TYPE4 ARG4, TYPE5 ARG5)
+#else
+#define DECL(NAME,ARGS) NAME()
+#define FDECL1(NAME,TYPE0, ARG0) NAME(ARG0) TYPE0 ARG0;
+#define FDECL2(NAME,TYPE0, ARG0,TYPE1, ARG1) NAME(ARG0, ARG1) TYPE0 ARG0; TYPE1 ARG1;
+#define FDECL3(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2) \
+	NAME(ARG0, ARG1, ARG2) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2;
+#define FDECL4(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3) \
+	NAME(ARG0, ARG1, ARG2, ARG3, ARG4) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3;
+#define FDECL5(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4) \
+	NAME(ARG0, ARG1, ARG2, ARG3, ARG4) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; TYPE4 ARG4;
+#define FDECL6(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4, TYPE5, ARG5) \
+	NAME(ARG0, ARG1, ARG2, ARG3, ARG4, ARG5) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; TYPE4 ARG4; TYPE5 ARG5;
+#define const
+#endif
+
+
+#ifdef __svr4__
+#include <stdlib.h>
+#else
+extern int optind;
+extern char *optarg;
+/* extern int getopt (int __argc, char **__argv, char *__optstring); */
+#endif
+
+#include "iso9660.h"
+#include "defaults.h"
+
+struct directory_entry{
+  struct directory_entry * next;
+  struct iso_directory_record isorec;
+  unsigned int starting_block;
+  unsigned int size;
+  unsigned int priority;
+  char * name;
+  char * table;
+  char * whole_name;
+  struct directory * filedir;
+  struct directory_entry * parent_rec;
+  unsigned int de_flags;
+  ino_t inode;  /* Used in the hash table */
+  dev_t dev;  /* Used in the hash table */
+  unsigned char * rr_attributes;
+  unsigned int rr_attr_size;
+  unsigned int total_rr_attr_size;
+};
+
+struct file_hash{
+  struct file_hash * next;
+  ino_t inode;  /* Used in the hash table */
+  dev_t dev;  /* Used in the hash table */
+  unsigned int starting_block;
+  unsigned int size;
+};
+  
+/* 
+ * This structure describes one complete directory.  It has pointers
+ * to other directories in the overall tree so that it is clear where
+ * this directory lives in the tree, and it also must contain pointers
+ * to the contents of the directory.  Note that subdirectories of this
+ * directory exist twice in this stucture.  Once in the subdir chain,
+ * and again in the contents chain.
+ */
+struct directory{
+  struct directory * next;  /* Next directory at same level as this one */
+  struct directory * subdir; /* First subdirectory in this directory */
+  struct directory * parent;
+  struct directory_entry * contents;
+  struct directory_entry * self;
+  char * whole_name;  /* Entire path */
+  char * de_name;  /* Entire path */
+  unsigned int ce_bytes;  /* Number of bytes of CE entries reqd for this dir */
+  unsigned int depth;
+  unsigned int size;
+  unsigned int extent;
+  unsigned short path_index;
+};
+
+struct deferred{
+  struct deferred * next;
+  unsigned int starting_block;
+  char * name;
+  struct directory * filedir;
+  unsigned int flags;
+};
+
+extern int goof;
+extern struct directory * root;
+extern struct directory * reloc_dir;
+extern unsigned int next_extent;
+extern unsigned int last_extent;
+extern unsigned int last_extent_written;
+extern unsigned int session_start;
+extern unsigned int path_table_size;
+extern unsigned int path_table[4];
+extern unsigned int path_blocks;
+extern char * path_table_l;
+extern char * path_table_m;
+extern struct iso_directory_record root_record;
+
+extern int use_eltorito;
+extern int use_RockRidge;
+extern int rationalize;
+extern int follow_links;
+extern int verbose;
+extern int all_files;
+extern int generate_tables;
+extern int omit_period;
+extern int omit_version_number;
+extern int transparent_compression;
+extern int RR_relocation_depth;
+extern int full_iso9660_filenames;
+
+/* tree.c */
+extern int DECL(stat_filter, (char *, struct stat *));
+extern void DECL(sort_n_finish,(struct directory *));
+extern void finish_cl_pl_entries();
+extern int DECL(scan_directory_tree,(char * path, 
+				     struct directory_entry * self,
+				     struct iso_directory_record *));
+extern void DECL(generate_iso9660_directories,(struct directory *, FILE*));
+extern void DECL(dump_tree,(struct directory * node));
+extern struct directory_entry * DECL(search_tree_file, (struct 
+				directory * node,char * filename));
+
+/* eltorito.c */
+extern void DECL(init_boot_catalog, (const char * path ));
+extern void DECL(get_torito_desc, (struct eltorito_boot_descriptor * path ));
+
+/* write.c */
+extern void DECL(assign_directory_addresses,(struct directory * root));
+extern int DECL(get_733,(char *));
+extern int DECL(isonum_733,(unsigned char *));
+extern void DECL(set_723,(char *, unsigned int));
+extern void DECL(set_731,(char *, unsigned int));
+extern void DECL(set_721,(char *, unsigned int));
+extern void DECL(set_733,(char *, unsigned int));
+extern void DECL(sort_directory,(struct directory_entry **));
+extern void generate_root_record();
+extern void DECL(generate_one_directory,(struct directory *, FILE*));
+extern void generate_path_tables();
+extern int DECL(iso_write,(FILE * outfile));
+extern void DECL(memcpy_max, (char *, char *, int));
+
+
+/* multi.c */
+
+extern FILE * in_image;
+extern struct iso_directory_record *
+	DECL(merge_isofs,(char * path)); 
+
+extern int DECL(free_mdinfo, (struct directory_entry **, int len));
+
+extern struct directory_entry ** 
+	DECL(read_merging_directory,(struct iso_directory_record *, int*));
+extern void 
+	DECL(merge_remaining_entries, (struct directory *, 
+				       struct directory_entry **, int));
+
+/* match.c */
+extern int DECL(matches, (char *));
+extern void DECL(add_match, (char *));
+
+/* files.c */
+struct dirent * DECL(readdir_add_files, (char **, char *, DIR *));
+
+/* */
+
+extern int DECL(iso9660_file_length,(const char* name, 
+			       struct directory_entry * sresult, int flag));
+extern int DECL(iso9660_date,(char *, time_t));
+extern void DECL(add_hash,(struct directory_entry *));
+extern struct file_hash * DECL(find_hash,(dev_t, ino_t));
+extern void DECL(add_directory_hash,(dev_t, ino_t));
+extern struct file_hash * DECL(find_directory_hash,(dev_t, ino_t));
+extern void flush_file_hash();
+extern int DECL(delete_file_hash,(struct directory_entry *));
+extern struct directory_entry * DECL(find_file_hash,(char *));
+extern void DECL(add_file_hash,(struct directory_entry *));
+extern int DECL(generate_rock_ridge_attributes,(char *, char *,
+					  struct directory_entry *, 
+					  struct stat *, struct stat *,
+					  int  deep_flag));
+extern char * DECL(generate_rr_extension_record,(char * id,  char  * descriptor,
+				    char * source, int  * size));
+
+extern int    DECL(check_prev_session, (struct directory_entry **, int len,
+				     struct directory_entry *,
+				     struct stat *,
+				     struct stat *,
+				     struct directory_entry **));
+
+#ifdef	USE_SCG
+/* scsi.c */
+extern	int	readsecs(int startsecno, void *buffer, int sectorcount);
+extern	int	scsidev_open(char *path);
+#endif
+
+extern char * extension_record;
+extern int extension_record_extent;
+extern int n_data_extents;
+
+/* These are a few goodies that can be specified on the command line, and  are
+   filled into the root record */
+
+extern char * preparer;
+extern char * publisher;
+extern char * copyright;
+extern char * biblio;
+extern char * abstract;
+extern char * appid;
+extern char * volset_id;
+extern char * system_id;
+extern char * volume_id;
+extern char * boot_catalog;
+extern char * boot_image;
+
+extern void * DECL(e_malloc,(size_t));
+
+
+#define SECTOR_SIZE (2048)
+#define ROUND_UP(X)    ((X + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
+
+#define NEED_RE 1
+#define NEED_PL  2
+#define NEED_CL 4
+#define NEED_CE 8
+#define NEED_SP 16
+
+#define PREV_SESS_DEV (sizeof(dev_t) >= 4 ? 0x7ffffffd : 0x7ffd)
+#define TABLE_INODE (sizeof(ino_t) >= 4 ? 0x7ffffffe : 0x7ffe)
+#define UNCACHED_INODE (sizeof(ino_t) >= 4 ? 0x7fffffff : 0x7fff)
+#define UNCACHED_DEVICE (sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff)
+
+#ifdef VMS
+#define STAT_INODE(X) (X.st_ino[0])
+#define PATH_SEPARATOR ']'
+#define SPATH_SEPARATOR ""
+#else
+#define STAT_INODE(X) (X.st_ino)
+#define PATH_SEPARATOR '/'
+#define SPATH_SEPARATOR "/"
+#endif
+
+/*
+ * When using multi-session, indicates that we can reuse the
+ * TRANS.TBL information for this directory entry.  If this flag
+ * is set for all entries in a directory, it means we can just
+ * reuse the TRANS.TBL and not generate a new one.
+ */
+#define SAFE_TO_REUSE_TABLE_ENTRY  1
+/*
+ * Volume sequence number to use in all of the iso directory records.
+ */
+#define DEF_VSN		1
+
+/*
+ * Make sure we have a definition for this.  If not, take a very conservative
+ * guess.  From what I can tell SunOS is the only one with this trouble.
+ */
+#ifndef NAME_MAX
+#ifdef FILENAME_MAX
+#define NAME_MAX	FILENAME_MAX
+#else
+#define NAME_MAX	128
+#endif
+#endif
diff --git a/mass_storage/mkisofs-1.11.3/mkisofs.spec b/mass_storage/mkisofs-1.11.3/mkisofs.spec
new file mode 100644
index 0000000..abc500b
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/mkisofs.spec
@@ -0,0 +1,44 @@
+# $Id: mkisofs.spec,v 1.4.2.1 1998/06/02 03:36:16 eric Exp $
+Summary: Creates a ISO9660 filesystem image
+Name: mkisofs
+Version: 1.11.3
+Release: 1
+Copyright: GPL
+Group: Utilities/System
+Source: tsx-11.mit.edu:/pub/linux/packages/mkisofs/mkisofs-1.11.3.tar.gz
+
+%description
+This is the mkisofs package.  It is used to create ISO 9660
+file system images for creating CD-ROMs. Now includes support
+for making bootable "El Torito" CD-ROMs.
+
+%prep
+%setup
+
+%build
+./configure --prefix=/usr
+make
+
+%install
+make install
+strip /usr/bin/mkisofs
+
+%changelog
+
+* Tue Feb 25 1997 Michael Fulbright <msf@redhat.com>
+
+ Updated to 1.10b7.
+
+* Wed Feb 12 1997 Michael Fulbright <msf@redhat.com>
+
+ Updated to 1.10b3.
+
+* Wed Feb 12 1997 Michael Fulbright <msf@redhat.com>
+
+ Added %doc line to spec file (was missing all docs before).
+
+%files
+%doc COPYING ChangeLog README README.eltorito TODO
+/usr/bin/mkisofs
+/usr/man/man8/mkisofs.8
+
diff --git a/mass_storage/mkisofs-1.11.3/multi.c b/mass_storage/mkisofs-1.11.3/multi.c
new file mode 100644
index 0000000..13ba6f6
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/multi.c
@@ -0,0 +1,1018 @@
+/*
+ * File multi.c - scan existing iso9660 image and merge into 
+ * iso9660 filesystem.  Used for multisession support.
+ *
+ * Written by Eric Youngdale (1996).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+ */
+
+static char rcsid[] ="$Id: multi.c,v 1.6.1.3 1998/06/02 03:00:25 eric Exp $";
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "config.h"
+
+#ifndef VMS
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#else
+#include <sys/file.h>
+#include <vms/fabdef.h>
+#include "vms.h"
+extern char * strdup(const char *);
+#endif
+
+#include "mkisofs.h"
+#include "iso9660.h"
+
+#define TF_CREATE 1
+#define TF_MODIFY 2
+#define TF_ACCESS 4
+#define TF_ATTRIBUTES 8
+
+static int  DECL(get_session_start, (int *));
+static int  DECL(merge_old_directory_into_tree, (struct directory_entry *,
+						 struct directory *));
+
+static int
+isonum_711 (unsigned char * p)
+{
+	return (*p & 0xff);
+}
+
+int
+isonum_721 (unsigned char * p)
+{
+	return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
+}
+
+static int
+isonum_723 (unsigned char * p)
+{
+#if 0
+	if (p[0] != p[3] || p[1] != p[2]) {
+		fprintf (stderr, "invalid format 7.2.3 number\n");
+		exit (1);
+	}
+#endif
+	return (isonum_721 (p));
+}
+
+int
+isonum_731 (unsigned char * p)
+{
+	return ((p[0] & 0xff)
+		| ((p[1] & 0xff) << 8)
+		| ((p[2] & 0xff) << 16)
+		| ((p[3] & 0xff) << 24));
+}
+
+int
+isonum_733 (unsigned char * p)
+{
+	return (isonum_731 (p));
+}
+
+FILE * in_image = NULL;
+
+#ifndef	USE_SCG
+/*
+ * Don't define readsecs if mkisofs is linked with
+ * the SCSI library.
+ * readsecs() will be implemented as SCSI command in this case.
+ *
+ * Use global var in_image directly in readsecs()
+ * the SCSI equivalent will not use a FILE* for I/O.
+ *
+ * The main point of this pointless abstraction is that Solaris won't let
+ * you read 2K sectors from the cdrom driver.  The fact that 99.9% of the
+ * discs out there have a 2K sectorsize doesn't seem to matter that much.
+ * Anyways, this allows the use of a scsi-generics type of interface on
+ * Solaris.
+ */
+static int
+readsecs(int startsecno, void *buffer, int sectorcount)
+{
+	int	f = fileno(in_image);
+
+	if (lseek(f, (off_t)startsecno * SECTOR_SIZE, 0) == (off_t)-1) {
+		fprintf(stderr," Seek error on old image\n");
+		exit(10);
+	}
+	return (read(f, buffer, sectorcount * SECTOR_SIZE));
+}
+#endif
+
+/*
+ * Parse the RR attributes so we can find the file name.
+ */
+static int 
+FDECL3(parse_rr, unsigned char *, pnt, int, len, struct directory_entry *,dpnt)
+{
+	int cont_extent, cont_offset, cont_size;
+	char name_buf[256];
+
+	cont_extent = cont_offset = cont_size = 0;
+
+	while(len >= 4){
+		if(pnt[3] != 1) {
+		  printf("**BAD RRVERSION");
+		  return -1;
+		};
+		if(strncmp((char *) pnt, "NM", 2) == 0) {
+		  strncpy(name_buf, (char *) pnt+5, pnt[2] - 5);
+		  name_buf[pnt[2] - 5] = 0;
+		  dpnt->name = strdup(name_buf);
+		  return 0;
+		}
+
+		if(strncmp((char *) pnt, "CE", 2) == 0) {
+			cont_extent = isonum_733(pnt+4);
+			cont_offset = isonum_733(pnt+12);
+			cont_size = isonum_733(pnt+20);
+		};
+
+		len -= pnt[2];
+		pnt += pnt[2];
+		if(len <= 3 && cont_extent) {
+		  unsigned char sector[SECTOR_SIZE];
+		  readsecs(cont_extent, sector, 1);
+		  parse_rr(&sector[cont_offset], cont_size, dpnt);
+		};
+	};
+	return 0;
+}
+
+
+static int 
+FDECL4(check_rr_dates, struct directory_entry *, dpnt, 
+       struct directory_entry *, current, 
+       struct stat *, statbuf, 
+       struct stat *,lstatbuf)
+{
+	int cont_extent, cont_offset, cont_size;
+	int offset;
+	unsigned char * pnt;
+	int len;
+	int same_file;
+	int same_file_type;
+	mode_t mode;
+	char time_buf[7];
+	
+	
+	cont_extent = cont_offset = cont_size = 0;
+	same_file = 1;
+	same_file_type = 1;
+
+	pnt = dpnt->rr_attributes;
+	len = dpnt->rr_attr_size;
+	/*
+	 * We basically need to parse the rr attributes again, and
+	 * dig out the dates and file types.
+	 */
+	while(len >= 4){
+		if(pnt[3] != 1) {
+		  printf("**BAD RRVERSION");
+		  return -1;
+		};
+
+		/*
+		 * If we have POSIX file modes, make sure that the file type
+		 * is the same.  If it isn't, then we must always
+		 * write the new file.
+		 */
+		if(strncmp((char *) pnt, "PX", 2) == 0) {
+		  mode = isonum_733(pnt + 4);
+		  if( (lstatbuf->st_mode & S_IFMT) != (mode & S_IFMT) )
+		    {
+		      same_file_type = 0;
+		      same_file = 0;
+		    }
+		}
+
+		if(strncmp((char *) pnt, "TF", 2) == 0) {
+		  offset = 5;
+		  if( pnt[4] & TF_CREATE )
+		    {
+		      iso9660_date((char *) time_buf, lstatbuf->st_ctime);
+		      if(memcmp(time_buf, pnt+offset, 7) == 0) 
+			same_file = 0;
+		      offset += 7;
+		    }
+		  if( pnt[4] & TF_MODIFY )
+		    {
+		      iso9660_date((char *) time_buf, lstatbuf->st_mtime);
+		      if(memcmp(time_buf, pnt+offset, 7) == 0) 
+			same_file = 0;
+		      offset += 7;
+		    }
+		}
+
+		if(strncmp((char *) pnt, "CE", 2) == 0) {
+			cont_extent = isonum_733(pnt+4);
+			cont_offset = isonum_733(pnt+12);
+			cont_size = isonum_733(pnt+20);
+		};
+
+		len -= pnt[2];
+		pnt += pnt[2];
+		if(len <= 3 && cont_extent) {
+		  unsigned char sector[SECTOR_SIZE];
+
+		  readsecs(cont_extent, sector, 1);
+		  parse_rr(&sector[cont_offset], cont_size, dpnt);
+		};
+	};
+
+	/*
+	 * If we have the same fundamental file type, then it is clearly
+	 * safe to reuse the TRANS.TBL entry.
+	 */
+	if( same_file_type )
+	  {
+	    current->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
+	  }
+
+	return same_file;
+}
+
+struct directory_entry **
+FDECL2(read_merging_directory, struct iso_directory_record *, mrootp,
+       int *, nent)
+{
+  unsigned char			* cpnt;
+  unsigned char			* cpnt1;
+  char				* dirbuff;
+  int				  i;
+  struct iso_directory_record	* idr;
+  int				  len;
+  struct directory_entry	**pnt;
+  int				  rlen;
+  struct directory_entry	**rtn;
+  int				  seen_rockridge;
+  unsigned char			* tt_buf;
+  int				  tt_extent;
+  int				  tt_size;
+
+  /*
+   * First, allocate a buffer large enough to read in the entire
+   * directory.
+   */
+  dirbuff = (char *) e_malloc(isonum_733((unsigned char *)mrootp->size));
+
+  readsecs(isonum_733((unsigned char *)mrootp->extent), dirbuff,
+	   isonum_733((unsigned char *)mrootp->size)/SECTOR_SIZE);
+
+  /*
+   * Next look over the directory, and count up how many entries we
+   * have.
+   */
+  len = isonum_733((unsigned char *)mrootp->size);
+  i = 0;
+  *nent = 0;
+  while(i < len )
+    {
+      idr = (struct iso_directory_record *) &dirbuff[i];
+      if(idr->length[0] == 0) 
+	{
+	  i = (i + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1);
+	  continue;
+	}
+      (*nent)++;
+      i += idr->length[0];
+    }
+
+  /*
+   * Now allocate the buffer which will hold the array we are
+   * about to return.
+   */
+  rtn = (struct directory_entry **) e_malloc(*nent * sizeof(*rtn));
+
+  /*
+   * Finally, scan the directory one last time, and pick out the
+   * relevant bits of information, and store it in the relevant
+   * bits of the structure.
+   */
+  i = 0;
+  pnt = rtn;
+  tt_extent = 0;
+  seen_rockridge = 0;
+  tt_size = 0;
+  while(i < len )
+    {
+      idr = (struct iso_directory_record *) &dirbuff[i];
+      if(idr->length[0] == 0) 
+	{
+	  i = (i + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1);
+	  continue;
+	}
+      *pnt = (struct directory_entry *) e_malloc(sizeof(**rtn));
+      (*pnt)->next = NULL;
+      (*pnt)->isorec = *idr;
+      (*pnt)->starting_block = isonum_733((unsigned char *)idr->extent);
+      (*pnt)->size = isonum_733((unsigned char *)idr->size);
+      (*pnt)->priority = 0;
+      (*pnt)->name = NULL;
+      (*pnt)->table = NULL;
+      (*pnt)->whole_name = NULL;
+      (*pnt)->filedir = NULL;
+      (*pnt)->parent_rec = NULL;
+      /*
+       * Set this information so that we correctly cache previous
+       * session bits of information.
+       */
+      (*pnt)->inode = (*pnt)->starting_block;
+      (*pnt)->dev = PREV_SESS_DEV;
+      (*pnt)->rr_attributes = NULL;
+      (*pnt)->rr_attr_size = 0;
+      (*pnt)->total_rr_attr_size = 0;
+      (*pnt)->de_flags = SAFE_TO_REUSE_TABLE_ENTRY;
+
+      /*
+       * Check for and parse any RR attributes for the file.
+       * All we are really looking for here is the original name
+       * of the file.
+       */
+      rlen = idr->length[0] & 0xff;
+      cpnt = (unsigned char *) idr;
+      
+      rlen -= sizeof(struct iso_directory_record);
+      cpnt += sizeof(struct iso_directory_record);
+      
+      rlen += sizeof(idr->name);
+      cpnt -= sizeof(idr->name);
+      
+      rlen -= idr->name_len[0];
+      cpnt += idr->name_len[0];
+      
+      if((idr->name_len[0] & 1) == 0){
+	cpnt++;
+	rlen--;
+      };
+
+      if( rlen != 0 )
+	{
+	  (*pnt)->total_rr_attr_size =  (*pnt)->rr_attr_size = rlen;
+	  (*pnt)->rr_attributes = e_malloc(rlen);
+	  memcpy((*pnt)->rr_attributes,  cpnt, rlen);
+	  seen_rockridge = 1;
+	}
+
+      /*
+       * Now zero out the remainder of the name field.
+       */
+      cpnt = (unsigned char *) &(*pnt)->isorec.name;
+      cpnt += idr->name_len[0];
+      memset(cpnt, 0, sizeof((*pnt)->isorec.name) - idr->name_len[0]);
+
+      parse_rr((*pnt)->rr_attributes, rlen, *pnt);
+      
+      if(    ((*pnt)->isorec.name_len[0] == 1)
+	  && (    ((*pnt)->isorec.name[0] == 0)
+	       || ((*pnt)->isorec.name[0] == 1)) )
+	{
+	  if( (*pnt)->name != NULL )
+	    {
+	      free((*pnt)->name);
+	    }
+	  if( (*pnt)->whole_name != NULL )
+	    {
+	      free((*pnt)->whole_name);
+	    }
+	  if( (*pnt)->isorec.name[0] == 0 )
+	    {
+	      (*pnt)->name = strdup(".");
+	    }
+	  else
+	    {
+	      (*pnt)->name = strdup("..");
+	    }
+	}
+
+      if( strncmp(idr->name, "TRANS.TBL", 9) == 0)
+	{
+	  if( (*pnt)->name != NULL )
+	    {
+	      free((*pnt)->name);
+	    }
+	  if( (*pnt)->whole_name != NULL )
+	    {
+	      free((*pnt)->whole_name);
+	    }
+	  (*pnt)->name = strdup("<translation table>");
+	  tt_extent = isonum_733((unsigned char *)idr->extent);
+	  tt_size = isonum_733((unsigned char *)idr->size);
+	}
+      
+      pnt++;
+      i += idr->length[0];
+    }
+
+  /*
+   * If there was a TRANS.TBL;1 entry, then grab it, read it, and use it
+   * to get the filenames of the files.  Also, save the table info, just
+   * in case we need to use it.
+   */
+  if( tt_extent != 0 && tt_size != 0 )
+    {
+      tt_buf = (unsigned char *) e_malloc(tt_size);
+      readsecs(tt_extent, tt_buf, tt_size/SECTOR_SIZE);
+
+      /*
+       * Loop through the file, examine each entry, and attempt to
+       * attach it to the correct entry.
+       */
+      cpnt = tt_buf;
+      cpnt1 = tt_buf;
+      while( cpnt - tt_buf < tt_size )
+	{
+	  while(*cpnt1 != '\n' && *cpnt1 != '\0')  cpnt1++;
+	  *cpnt1 = '\0';
+
+	  for(pnt = rtn, i = 0; i <*nent; i++, pnt++)
+	    {
+	      rlen = isonum_711((*pnt)->isorec.name_len);
+	      if( strncmp((char *) cpnt + 2, (*pnt)->isorec.name,
+			  rlen) == 0 
+		  && cpnt[2+rlen] == ' ')
+		{
+		  (*pnt)->table = e_malloc(strlen((char*)cpnt) - 34);
+		  sprintf((*pnt)->table, "%c\t%s\n",
+			  *cpnt, cpnt+37);
+		  if( (*pnt)->name == NULL )
+		    {
+		      (*pnt)->name = strdup((char *) cpnt+37);
+		    }
+		  break;
+		}
+	    }
+	  cpnt = cpnt1 + 1;
+	  cpnt1 = cpnt;
+	}
+      
+      free(tt_buf);
+    }
+  else if( !seen_rockridge )
+    {
+      /*
+       * This is a fatal error right now because we must have some mechanism
+       * for taking the 8.3 names back to the original unix names.
+       * In principle we could do this the hard way, and try and translate
+       * the unix names that we have seen forwards, but this would be
+       * a real pain in the butt.
+       */
+      fprintf(stderr,"Previous session must have either Rock Ridge (-R) or\n");
+      fprintf(stderr,"TRANS.TBL (-T) for mkisofs to be able to correctly\n");
+      fprintf(stderr,"generate additional sessions.\n");
+      exit(3);
+    }
+
+  if( dirbuff != NULL )
+    {
+      free(dirbuff);
+    }
+  
+  return rtn;
+}
+
+/*
+ * Free any associated data related to the structures.
+ */
+int 
+FDECL2(free_mdinfo, struct directory_entry **  , ptr, int, len )
+{
+  int		i;
+  struct directory_entry **p;
+
+  p = ptr;
+  for(i=0; i<len; i++, p++)
+    {
+      /*
+       * If the tree-handling code decided that it needed an entry,
+       * it will have removed it from the list.  Thus we must allow
+       * for null pointers here.
+       */
+      if( *p == NULL )
+	{
+	  continue;
+	}
+
+      if( (*p)->name != NULL )
+	{
+	  free((*p)->name);
+	}
+
+      if( (*p)->whole_name != NULL )
+	{
+	  free((*p)->whole_name);
+	}
+
+      if( (*p)->rr_attributes != NULL )
+	{
+	  free((*p)->rr_attributes);
+	}
+
+      if( (*p)->table != NULL )
+	{
+	  free((*p)->table);
+	}
+
+      free(*p);
+
+    }
+
+  free(ptr);
+  return 0;
+}
+
+/*
+ * Search the list to see if we have any entries from the previous
+ * session that match this entry.  If so, copy the extent number
+ * over so we don't bother to write it out to the new session.
+ */
+
+int
+FDECL6(check_prev_session, struct directory_entry **  , ptr, int, len,
+       struct directory_entry *, curr_entry,
+       struct stat *, statbuf, struct stat *, lstatbuf,
+       struct directory_entry **, odpnt)
+{
+  int		i;
+
+  for( i=0; i < len; i++ )
+    {
+      if( ptr[i] == NULL )
+	{
+	  continue;
+	}
+
+#if 0
+      if( ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1
+	  && ptr[i]->name[0] == '\0' )
+	{
+	  continue;
+	}
+      if( ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1
+	  && ptr[i]->name[0] == 1)
+	{
+	  continue;
+	}
+#else
+      if( ptr[i]->name != NULL && strcmp(ptr[i]->name, ".") == 0 )
+	{
+	  continue;
+	}
+      if( ptr[i]->name != NULL  && strcmp(ptr[i]->name, "..") == 0 )
+	{
+	  continue;
+	}
+#endif
+
+      if(    ptr[i]->name != NULL
+	  && strcmp(ptr[i]->name, curr_entry->name) != 0 )
+	{
+	  continue;
+	}
+
+      /*
+       * We know that the files have the same name.  If they also have
+       * the same file type (i.e. file, dir, block, etc), then we
+       * can safely reuse the TRANS.TBL entry for this file.
+       * The check_rr_dates function will do this for us.
+       *
+       * Verify that the file type and dates are consistent.
+       * If not, we probably have a different file, and we need
+       * to write it out again.
+       */
+      if(    (ptr[i]->rr_attributes != NULL)
+	  && (check_rr_dates(ptr[i], curr_entry, statbuf, lstatbuf)) )
+	{
+	  goto found_it;
+	}
+
+
+      /*
+       * Verify size and timestamp.  If rock ridge is in use, we need
+       * to compare dates from RR too.  Directories are special, we
+       * calculate their size later.
+       */
+      if(     (curr_entry->isorec.flags[0] & 2) == 0
+	  &&  ptr[i]->size != curr_entry->size )
+	{
+	  goto found_it;
+	}
+
+      if( memcmp(ptr[i]->isorec.date, curr_entry->isorec.date,7) != 0 )
+	{
+	  goto found_it;
+	}
+
+      /*
+       * Never ever reuse directory extents.  See comments in
+       * tree.c for an explaination of why this must be the case.
+       */
+      if( (curr_entry->isorec.flags[0] & 2) != 0 )
+	{
+	  goto found_it;
+	}
+
+      memcpy(curr_entry->isorec.extent, ptr[i]->isorec.extent, 8);
+      curr_entry->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
+      goto found_it;
+    }
+  return 0;
+
+found_it:
+  if( odpnt != NULL )
+    {
+      *odpnt = ptr[i];
+    }
+  else
+    {
+      free(ptr[i]);
+    }
+  ptr[i] = NULL;
+  return 0;
+}
+
+/*
+ * merge_isofs:  Scan an existing image, and return a pointer
+ * to the root directory for this image.
+ */
+struct iso_directory_record * FDECL1(merge_isofs, char *, path)
+{
+  char				  buffer[SECTOR_SIZE];
+  int				  file_addr;
+  int				  i;
+  struct iso_primary_descriptor * pri = NULL;
+  struct iso_directory_record   * rootp;
+  struct iso_volume_descriptor  * vdp;
+
+  /*
+   * Start by opening up the image and searching for the volume header.
+   * Ultimately, we need to search for volume headers in multiple places
+   * because we might be starting with a multisession image.
+   * FIXME(eric).
+   */
+
+#ifndef	USE_SCG
+  in_image = fopen(path, "rb");
+  if( in_image == NULL )
+    {
+      return NULL;
+    }
+#else
+  if (strchr(path, '/')) {
+	in_image = fopen(path, "rb");
+	if( in_image == NULL ) {
+		return NULL;
+	}
+  } else {
+	if (scsidev_open(path) < 0)
+		return NULL;
+  }
+#endif
+
+  get_session_start(&file_addr);
+
+  for(i = 0; i< 100; i++)
+    {
+      if (readsecs(file_addr/SECTOR_SIZE, &buffer,
+		   sizeof(buffer)/SECTOR_SIZE) != sizeof(buffer))
+	{
+	  fprintf(stderr," Read error on old image %s\n", path);
+	  exit(10);
+	}
+
+      vdp = (struct iso_volume_descriptor *)buffer;
+
+      if(    (strncmp(vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0)
+	  && (isonum_711((unsigned char *) vdp->type) == ISO_VD_PRIMARY) )
+	{
+	  break;
+	}
+      file_addr += SECTOR_SIZE;
+    }
+
+  if( i == 100 )
+    {
+      return NULL;
+    }
+
+  pri = (struct iso_primary_descriptor *)vdp;
+
+  /*
+   * Check the blocksize of the image to make sure it is compatible.
+   */
+  if(    (isonum_723 ((unsigned char *) pri->logical_block_size) != SECTOR_SIZE)
+      || (isonum_723 ((unsigned char *) pri->volume_set_size) != 1) )
+    {
+      return NULL;
+    }
+
+  /*
+   * Get the location and size of the root directory.
+   */
+  rootp = (struct iso_directory_record *) 
+    malloc(sizeof(struct iso_directory_record));
+
+  memcpy(rootp, pri->root_directory_record, sizeof(*rootp));
+
+  return rootp;
+}
+
+void FDECL3(merge_remaining_entries, struct directory *, this_dir,
+	    struct directory_entry **, pnt,
+	    int, n_orig)
+{
+  int i;
+  struct directory_entry * s_entry;
+  unsigned int ttbl_extent = 0;
+  unsigned int ttbl_index  = 0;
+
+  /*
+   * Whatever is leftover in the list needs to get merged back
+   * into the directory.
+   */
+  for( i=0; i < n_orig; i++ )
+    {
+      if( pnt[i] == NULL )
+	{
+	  continue;
+	}
+      
+      if( pnt[i]->name != NULL
+	  && strcmp(pnt[i]->name, "<translation table>") == 0 )
+	{
+	  ttbl_extent = isonum_733((unsigned char *) pnt[i]->isorec.extent);
+	  ttbl_index = i;
+	  continue;
+	}
+      /*
+       * Skip directories for now - these need to be treated
+       * differently.
+       */
+      if( (pnt[i]->isorec.flags[0] & 2) != 0 )
+	{
+	  /*
+	   * FIXME - we need to insert this directory into the
+	   * tree, so that the path tables we generate will
+	   * be correct.
+	   */
+	  if(    (strcmp(pnt[i]->name, ".") == 0)
+	      || (strcmp(pnt[i]->name, "..") == 0) )
+	    {
+	      free(pnt[i]);
+	      pnt[i] = NULL;
+	      continue;
+	    }
+	  else
+	    {
+	      merge_old_directory_into_tree(pnt[i], this_dir);
+	    }
+	}
+      pnt[i]->next = this_dir->contents;
+      pnt[i]->filedir = this_dir;
+      this_dir->contents = pnt[i];
+      pnt[i] = NULL;
+    }
+  
+
+  /*
+   * If we don't have an entry for the translation table, then
+   * don't bother trying to copy the starting extent over.
+   * Note that it is possible that if we are copying the entire
+   * directory, the entry for the translation table will have already
+   * been inserted into the linked list and removed from the old
+   * entries list, in which case we want to leave the extent number
+   * as it was before.
+   */
+  if( ttbl_extent == 0 )
+    {
+      return;
+    }
+
+  /*
+   * Finally, check the directory we are creating to see whether
+   * there are any new entries in it.  If there are not, we can
+   * reuse the same translation table.
+   */
+  for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
+    {
+      /*
+       * Don't care about '.' or '..'.  They are never in the table
+       * anyways.
+       */
+      if( s_entry->name != NULL && strcmp(s_entry->name, ".") == 0 )
+	{
+	  continue;
+	}
+      if( s_entry->name != NULL && strcmp(s_entry->name, "..") == 0 )
+	{
+	  continue;
+	}
+      if( strcmp(s_entry->name, "<translation table>") == 0)
+	{
+	  continue;
+	}
+      if( (s_entry->de_flags & SAFE_TO_REUSE_TABLE_ENTRY) == 0 )
+	{
+	  return;
+	}
+    }
+
+  /*
+   * Locate the translation table, and re-use the same extent.
+   * It isn't clear that there should ever be one in there already
+   * so for now we try and muddle through the best we can.
+   */
+  for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
+    {
+      if( strcmp(s_entry->name, "<translation table>") == 0)
+	{
+	  fprintf(stderr,"Should never get here\n");
+	  set_733(s_entry->isorec.extent, ttbl_extent);
+	  return;
+	}
+    }
+
+  pnt[ttbl_index]->next = this_dir->contents;
+  pnt[ttbl_index]->filedir = this_dir;
+  this_dir->contents = pnt[ttbl_index];
+  pnt[ttbl_index] = NULL;
+}
+
+
+/*
+ * Here we have a case of a directory that has completely disappeared from
+ * the face of the earth on the tree we are mastering from.  Go through and
+ * merge it into the tree, as well as everything beneath it.
+ *
+ * Note that if a directory has been moved for some reason, this will
+ * incorrectly pick it up and attempt to merge it back into the old
+ * location.  FIXME(eric).
+ */
+static int
+FDECL2(merge_old_directory_into_tree, struct directory_entry *, dpnt, 
+       struct directory *, parent)
+{
+  struct directory_entry	**contents = NULL;
+  int				  i;
+  int				  n_orig;
+  struct directory		* this_dir, *next_brother;
+  char				  whole_path[1024];
+
+  this_dir = (struct directory *) e_malloc(sizeof(struct directory));
+  this_dir->next = NULL;
+  this_dir->subdir = NULL;
+  this_dir->self = dpnt;
+  this_dir->contents = NULL;
+  this_dir->size = 0;
+  this_dir->extent = 0;
+  this_dir->depth = parent->depth + 1;
+  this_dir->parent = parent;
+  if(!parent->subdir)
+    parent->subdir = this_dir;
+  else {
+    next_brother = parent->subdir;
+    while(next_brother->next) next_brother = next_brother->next;
+    next_brother->next = this_dir;
+  }
+
+  /*
+   * Set the name for this directory.
+   */
+  strcpy(whole_path, parent->de_name);
+  strcat(whole_path, SPATH_SEPARATOR);
+  strcat(whole_path, dpnt->name);
+  this_dir->de_name = strdup(whole_path);
+  this_dir->whole_name = strdup(whole_path);
+
+  /*
+   * Now fill this directory using information from the previous
+   * session.
+   */
+  contents = read_merging_directory(&dpnt->isorec, &n_orig);
+  /*
+   * Start by simply copying the '.', '..' and non-directory
+   * entries to this directory.  Technically we could let
+   * merge_remaining_entries handle this, but it gets rather confused
+   * by the '.' and '..' entries.
+   */
+  for(i=0; i < n_orig; i ++ )
+    {
+      /*
+       * We can always reuse the TRANS.TBL in this particular case.
+       */
+      contents[i]->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;	
+
+      if(    ((contents[i]->isorec.flags[0] & 2) != 0)
+	  && (i >= 2) )
+	{
+	  continue;
+	}
+
+      /*
+       * If we have a directory, don't reuse the extent number.
+       */
+      if( (contents[i]->isorec.flags[0] & 2) != 0 )
+	{
+	  memset(contents[i]->isorec.extent, 0, 8);
+	}
+
+      contents[i]->next = this_dir->contents;
+      contents[i]->filedir = this_dir;
+      this_dir->contents = contents[i];
+      contents[i] = NULL;
+    }
+
+  /*
+   * Zero the extent number for ourselves.
+   */
+  memset(dpnt->isorec.extent, 0, 8);
+
+  /*
+   * Anything that is left are other subdirectories that need to be merged.
+   */
+  merge_remaining_entries(this_dir, contents, n_orig);
+  free_mdinfo(contents, n_orig);
+  sort_n_finish(this_dir);
+
+  return 0;
+}
+
+
+char * cdwrite_data = NULL;
+
+static int
+FDECL1(get_session_start, int *, file_addr) 
+{
+  char * pnt;
+
+#ifdef CDWRITE_DETERMINES_FIRST_WRITABLE_ADDRESS
+  /*
+   * FIXME(eric).  We need to coordinate with cdwrite to obtain
+   * the parameters.  For now, we assume we are writing the 2nd session,
+   * so we start from the session that starts at 0.
+   */
+
+  *file_addr = (16 << 11);
+
+  /*
+   * We need to coordinate with cdwrite to get the next writable address
+   * from the device.  Here is where we use it.
+   */
+  session_start = last_extent = last_extent_written = cdwrite_result();
+
+#else
+
+  if( cdwrite_data == NULL )
+    {
+      fprintf(stderr,"Special parameters for cdwrite not specified with -C\n");
+      exit(1);
+    }
+
+  /*
+   * Next try and find the ',' in there which delimits the two numbers.
+   */
+  pnt = strchr(cdwrite_data, ',');
+  if( pnt == NULL )
+    {
+      fprintf(stderr, "Malformed cdwrite parameters\n");
+      exit(1);
+    }
+
+  *pnt = '\0';
+  *file_addr = atol(cdwrite_data) * SECTOR_SIZE;
+  pnt++;
+
+  session_start = last_extent = last_extent_written = atol(pnt);
+
+  pnt--;
+  *pnt = ',';
+
+#endif
+  return 0;
+}
+
diff --git a/mass_storage/mkisofs-1.11.3/name.c b/mass_storage/mkisofs-1.11.3/name.c
new file mode 100644
index 0000000..10475d4
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/name.c
@@ -0,0 +1,390 @@
+/*
+ * File name.c - map full Unix file names to unique 8.3 names that
+ * would be valid on DOS.
+ *
+
+   Written by Eric Youngdale (1993).
+
+   Copyright 1993 Yggdrasil Computing, Incorporated
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+static char rcsid[] ="$Id: name.c,v 1.7 1997/11/09 16:42:51 eric Exp $";
+
+#include "mkisofs.h"
+
+#include <ctype.h>
+
+extern int allow_leading_dots;
+   
+/*
+ * Function:	iso9660_file_length
+ *
+ * Purpose:	Map file name to 8.3 format, return length
+ *		of result.
+ *
+ * Arguments:	name	file name we need to map.
+ *		sresult	directory entry structure to contain mapped name.
+ *		dirflag	flag indicating whether this is a directory or not.
+ *
+ * Notes:	This procedure probably needs to be rationalized somehow.
+ *		New options to affect the behavior of this function
+ *		would also be nice to have.
+ */
+int FDECL3(iso9660_file_length,
+	   const char*, name, 
+	   struct directory_entry *, sresult, 
+	   int, dirflag)
+{
+  char		* c;
+  int		  chars_after_dot  = 0;
+  int		  chars_before_dot = 0;
+  int		  current_length   = 0;
+  int		  extra		   = 0;
+  int		  ignore	   = 0;
+  char		* last_dot;
+  const char	* pnt;
+  int		  priority	   = 32767;
+  char		* result;
+  int		  seen_dot	   = 0;
+  int		  seen_semic	   = 0;
+  int		  tildes	   = 0;
+
+  result = sresult->isorec.name;
+
+  /*
+   * For the '.' entry, generate the correct record, and return
+   * 1 for the length.
+   */
+  if(strcmp(name,".") == 0)
+    {
+      if(result) 
+	{
+	  *result = 0;
+	}
+      return 1;
+    }
+
+  /*
+   * For the '..' entry, generate the correct record, and return
+   * 1 for the length.
+   */
+  if(strcmp(name,"..") == 0)
+    {
+      if(result) 
+	{
+	  *result++ = 1;
+	  *result++ = 0;
+	}
+      return 1;
+    }
+
+  /*
+   * Now scan the directory one character at a time, and figure out
+   * what to do.
+   */
+  pnt = name;
+
+  /*
+   * Find the '.' that we intend to use for the extension.  Usually this
+   * is the last dot, but if we have . followed by nothing or a ~, we
+   * would consider this to be unsatisfactory, and we keep searching.
+   */
+  last_dot = strrchr (pnt,'.');
+  if(    (last_dot != NULL)
+      && (    (last_dot[1] == '~')
+	   || (last_dot[1] == '\0')
+	   || (last_dot[1] == '\0')) )
+    {
+      c = last_dot;
+      *c = '\0';
+      last_dot = strrchr (pnt,'.');
+      *c = '.';
+    }
+
+  while(*pnt)
+    {
+#ifdef VMS
+      if( strcmp(pnt,".DIR;1") == 0 ) 
+	{
+	  break;
+	}
+#endif
+
+      /*
+       * This character indicates a Unix style of backup file
+       * generated by some editors.  Lower the priority of
+       * the file.
+       */
+      if(*pnt == '#') 
+	{
+	  priority = 1; 
+	  pnt++; 
+	  continue; 
+	}
+
+      /*
+       * This character indicates a Unix style of backup file
+       * generated by some editors.  Lower the priority of
+       * the file.
+       */
+      if(*pnt == '~') 
+	{
+	  priority = 1; 
+	  tildes++; 
+	  pnt++; 
+	  continue;
+	}
+
+      /*
+       * This might come up if we had some joker already try and put
+       * iso9660 version numbers into the file names.  This would be
+       * a silly thing to do on a Unix box, but we check for it
+       * anyways.  If we see this, then we don't have to add our
+       * own version number at the end.
+       */
+      if(*pnt == ';') 
+	{
+	  seen_semic = 1; 
+	  *result++ = *pnt++; 
+	  continue; 
+	}
+
+      /*
+       * If we have a name with multiple '.' characters, we ignore everything
+       * after we have gotten the extension.
+       */
+      if(ignore) 
+	{
+	  pnt++; 
+	  continue;
+	}
+
+      /*
+       * Spin past any iso9660 version number we might have.
+       */
+      if(seen_semic)
+	{
+	  if(*pnt >= '0' && *pnt <= '9') 
+	    {
+	      *result++ = *pnt;
+	    }
+	  extra++;
+	  pnt++;
+	  continue;
+	}
+
+	/*
+	 * If we have full names, the names we generate will not
+	 * work on a DOS machine, since they are not guaranteed
+	 * to be 8.3.  Nonetheless, in many cases this is a useful
+	 * option.  We still only allow one '.' character in the
+	 * name, however.
+	 */
+      if(full_iso9660_filenames) 
+	{
+	  /* Here we allow a more relaxed syntax. */
+	  if(*pnt == '.') 
+	    {
+	      if (seen_dot) 
+		{
+		  ignore++; 
+		  continue;
+		}
+	      seen_dot++;
+	    }
+	  if(current_length < 30) 
+	    {
+	      if( *pnt < 0 )
+		{
+		  *result++ = '_';
+		}
+	      else
+		{
+		  *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt);
+		}
+	    }
+	}
+      else
+	{ 
+	  /* 
+	   * Dos style filenames.  We really restrict the
+	   * names here.
+	   */
+	  /* It would be nice to have .tar.gz transform to .tgz,
+	   * .ps.gz to .psz, ...
+	   */
+	  if(*pnt == '.') 
+	    {
+	      if (!chars_before_dot && !allow_leading_dots) 
+		{
+		  /* DOS can't read files with dot first */
+		  chars_before_dot++;
+		  if (result) 
+		    {
+		      *result++ = '_'; /* Substitute underscore */
+		    }
+		}
+	      else if( pnt != last_dot )
+		{
+		  /*
+		   * If this isn't the dot that we use for the extension,
+		   * then change the character into a '_' instead.
+		   */
+		  if(chars_before_dot < 8) 
+		    {
+		      chars_before_dot++;
+		      if(result) 
+			{
+			  *result++ = '_';
+			}
+		    }
+		}
+	      else 
+		{
+		  if (seen_dot) 
+		    {
+		      ignore++; continue;
+		    }
+		  if(result) 
+		    {
+		      *result++ = '.';
+		    }
+		  seen_dot++;
+		}
+	    }
+	  else 
+	    {
+	      if(    (seen_dot && (chars_after_dot < 3) && ++chars_after_dot)
+		     || (!seen_dot && (chars_before_dot < 8) && ++chars_before_dot) )
+		{
+		  if(result) 
+		    {
+		      switch (*pnt) 
+			{
+			default:
+			  if( *pnt < 0 )
+			    {
+			      *result++ = '_';
+			    }
+			  else
+			    {
+			      *result++ = islower(*pnt) ? toupper(*pnt) : *pnt;
+			    }
+			  break;
+
+			/* 
+			 * Descriptions of DOS's 'Parse Filename'
+			 * (function 29H) describes V1 and V2.0+
+			 * separator and terminator characters.
+			 * These characters in a DOS name make
+			 * the file visible but un-manipulable
+			 * (all useful operations error off.
+			 */
+			/* separators */
+			case '+':
+			case '=':
+			case '%': /* not legal DOS filename */
+			case ':':
+			case ';': /* already handled */
+			case '.': /* already handled */
+			case ',': /* already handled */
+			case '\t':
+			case ' ':
+			  /* V1 only separators */
+			case '/':
+			case '"':
+			case '[':
+			case ']':
+			  /* terminators */
+			case '>':
+			case '<':
+			case '|':
+			  /* Hmm - what to do here?  Skip?
+			   * Win95 looks like it substitutes '_'
+			   */
+			  *result++ = '_';
+			  break;
+			} /* switch (*pnt) */
+		    } /* if (result) */
+		} /* if (chars_{after,before}_dot) ... */
+	    } /* else *pnt == '.' */
+	} /* else DOS file names */
+      current_length++;
+      pnt++;
+    } /* while (*pnt) */
+  
+  /*
+   * OK, that wraps up the scan of the name.  Now tidy up a few other
+   * things.
+   */
+
+  /*
+   * Look for emacs style of numbered backups, like foo.c.~3~.  If
+   * we see this, convert the version number into the priority
+   * number.  In case of name conflicts, this is what would end
+   * up being used as the 'extension'.
+   */
+  if(tildes == 2)
+    {
+      int prio1 = 0;
+      pnt = name;
+      while (*pnt && *pnt != '~') 
+	{
+	  pnt++;
+	}
+      if (*pnt) 
+	{
+	  pnt++;
+	}
+      while(*pnt && *pnt != '~')
+	{
+	  prio1 = 10*prio1 + *pnt - '0';
+	  pnt++;
+	}
+      priority = prio1;
+    }
+  
+  /*
+   * If this is not a directory, force a '.' in case we haven't
+   * seen one, and add a version number if we haven't seen one
+   * of those either.
+   */
+  if (!dirflag)
+    {
+      if (!seen_dot && !omit_period) 
+	{
+	  if (result) *result++ = '.'; 
+	  extra++;
+	}
+      if(!omit_version_number && !seen_semic) 
+	{
+	  if(result)
+	    {
+	      *result++ = ';';
+	      *result++ = '1';
+	    };
+	  extra += 2;
+	}
+    }
+		    
+  if(result) 
+    {
+      *result++ = 0;
+    }
+  sresult->priority = priority;
+
+  return (chars_before_dot + chars_after_dot + seen_dot + extra);
+}
diff --git a/mass_storage/mkisofs-1.11.3/rock.c b/mass_storage/mkisofs-1.11.3/rock.c
new file mode 100644
index 0000000..47cba55
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/rock.c
@@ -0,0 +1,556 @@
+/*
+ * File rock.c - generate RRIP  records for iso9660 filesystems.
+
+   Written by Eric Youngdale (1993).
+
+   Copyright 1993 Yggdrasil Computing, Incorporated
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+static char rcsid[] ="$Id: rock.c,v 1.3 1997/05/17 15:45:26 eric Exp $";
+
+#include <stdlib.h>
+
+#include "config.h"
+
+#ifndef VMS
+#if defined(MAJOR_IN_SYSMACROS)
+#include <sys/sysmacros.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#endif
+#if defined(MAJOR_IN_MKDEV)
+#include <sys/types.h>
+#include <sys/mkdev.h>
+#endif
+
+#include "mkisofs.h"
+#include "iso9660.h"
+#include <string.h>
+
+#ifdef NON_UNIXFS
+#define S_ISLNK(m)	(0)
+#else
+#ifndef S_ISLNK
+#define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)
+#endif
+#endif
+
+#define SU_VERSION 1
+
+#define SL_ROOT    8
+#define SL_PARENT  4
+#define SL_CURRENT 2
+#define SL_CONTINUE 1
+
+#define CE_SIZE 28
+#define CL_SIZE 12
+#define ER_SIZE 8
+#define NM_SIZE 5
+#define PL_SIZE 12
+#define PN_SIZE 20
+#define PX_SIZE 36
+#define RE_SIZE 4
+#define SL_SIZE 20
+#define ZZ_SIZE 15
+#ifdef __QNX__
+#define TF_SIZE (5 + 4 * 7)
+#else
+#define TF_SIZE (5 + 3 * 7)
+#endif
+
+/* If we need to store this number of bytes, make sure we
+   do not box ourselves in so that we do not have room for
+   a CE entry for the continuation record */
+
+#define MAYBE_ADD_CE_ENTRY(BYTES) \
+    (BYTES + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0) 
+
+/*
+ * Buffer to build RR attributes
+ */
+
+static unsigned char Rock[16384];
+static unsigned char symlink_buff[256];
+static int ipnt = 0;
+static int recstart = 0;
+static int currlen = 0;
+static int mainrec = 0;
+static int reclimit;
+
+static void add_CE_entry(){
+          if(recstart)
+	    set_733((char*)Rock + recstart - 8, ipnt + 28 - recstart);
+	  Rock[ipnt++] ='C';
+	  Rock[ipnt++] ='E';
+	  Rock[ipnt++] = CE_SIZE;
+	  Rock[ipnt++] = SU_VERSION;
+	  set_733((char*)Rock + ipnt, 0);
+	  ipnt += 8;
+	  set_733((char*)Rock + ipnt, 0);
+	  ipnt += 8;
+	  set_733((char*)Rock + ipnt, 0);
+	  ipnt += 8;
+	  recstart = ipnt;
+	  currlen = 0;
+	  if(!mainrec) mainrec = ipnt;
+	  reclimit = SECTOR_SIZE - 8; /* Limit to one sector */
+}
+
+#ifdef __STDC__
+int generate_rock_ridge_attributes (char * whole_name, char * name,
+				    struct directory_entry * s_entry,
+				    struct stat * statbuf,
+				    struct stat * lstatbuf,
+				    int deep_opt)
+#else
+int generate_rock_ridge_attributes (whole_name, name,
+				    s_entry,
+				    statbuf,
+				    lstatbuf,
+				    deep_opt)
+char * whole_name; char * name; struct directory_entry * s_entry;
+struct stat * statbuf, *lstatbuf;
+int deep_opt;
+#endif
+{
+  int flagpos, flagval;
+  int need_ce;
+
+  statbuf = statbuf;        /* this shuts up unreferenced compiler warnings */
+  mainrec = recstart = ipnt = 0;
+  reclimit = 0xf8;
+
+  /* Obtain the amount of space that is currently used for the directory
+     record.  Assume max for name, since name conflicts may cause us
+     to rename the file later on */
+  currlen = sizeof(s_entry->isorec);
+
+  /* Identify that we are using the SUSP protocol */
+  if(deep_opt & NEED_SP){
+	  Rock[ipnt++] ='S';
+	  Rock[ipnt++] ='P';
+	  Rock[ipnt++] = 7;
+	  Rock[ipnt++] = SU_VERSION;
+	  Rock[ipnt++] = 0xbe;
+	  Rock[ipnt++] = 0xef;
+	  Rock[ipnt++] = 0;
+  };
+
+  /* First build the posix name field */
+  Rock[ipnt++] ='R';
+  Rock[ipnt++] ='R';
+  Rock[ipnt++] = 5;
+  Rock[ipnt++] = SU_VERSION;
+  flagpos = ipnt;
+  flagval = 0;
+  Rock[ipnt++] = 0;   /* We go back and fix this later */
+
+  if(strcmp(name,".")  && strcmp(name,"..")){
+    char * npnt;
+    int remain, use;
+
+    remain = strlen(name);
+    npnt = name;
+
+    while(remain){
+          use = remain;
+	  need_ce = 0;
+	  /* Can we fit this SUSP and a CE entry? */
+	  if(use + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
+	    use = reclimit - currlen - CE_SIZE - (ipnt - recstart);
+	    need_ce++;
+	  }
+
+	  /* Only room for 256 per SUSP field */
+	  if(use > 0xf8) use = 0xf8;
+
+	  /* First build the posix name field */
+	  Rock[ipnt++] ='N';
+	  Rock[ipnt++] ='M';
+	  Rock[ipnt++] = NM_SIZE + use;
+	  Rock[ipnt++] = SU_VERSION;
+	  Rock[ipnt++] = (remain != use ? 1 : 0);
+	  flagval |= (1<<3);
+	  strncpy((char *)&Rock[ipnt], npnt, use);
+	  npnt += use;
+	  ipnt += use;
+	  remain -= use;
+	  if(remain && need_ce) add_CE_entry();
+	};
+  };
+
+  /*
+   * Add the posix modes 
+   */
+  if(MAYBE_ADD_CE_ENTRY(PX_SIZE)) add_CE_entry();
+  Rock[ipnt++] ='P';
+  Rock[ipnt++] ='X';
+  Rock[ipnt++] = PX_SIZE;
+  Rock[ipnt++] = SU_VERSION;  
+  flagval |= (1<<0);
+  set_733((char*)Rock + ipnt, lstatbuf->st_mode);
+  ipnt += 8;
+  set_733((char*)Rock + ipnt, lstatbuf->st_nlink);
+  ipnt += 8;
+  set_733((char*)Rock + ipnt, lstatbuf->st_uid);
+  ipnt += 8;
+  set_733((char*)Rock + ipnt, lstatbuf->st_gid);
+  ipnt += 8;
+
+  /*
+   * Check for special devices
+   */
+#ifndef NON_UNIXFS
+  if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) {
+    if(MAYBE_ADD_CE_ENTRY(PN_SIZE)) add_CE_entry();
+    Rock[ipnt++] ='P';
+    Rock[ipnt++] ='N';
+    Rock[ipnt++] = PN_SIZE;
+    Rock[ipnt++] = SU_VERSION;  
+    flagval |= (1<<1);
+#if !defined(MAJOR_IN_SYSMACROS) && !defined(MAJOR_IN_MKDEV)
+    set_733((char*)Rock + ipnt, major(lstatbuf->st_rdev ));
+    ipnt += 8;
+    set_733((char*)Rock + ipnt, minor(lstatbuf->st_rdev));
+    ipnt += 8;
+#else
+    /*
+     * If we don't have sysmacros.h, then we have to guess as to how
+     * best to pick apart the device number for major/minor.
+     * Note: this may very well be wrong for many systems, so
+     * it is always best to use the major/minor macros if the
+     * system supports it.
+     */
+    if(sizeof(dev_t) <= 2) {
+        set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8));
+        ipnt += 8;
+        set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xff);
+        ipnt += 8;
+    }
+    else if(sizeof(dev_t) <= 4) {
+        set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8) >> 8);
+        ipnt += 8;
+        set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xffff);
+        ipnt += 8;
+    }
+    else {
+        set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 16) >> 16);
+        ipnt += 8;
+        set_733((char*)Rock + ipnt, lstatbuf->st_rdev);
+        ipnt += 8;
+    }
+#endif
+  };
+#endif
+  /*
+   * Check for and symbolic links.  VMS does not have these.
+   */
+  if (S_ISLNK(lstatbuf->st_mode)){
+    int lenpos, lenval, j0, j1;
+    int nchar;
+    unsigned char * cpnt, *cpnt1;
+    nchar = readlink(whole_name, symlink_buff, sizeof(symlink_buff));
+    symlink_buff[nchar < 0 ? 0 : nchar] = 0;
+    set_733(s_entry->isorec.size, 0);
+    cpnt = &symlink_buff[0];
+    flagval |= (1<<2);
+
+    while(nchar){
+      if(MAYBE_ADD_CE_ENTRY(SL_SIZE)) add_CE_entry();
+      Rock[ipnt++] ='S';
+      Rock[ipnt++] ='L';
+      lenpos = ipnt;
+      Rock[ipnt++] = SL_SIZE;
+      Rock[ipnt++] = SU_VERSION;  
+      Rock[ipnt++] = 0; /* Flags */
+      lenval = 5;
+      while(*cpnt){
+	cpnt1 = (unsigned char *) strchr((char *) cpnt, '/');
+	if(cpnt1) {
+	  nchar--;
+	  *cpnt1 = 0;
+	};
+	
+	/* We treat certain components in a special way.  */
+	if(cpnt[0] == '.' && cpnt[1] == '.' && cpnt[2] == 0){
+	  if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
+	  Rock[ipnt++] = SL_PARENT;
+	  Rock[ipnt++] = 0;  /* length is zero */
+	  lenval += 2;
+	  nchar -= 2;
+	} else if(cpnt[0] == '.' && cpnt[1] == 0){
+	  if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
+	  Rock[ipnt++] = SL_CURRENT;
+	  Rock[ipnt++] = 0;  /* length is zero */
+	  lenval += 2;
+	  nchar -= 1;
+	} else if(cpnt[0] == 0){
+	  if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
+	  Rock[ipnt++] = SL_ROOT;
+	  Rock[ipnt++] = 0;  /* length is zero */
+	  lenval += 2;
+	} else {
+	  /* If we do not have enough room for a component, start
+	     a new continuations segment now */
+	  if(MAYBE_ADD_CE_ENTRY(6)) {
+	    add_CE_entry();
+	    if(cpnt1){
+	      *cpnt1 = '/';
+              nchar++;
+	      cpnt1 = NULL; /* A kluge so that we can restart properly */
+	    }
+	    break;
+	  }
+	  j0 = strlen((char *) cpnt);
+	  while(j0) {
+	    j1 = j0;
+	    if(j1 > 0xf8) j1 = 0xf8;
+	    need_ce = 0;
+	    if(j1 + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
+	      j1 = reclimit - currlen - CE_SIZE - (ipnt - recstart);
+	      need_ce++;
+	    }
+	    Rock[ipnt++] = (j1 != j0 ? SL_CONTINUE : 0);
+	    Rock[ipnt++] = j1;
+	    strncpy((char *) Rock + ipnt, (char *) cpnt, j1);
+	    ipnt += j1;
+	    lenval += j1 + 2;
+	    cpnt += j1;
+	    nchar -= j1;  /* Number we processed this time */
+	    j0 -= j1;
+	    if(need_ce) {
+	      add_CE_entry();
+	      if(cpnt1) {
+		*cpnt1 = '/';
+                nchar++;
+		cpnt1 = NULL; /* A kluge so that we can restart properly */
+	      }
+	      break;
+	    }
+	  }
+	};
+	if(cpnt1) {
+	  cpnt = cpnt1 + 1;
+	} else
+	  break;
+      }
+      Rock[lenpos] = lenval;
+      if(nchar) Rock[lenpos + 2] = SL_CONTINUE; /* We need another SL entry */
+    } /* while nchar */
+  } /* Is a symbolic link */
+  /* 
+   * Add in the Rock Ridge TF time field
+   */
+  if(MAYBE_ADD_CE_ENTRY(TF_SIZE)) add_CE_entry();
+  Rock[ipnt++] ='T';
+  Rock[ipnt++] ='F';
+  Rock[ipnt++] = TF_SIZE;
+  Rock[ipnt++] = SU_VERSION;
+#ifdef __QNX__
+  Rock[ipnt++] = 0x0f;
+#else
+  Rock[ipnt++] = 0x0e;
+#endif
+  flagval |= (1<<7);
+#ifdef __QNX__
+  iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime);
+  ipnt += 7;
+#endif
+  iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime);
+  ipnt += 7;
+  iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime);
+  ipnt += 7;
+  iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime);
+  ipnt += 7;
+
+  /* 
+   * Add in the Rock Ridge RE time field
+   */
+  if(deep_opt & NEED_RE){
+          if(MAYBE_ADD_CE_ENTRY(RE_SIZE)) add_CE_entry();
+	  Rock[ipnt++] ='R';
+	  Rock[ipnt++] ='E';
+	  Rock[ipnt++] = RE_SIZE;
+	  Rock[ipnt++] = SU_VERSION;
+	  flagval |= (1<<6);
+  };
+  /* 
+   * Add in the Rock Ridge PL record, if required.
+   */
+  if(deep_opt & NEED_PL){
+          if(MAYBE_ADD_CE_ENTRY(PL_SIZE)) add_CE_entry();
+	  Rock[ipnt++] ='P';
+	  Rock[ipnt++] ='L';
+	  Rock[ipnt++] = PL_SIZE;
+	  Rock[ipnt++] = SU_VERSION;
+	  set_733((char*)Rock + ipnt, 0);
+	  ipnt += 8;
+	  flagval |= (1<<5);
+  };
+
+  /* 
+   * Add in the Rock Ridge CL field, if required.
+   */
+  if(deep_opt & NEED_CL){
+          if(MAYBE_ADD_CE_ENTRY(CL_SIZE)) add_CE_entry();
+	  Rock[ipnt++] ='C';
+	  Rock[ipnt++] ='L';
+	  Rock[ipnt++] = CL_SIZE;
+	  Rock[ipnt++] = SU_VERSION;
+	  set_733((char*)Rock + ipnt, 0);
+	  ipnt += 8;
+	  flagval |= (1<<4);
+  };
+
+#ifndef VMS
+  /* If transparent compression was requested, fill in the correct
+     field for this file */
+  if(transparent_compression && 
+     S_ISREG(lstatbuf->st_mode) &&
+     strlen(name) > 3 &&
+     strcmp(name + strlen(name) - 3,".gZ") == 0){
+    FILE * zipfile;
+    char * checkname;
+    unsigned int file_size;
+    unsigned char header[8];
+    int OK_flag;
+
+    /* First open file and verify that the correct algorithm was used */
+    file_size = 0;
+    OK_flag = 1;
+
+    zipfile = fopen(whole_name, "r");
+    fread(header, 1, sizeof(header), zipfile);
+
+    /* Check some magic numbers from gzip. */
+    if(header[0] != 0x1f || header[1] != 0x8b || header[2] != 8) OK_flag = 0;
+    /* Make sure file was blocksized. */
+    if(((header[3] & 0x40) == 0)) OK_flag = 0;
+    /* OK, now go to the end of the file and get some more info */
+    if(OK_flag){
+      int status;
+      status = (long)lseek(fileno(zipfile), (off_t)(-8), SEEK_END);
+      if(status == -1) OK_flag = 0;
+    }
+    if(OK_flag){
+      if(read(fileno(zipfile), (char*)header, sizeof(header)) != sizeof(header))
+	OK_flag = 0;
+      else {
+	int blocksize;
+	blocksize = (header[3] << 8) | header[2];
+	file_size = ((unsigned int)header[7] << 24) | 
+		    ((unsigned int)header[6] << 16) | 
+		    ((unsigned int)header[5] << 8)  | header[4];
+#if 0
+	fprintf(stderr,"Blocksize = %d %d\n", blocksize, file_size);
+#endif
+	if(blocksize != SECTOR_SIZE) OK_flag = 0;
+      }
+    }
+    fclose(zipfile);
+
+    checkname = strdup(whole_name);
+    checkname[strlen(whole_name)-3] = 0;
+    zipfile = fopen(checkname, "r");
+    if(zipfile) {
+      OK_flag = 0;
+      fprintf(stderr,"Unable to insert transparent compressed file - name conflict\n");
+      fclose(zipfile);
+    }
+
+    free(checkname);
+
+    if(OK_flag){
+      if(MAYBE_ADD_CE_ENTRY(ZZ_SIZE)) add_CE_entry();
+      Rock[ipnt++] ='Z';
+      Rock[ipnt++] ='Z';
+      Rock[ipnt++] = ZZ_SIZE;
+      Rock[ipnt++] = SU_VERSION;
+      Rock[ipnt++] = 'g'; /* Identify compression technique used */
+      Rock[ipnt++] = 'z';
+      Rock[ipnt++] = 3;
+      set_733((char*)Rock + ipnt, file_size); /* Real file size */
+      ipnt += 8;
+    };
+  }
+#endif
+  /* 
+   * Add in the Rock Ridge CE field, if required.  We use  this for the
+   * extension record that is stored in the root directory.
+   */
+  if(deep_opt & NEED_CE) add_CE_entry();
+  /*
+   * Done filling in all of the fields.  Now copy it back to a buffer for the
+   * file in question.
+   */
+
+  /* Now copy this back to the buffer for the file */
+  Rock[flagpos] = flagval;
+
+  /* If there was a CE, fill in the size field */
+  if(recstart)
+    set_733((char*)Rock + recstart - 8, ipnt - recstart);
+
+  s_entry->rr_attributes = (unsigned char *) e_malloc(ipnt);
+  s_entry->total_rr_attr_size = ipnt;
+  s_entry->rr_attr_size = (mainrec ? mainrec : ipnt);
+  memcpy(s_entry->rr_attributes, Rock, ipnt);
+  return ipnt;
+}
+
+/* Guaranteed to  return a single sector with the relevant info */
+
+char * FDECL4(generate_rr_extension_record, char *, id,  char  *, descriptor,
+				    char *, source, int  *, size){
+  int ipnt = 0;
+  char * pnt;
+  int len_id, len_des, len_src;
+
+  len_id = strlen(id);
+  len_des =  strlen(descriptor);
+  len_src = strlen(source);
+  Rock[ipnt++] ='E';
+  Rock[ipnt++] ='R';
+  Rock[ipnt++] = ER_SIZE + len_id + len_des + len_src;
+  Rock[ipnt++] = 1;
+  Rock[ipnt++] = len_id;
+  Rock[ipnt++] = len_des;
+  Rock[ipnt++] = len_src;
+  Rock[ipnt++] = 1;
+
+  memcpy(Rock  + ipnt, id, len_id);
+  ipnt += len_id;
+
+  memcpy(Rock  + ipnt, descriptor, len_des);
+  ipnt += len_des;
+
+  memcpy(Rock  + ipnt, source, len_src);
+  ipnt += len_src;
+
+  if(ipnt  > SECTOR_SIZE) {
+	  fprintf(stderr,"Extension record too  long\n");
+	  exit(1);
+  };
+  pnt = (char *) e_malloc(SECTOR_SIZE);
+  memset(pnt, 0,  SECTOR_SIZE);
+  memcpy(pnt, Rock, ipnt);
+  *size = ipnt;
+  return pnt;
+}
diff --git a/mass_storage/mkisofs-1.11.3/tree.c b/mass_storage/mkisofs-1.11.3/tree.c
new file mode 100644
index 0000000..7180905
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/tree.c
@@ -0,0 +1,1292 @@
+/*
+ * File tree.c - scan directory  tree and build memory structures for iso9660
+ * filesystem
+
+   Written by Eric Youngdale (1993).
+
+   Copyright 1993 Yggdrasil Computing, Incorporated
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+static char rcsid[] ="$Id: tree.c,v 1.9.1.2 1998/06/02 03:17:31 eric Exp $";
+
+/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include "config.h"
+
+#ifndef VMS
+#if defined(MAJOR_IN_SYSMACROS)
+#include <sys/sysmacros.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if defined(MAJOR_IN_MKDEV)
+#include <sys/types.h>
+#include <sys/mkdev.h>
+#endif
+#else
+#include <sys/file.h>
+#include <vms/fabdef.h>
+#include "vms.h"
+extern char * strdup(const char *);
+#endif
+
+/*
+ * Autoconf should be able to figure this one out for us and let us know
+ * whether the system has memmove or not.
+ */
+# ifndef HAVE_MEMMOVE
+#  define memmove(d, s, n) bcopy ((s), (d), (n))
+# endif
+
+#include "mkisofs.h"
+#include "iso9660.h"
+
+#include <sys/stat.h>
+
+#include "exclude.h"
+
+#ifdef NON_UNIXFS
+#define S_ISLNK(m)	(0)
+#define S_ISSOCK(m)	(0)
+#define S_ISFIFO(m)	(0)
+#else
+#ifndef S_ISLNK
+#define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)
+#endif
+#ifndef S_ISSOCK
+# ifdef S_IFSOCK
+#   define S_ISSOCK(m)	(((m) & S_IFMT) == S_IFSOCK)
+# else
+#   define S_ISSOCK(m)	(0)
+# endif
+#endif
+#endif
+
+#ifdef __svr4__
+extern char * strdup(const char *);
+#endif
+
+static unsigned char symlink_buff[256];
+
+extern int verbose;
+
+struct stat fstatbuf = {0,};  /* We use this for the artificial entries we create */
+
+struct stat root_statbuf = {0, };  /* Stat buffer for root directory */
+
+struct directory * reloc_dir = NULL;
+
+void
+FDECL1(stat_fix, struct stat *, st)
+{
+  /* Remove the uid and gid, they will only be useful on the author's
+     system.  */
+  st->st_uid = 0;
+  st->st_gid = 0;
+
+ /*
+  * Make sure the file modes make sense.  Turn on all read bits.  Turn
+  * on all exec/search bits if any exec/search bit is set.  Turn off
+  * all write bits, and all special mode bits (on a r/o fs lock bits
+  * are useless, and with uid+gid 0 don't want set-id bits, either).
+  */
+  st->st_mode |= 0444;
+  if (st->st_mode & 0111)
+    st->st_mode |= 0111;
+  st->st_mode &= ~07222;
+}
+
+int
+FDECL2(stat_filter, char *, path, struct stat *, st)
+{
+  int result = stat(path, st);
+  if (result >= 0 && rationalize)
+    stat_fix(st);
+  return result;
+}
+
+int
+FDECL2(lstat_filter, char *, path, struct stat *, st)
+{
+  int result = lstat(path, st);
+  if (result >= 0 && rationalize)
+    stat_fix(st);
+  return result;
+}
+
+void FDECL1(sort_n_finish, struct directory *, this_dir)
+{
+  struct directory_entry  * s_entry;
+  struct directory_entry  * s_entry1;
+  time_t		    current_time;
+  struct directory_entry  * table;
+  int			    count;
+  int			    d1;
+  int			    d2;
+  int			    d3;
+  int			    new_reclen;
+  char			 *  c;
+  int			    tablesize = 0;
+  char			    newname[34];
+  char			    rootname[34];
+
+  /* Here we can take the opportunity to toss duplicate entries from the
+     directory.  */
+
+  table = NULL;
+
+  if(fstatbuf.st_ctime == 0)
+    {
+      time (&current_time);
+      fstatbuf.st_uid = 0;
+      fstatbuf.st_gid = 0;
+      fstatbuf.st_ctime = current_time;
+      fstatbuf.st_mtime = current_time;
+      fstatbuf.st_atime = current_time;
+    }
+
+  flush_file_hash();
+  s_entry = this_dir->contents;
+  while(s_entry)
+    {
+	  
+      /*
+       * First assume no conflict, and handle this case 
+       */
+      if(!(s_entry1 = find_file_hash(s_entry->isorec.name)))
+	{
+	  add_file_hash(s_entry);
+	  s_entry = s_entry->next;
+	  continue;
+	}
+	  
+      if(s_entry1 == s_entry)
+	{
+	  fprintf(stderr,"Fatal goof\n");
+	  exit(1);
+	}
+      
+      /* 
+       * OK, handle the conflicts.  Try substitute names until we come
+       * up with a winner 
+       */
+      strcpy(rootname, s_entry->isorec.name);
+      if(full_iso9660_filenames) 
+	{
+	  if(strlen(rootname) > 27) rootname[27] = 0;
+	}
+
+      /*
+       * Strip off the non-significant part of the name so that we are left
+       * with a sensible root filename.  If we don't find a '.', then try
+       * a ';'.
+       */
+      c  = strchr(rootname, '.');
+      if (c) 
+	*c = 0;
+      else
+	{
+	  c  = strchr(rootname, ';');
+	  if (c) *c = 0;
+	}
+      for(d1 = 0; d1 < 36; d1++)
+	{
+	  for(d2 = 0; d2 < 36; d2++)
+	    {
+	      for(d3 = 0; d3 < 36; d3++)
+		{
+		  sprintf(newname,"%s.%c%c%c%s", rootname,  
+			  (d1 <= 9 ? '0' + d1 : 'A' + d1 - 10),
+			  (d2 <= 9 ? '0' + d2 : 'A' + d2 - 10),
+			  (d3 <= 9 ? '0' + d3 : 'A' + d3 - 10),
+			  (s_entry->isorec.flags[0] == 2 || 
+			   omit_version_number ? "" : ";1"));
+		  
+#ifdef VMS
+		  /* Sigh.  VAXCRTL seems to be broken here */
+		  {
+		    int ijk = 0;
+		    while(newname[ijk]) 
+		      {
+			if(newname[ijk] == ' ') newname[ijk] = '0';
+			ijk++;
+		      }
+		  }
+#endif
+		  
+		  if(!find_file_hash(newname)) goto got_valid_name;
+		}
+	    }
+	}
+
+      /*
+       * If we fell off the bottom here, we were in real trouble.
+       */
+      fprintf(stderr,"Unable to  generate unique  name for file %s\n", s_entry->name);
+      exit(1);
+
+got_valid_name:      
+      /* 
+       * OK, now we have a good replacement name.  Now decide which one
+       * of these two beasts should get the name changed 
+       */
+      if(s_entry->priority < s_entry1->priority) 
+	{
+	  fprintf(stderr,"Using %s for  %s%s%s (%s)\n", newname,  this_dir->whole_name, SPATH_SEPARATOR, s_entry->name, s_entry1->name);
+	  s_entry->isorec.name_len[0] =  strlen(newname);
+	  new_reclen =  sizeof(struct iso_directory_record) -
+	    sizeof(s_entry->isorec.name) +
+	    strlen(newname);
+	  if(use_RockRidge) 
+	    {
+	      if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */
+	      new_reclen += s_entry->rr_attr_size;
+	    }
+	  if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */
+	  s_entry->isorec.length[0] = new_reclen;
+	  strcpy(s_entry->isorec.name, newname);
+	}
+      else 
+	{
+	  delete_file_hash(s_entry1);
+	  fprintf(stderr,"Using %s for  %s%s%s (%s)\n", newname,  this_dir->whole_name, SPATH_SEPARATOR, s_entry1->name, s_entry->name);
+	  s_entry1->isorec.name_len[0] =  strlen(newname);
+	  new_reclen =  sizeof(struct iso_directory_record) -
+	    sizeof(s_entry1->isorec.name) +
+	    strlen(newname);
+	  if(use_RockRidge) 
+	    {
+	      if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */
+	      new_reclen += s_entry1->rr_attr_size;
+	    }
+	  if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */
+	  s_entry1->isorec.length[0] = new_reclen;
+	  strcpy(s_entry1->isorec.name, newname);
+	  add_file_hash(s_entry1);
+	}
+      add_file_hash(s_entry);
+      s_entry = s_entry->next;
+    }
+  
+  if(generate_tables 
+     && !find_file_hash("TRANS.TBL") 
+     && (reloc_dir != this_dir)
+     && (this_dir->extent == 0) )
+    {
+      /* 
+       * First we need to figure out how big this table is 
+       */
+      for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
+	{
+	  if(strcmp(s_entry->name, ".") == 0  ||
+	     strcmp(s_entry->name, "..") == 0) continue; 
+	  if(s_entry->table) tablesize += 35 + strlen(s_entry->table);
+	}
+    }
+
+  if( tablesize > 0 )
+    {
+      table = (struct directory_entry *) 
+	e_malloc(sizeof (struct directory_entry));
+      memset(table, 0, sizeof(struct directory_entry));
+      table->table = NULL;
+      table->next = this_dir->contents;
+      this_dir->contents = table;
+      
+      table->filedir = root;
+      table->isorec.flags[0] = 0;
+      table->priority  = 32768;
+      iso9660_date(table->isorec.date, fstatbuf.st_mtime);
+      table->inode = TABLE_INODE;
+      table->dev = (dev_t) UNCACHED_DEVICE;
+      set_723(table->isorec.volume_sequence_number, DEF_VSN);
+      set_733((char *) table->isorec.size, tablesize);
+      table->size = tablesize;
+      table->filedir = this_dir;
+      table->name = strdup("<translation table>");
+      table->table = (char *) e_malloc(ROUND_UP(tablesize));
+      memset(table->table, 0, ROUND_UP(tablesize));
+      iso9660_file_length  ("TRANS.TBL", table, 0);
+      
+      if(use_RockRidge)
+	{
+	  fstatbuf.st_mode = 0444 | S_IFREG;
+	  fstatbuf.st_nlink = 1;
+	  generate_rock_ridge_attributes("",
+					 "TRANS.TBL", table,
+					 &fstatbuf, &fstatbuf, 0);
+	}
+    }
+  
+  for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
+    {
+      new_reclen = strlen(s_entry->isorec.name);
+	  
+      if(s_entry->isorec.flags[0] ==  2)
+	{
+	  if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) 
+	    {
+	      path_table_size += new_reclen + sizeof(struct iso_path_table) - 1;
+	      if (new_reclen & 1) path_table_size++;
+	    }
+	  else 
+	    {
+	      new_reclen = 1;
+	      if (this_dir == root && strlen(s_entry->name) == 1)
+		path_table_size += sizeof(struct iso_path_table);
+	    }
+	}
+      if(path_table_size & 1) path_table_size++;  /* For odd lengths we pad */
+      s_entry->isorec.name_len[0] = new_reclen;
+      
+      new_reclen += 
+	sizeof(struct iso_directory_record) -
+	sizeof(s_entry->isorec.name);
+      
+      if (new_reclen & 1)	
+	new_reclen++;
+      
+      new_reclen += s_entry->rr_attr_size;
+      
+      if (new_reclen & 1) new_reclen++;
+      
+      if(new_reclen > 0xff) 
+	{
+	  fprintf(stderr,"Fatal error - RR overflow for file %s\n",
+		  s_entry->name);
+	  exit(1);
+	}
+      s_entry->isorec.length[0] = new_reclen;
+    }
+
+  sort_directory(&this_dir->contents);
+
+  if(table)
+    {
+      count = 0;
+      for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
+	if(s_entry == table) continue;
+	if(!s_entry->table) continue;
+	if(strcmp(s_entry->name, ".") == 0  ||
+	   strcmp(s_entry->name, "..") == 0) continue;
+	
+	count += sprintf(table->table + count, "%c %-34s%s",
+			 s_entry->table[0],
+			 s_entry->isorec.name, s_entry->table+1);
+	free(s_entry->table);
+	s_entry->table = NULL;
+      }
+
+      if(count !=  tablesize) 
+	{
+	  fprintf(stderr,"Translation table size mismatch %d %d\n",
+		  count, tablesize);
+	  exit(1);
+	}
+    }
+
+  /* 
+   * Now go through the directory and figure out how large this one will be.
+   * Do not split a directory entry across a sector boundary 
+   */
+  s_entry = this_dir->contents;
+  this_dir->ce_bytes = 0;
+  while(s_entry)
+    {
+      new_reclen = s_entry->isorec.length[0];
+      if ((this_dir->size & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE)
+	this_dir->size = (this_dir->size + (SECTOR_SIZE - 1)) & 
+	~(SECTOR_SIZE - 1);
+      this_dir->size += new_reclen;
+      
+      /* See if continuation entries were used on disc */
+      if(use_RockRidge && 
+	 s_entry->rr_attr_size != s_entry->total_rr_attr_size) 
+	{
+	  unsigned char * pnt;
+	  int len;
+	  int nbytes;
+	  
+	  pnt = s_entry->rr_attributes;
+	  len = s_entry->total_rr_attr_size;
+	  
+	  /*
+	   * We make sure that each continuation entry record is not
+	   * split across sectors, but each file could in theory have more
+	   * than one CE, so we scan through and figure out what we need. 
+	   */
+	  while(len > 3)
+	    {
+	      if(pnt[0] == 'C' && pnt[1] == 'E') 
+		{
+		  nbytes = get_733((char *) pnt+20);
+		  
+		  if((this_dir->ce_bytes & (SECTOR_SIZE - 1)) + nbytes >=
+		     SECTOR_SIZE) this_dir->ce_bytes = 
+				    ROUND_UP(this_dir->ce_bytes);
+		  /* Now store the block in the ce buffer */
+		  this_dir->ce_bytes += nbytes;
+		  if(this_dir->ce_bytes & 1) this_dir->ce_bytes++;
+		}
+	      len -= pnt[2];
+	      pnt += pnt[2];
+	    }
+	}
+      s_entry = s_entry->next;
+    }
+}
+
+static void generate_reloc_directory()
+{
+	int new_reclen;
+	time_t current_time;
+	struct directory_entry  *s_entry;
+
+	/* Create an  entry for our internal tree */
+	time (&current_time);
+	reloc_dir = (struct directory *) 
+		e_malloc(sizeof(struct directory));
+	memset(reloc_dir, 0, sizeof(struct directory));
+	reloc_dir->parent = root;
+	reloc_dir->next = root->subdir;
+	root->subdir = reloc_dir;
+	reloc_dir->depth = 1;
+	reloc_dir->whole_name = strdup("./rr_moved");
+	reloc_dir->de_name =  strdup("rr_moved");
+	reloc_dir->extent = 0;
+	
+	new_reclen  = strlen(reloc_dir->de_name);
+	
+	/* Now create an actual directory  entry */
+	s_entry = (struct directory_entry *) 
+		e_malloc(sizeof (struct directory_entry));
+	memset(s_entry, 0, sizeof(struct directory_entry));
+	s_entry->next = root->contents;
+	reloc_dir->self = s_entry;
+
+	root->contents = s_entry;
+	root->contents->name = strdup(reloc_dir->de_name);
+	root->contents->filedir = root;
+	root->contents->isorec.flags[0] = 2;
+	root->contents->priority  = 32768;
+	iso9660_date(root->contents->isorec.date, current_time);
+	root->contents->inode = UNCACHED_INODE;
+	root->contents->dev = (dev_t) UNCACHED_DEVICE;
+	set_723(root->contents->isorec.volume_sequence_number, DEF_VSN);
+	iso9660_file_length (reloc_dir->de_name, root->contents, 1);
+
+	if(use_RockRidge){
+		fstatbuf.st_mode = 0555 | S_IFDIR;
+		fstatbuf.st_nlink = 2;
+		generate_rock_ridge_attributes("",
+					       "rr_moved", s_entry,
+					       &fstatbuf, &fstatbuf, 0);
+	};
+	
+	/* Now create the . and .. entries in rr_moved */
+	/* Now create an actual directory  entry */
+	s_entry = (struct directory_entry *) 
+		e_malloc(sizeof (struct directory_entry));
+	memcpy(s_entry, root->contents, 
+	       sizeof(struct directory_entry));
+	s_entry->name = strdup(".");
+	iso9660_file_length (".", s_entry, 1);
+
+	s_entry->filedir = reloc_dir;
+	reloc_dir->contents = s_entry;
+
+	if(use_RockRidge){
+		fstatbuf.st_mode = 0555 | S_IFDIR;
+		fstatbuf.st_nlink = 2;
+		generate_rock_ridge_attributes("",
+					       ".", s_entry,
+					       &fstatbuf, &fstatbuf, 0);
+	};
+	
+	s_entry = (struct directory_entry *) 
+		e_malloc(sizeof (struct directory_entry));
+	memcpy(s_entry, root->contents, 
+	       sizeof(struct directory_entry));
+	s_entry->name = strdup("..");
+	iso9660_file_length ("..", s_entry, 1);
+	s_entry->filedir = root;
+	reloc_dir->contents->next = s_entry;
+	reloc_dir->contents->next->next = NULL;
+	if(use_RockRidge){
+		fstatbuf.st_mode = 0555 | S_IFDIR;
+		fstatbuf.st_nlink = 2;
+		generate_rock_ridge_attributes("",
+					       "..", s_entry,
+					       &root_statbuf, &root_statbuf, 0);
+	};
+}
+
+static void FDECL1(increment_nlink, struct directory_entry *, s_entry){
+  unsigned char * pnt;
+  int len, nlink;
+
+  pnt = s_entry->rr_attributes;
+  len = s_entry->total_rr_attr_size;
+  while(len){
+    if(pnt[0] == 'P' && pnt[1] == 'X') {
+      nlink =  get_733((char *) pnt+12);
+      set_733((char *) pnt+12, nlink+1);
+      break;
+    };
+    len -= pnt[2];
+    pnt += pnt[2];
+  };
+}
+
+void finish_cl_pl_entries(){
+  struct directory_entry  *s_entry, *s_entry1;
+  struct directory *  d_entry;
+
+  s_entry = reloc_dir->contents;
+   s_entry  = s_entry->next->next;  /* Skip past . and .. */
+  for(; s_entry; s_entry = s_entry->next){
+	  d_entry = reloc_dir->subdir;
+	  while(d_entry){
+		  if(d_entry->self == s_entry) break;
+		  d_entry = d_entry->next;
+	  };
+	  if(!d_entry){
+		  fprintf(stderr,"Unable to locate directory parent\n");
+		  exit(1);
+	  };
+
+	  /* First fix the PL pointer in the directory in the rr_reloc dir */
+	  s_entry1 = d_entry->contents->next;
+	  set_733((char *) s_entry1->rr_attributes +  s_entry1->total_rr_attr_size - 8,
+		  s_entry->filedir->extent);
+
+	  /* Now fix the CL pointer */
+	  s_entry1 = s_entry->parent_rec;
+
+	  set_733((char *) s_entry1->rr_attributes +  s_entry1->total_rr_attr_size - 8,
+		  d_entry->extent);
+
+	  s_entry->filedir = reloc_dir;  /* Now we can fix this */
+  }
+  /* Next we need to modify the NLINK terms in the assorted root directory records
+     to account for the presence of the RR_MOVED directory */
+
+  increment_nlink(root->self);
+  increment_nlink(root->self->next);
+  d_entry = root->subdir;
+  while(d_entry){
+    increment_nlink(d_entry->contents->next);
+    d_entry = d_entry->next;
+  };
+}
+
+/*
+ * This function scans the directory tree, looking for files, and it makes
+ * note of everything that is found.  We also begin to construct the ISO9660
+ * directory entries, so that we can determine how large each directory is.
+ */
+
+int
+FDECL3(scan_directory_tree,char *, path, struct directory_entry *, de,
+       struct iso_directory_record *, mrootp){
+  DIR				* current_dir;
+  char				  whole_path[1024];
+  struct dirent			* d_entry;
+  struct directory_entry	* s_entry, *s_entry1;
+  struct directory		* this_dir, *next_brother, *parent;
+  struct stat			  statbuf, lstatbuf;
+  int				  status, dflag;
+  int				  lstatus;
+  int				  n_orig;
+  struct directory_entry	**orig_contents = NULL;
+  struct directory_entry        * odpnt = NULL;
+  char				* cpnt;
+  int				  new_reclen;
+  int				  deep_flag;
+  char				* old_path;
+
+  current_dir = opendir(path);
+  d_entry = NULL;
+
+  /* Apparently NFS sometimes allows you to open the directory, but
+     then refuses to allow you to read the contents.  Allow for this */
+
+  old_path = path;
+
+  if(current_dir) d_entry = readdir_add_files(&path, old_path, current_dir);
+
+  if(!current_dir || !d_entry) {
+	  fprintf(stderr,"Unable to open directory %s\n", path);
+	  de->isorec.flags[0] &= ~2; /* Mark as not a directory */
+	  if(current_dir) closedir(current_dir);
+	  return 0;
+  };
+
+  parent = de->filedir;
+  /* Set up the struct for the current directory, and insert it into the
+     tree */
+
+#ifdef VMS
+  vms_path_fixup(path);
+#endif
+
+  this_dir = (struct directory *) e_malloc(sizeof(struct directory));
+  this_dir->next = NULL;
+  new_reclen = 0;
+  this_dir->subdir = NULL;
+  this_dir->self = de;
+  this_dir->contents = NULL;
+  this_dir->whole_name = strdup(path);
+  cpnt = strrchr(path, PATH_SEPARATOR);
+  if(cpnt)
+    cpnt++;
+  else
+    cpnt = path;
+  this_dir->de_name = strdup(cpnt);
+  this_dir->size = 0;
+  this_dir->extent = 0;
+
+  if(!parent || parent == root){
+    if (!root) {
+      root = this_dir;  /* First time through for root directory only */
+      root->depth = 0;
+      root->parent = root;
+    } else {
+      this_dir->depth = 1;
+      if(!root->subdir)
+	root->subdir = this_dir;
+      else {
+	next_brother = root->subdir;
+	while(next_brother->next) next_brother = next_brother->next;
+	next_brother->next = this_dir;
+      };
+      this_dir->parent = parent;
+    };
+  } else {
+	  /* Come through here for  normal traversal of  tree */
+#ifdef DEBUG
+	  fprintf(stderr,"%s(%d) ", path, this_dir->depth);
+#endif
+	  if(parent->depth >  RR_relocation_depth) {
+		  fprintf(stderr,"Directories too deep  %s\n", path);
+		  exit(1);
+	  };
+
+	  this_dir->parent = parent; 
+	  this_dir->depth = parent->depth + 1;
+
+	  if(!parent->subdir)
+		  parent->subdir = this_dir;
+	  else {
+		  next_brother = parent->subdir;
+		  while(next_brother->next) next_brother = next_brother->next;
+		  next_brother->next = this_dir;
+	  }
+  }
+
+  /*
+   * Parse the same directory in the image that we are merging
+   * for multisession stuff.
+   */
+  if( mrootp != NULL )
+    {
+      orig_contents = read_merging_directory(mrootp, &n_orig);
+    }
+
+/* Now we scan the directory itself, and look at what is inside of it. */
+
+  dflag = 0;
+  while(1==1){
+
+    /* The first time through, skip this, since we already asked for
+       the first entry when we opened the directory. */
+    if(dflag) d_entry = readdir_add_files(&path, old_path, current_dir);
+    dflag++;
+
+    if(!d_entry) break;
+
+    /* OK, got a valid entry */
+
+    /* If we do not want all files, then pitch the backups. */
+    if(!all_files){
+	    if(strchr(d_entry->d_name,'~')) continue;
+	    if(strchr(d_entry->d_name,'#')) continue;
+    };
+
+    if(strlen(path)+strlen(d_entry->d_name) + 2 > sizeof(whole_path)){
+      fprintf(stderr, "Overflow of stat buffer\n");
+      exit(1);
+    };
+
+    /* Generate the complete ASCII path for this file */
+    strcpy(whole_path, path);
+#ifndef VMS
+    if(whole_path[strlen(whole_path)-1] != '/')
+      strcat(whole_path, "/");
+#endif
+    strcat(whole_path, d_entry->d_name);
+
+    /* Should we exclude this file? */
+    if (is_excluded(whole_path)) {
+      if (verbose) {
+        fprintf(stderr, "Excluded: %s\n",whole_path);
+      }
+      continue;
+    }
+    /** Should we exclude this file ? */
+    if (matches(d_entry->d_name)) {
+      if (verbose) {
+	fprintf(stderr, "Excluded by match: %s\n", whole_path);
+      }
+      continue;
+    }
+
+    if(    generate_tables 
+	&& strcmp(d_entry->d_name, "TRANS.TBL") == 0 )
+      {
+	/*
+	 * Ignore this entry.  We are going to be generating new
+	 * versions of these files, and we need to ignore any
+	 * originals that we might have found.
+	 */
+	if (verbose) 
+	  {
+	    fprintf(stderr, "Excluded: %s\n",whole_path);
+	  }
+	continue;
+      }
+
+#if 0
+    if (verbose)  fprintf(stderr, "%s\n",whole_path);
+#endif
+    status = stat_filter(whole_path, &statbuf);
+
+    lstatus = lstat_filter(whole_path, &lstatbuf);
+
+    if( (status == -1) && (lstatus == -1) )
+      {
+	/*
+	 * This means that the file doesn't exist, or isn't accessible.
+	 * Sometimes this is because of NFS permissions problems
+	 * or it could mean that the user has attempted to 'add' something
+	 * with the -i option and the directory being added doesn't exist.
+	 */
+	fprintf(stderr, "Non-existant or inaccessible: %s\n",whole_path);
+	continue;
+      }
+
+    if(this_dir == root && strcmp(d_entry->d_name, ".") == 0)
+      root_statbuf = statbuf;  /* Save this for later on */
+
+    /* We do this to make sure that the root entries are consistent */
+    if(this_dir == root && strcmp(d_entry->d_name, "..") == 0) {
+      statbuf = root_statbuf;
+      lstatbuf = root_statbuf;
+    };
+
+    if(S_ISLNK(lstatbuf.st_mode)){
+
+	    /* Here we decide how to handle the symbolic links.  Here
+	       we handle the general case - if we are not following
+	       links or there is an error, then we must change
+	       something.  If RR is in use, it is easy, we let RR
+	       describe the file.  If not, then we punt the file. */
+
+	    if((status || !follow_links)){
+		    if(use_RockRidge){
+			    status = 0;
+			    statbuf.st_size = 0;
+			    STAT_INODE(statbuf) = UNCACHED_INODE;
+			    statbuf.st_dev = (dev_t) UNCACHED_DEVICE;
+			    statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG;
+		    } else {
+			    if(follow_links) fprintf(stderr,
+				    "Unable to stat file %s - ignoring and continuing.\n",
+				    whole_path);
+			    else fprintf(stderr,
+				    "Symlink %s ignored - continuing.\n",
+				    whole_path);
+			    continue;  /* Non Rock Ridge discs - ignore all symlinks */
+		    };
+	    }
+	    
+	    /* Here we handle a different kind of case.  Here we have
+	       a symlink, but we want to follow symlinks.  If we run
+	       across a directory loop, then we need to pretend that
+	       we are not following symlinks for this file.  If this
+	       is the first time we have seen this, then make this
+	       seem as if there was no symlink there in the first
+	       place */
+	       	       
+	    if( follow_links
+	       && S_ISDIR(statbuf.st_mode) ) 
+	      {
+		if(   strcmp(d_entry->d_name, ".")
+		   && strcmp(d_entry->d_name, "..") )
+		  {
+		    if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)))
+		      {
+			if(!use_RockRidge) 
+			  {
+			    fprintf(stderr, "Already cached directory seen (%s)\n", 
+				    whole_path);
+			    continue;
+			  }
+			statbuf.st_size = 0;
+			STAT_INODE(statbuf) = UNCACHED_INODE;
+			statbuf.st_dev = (dev_t) UNCACHED_DEVICE;
+			statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG;
+		    } else {
+		      lstatbuf = statbuf;
+		      add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
+		    }
+		  }
+	      }
+
+	    /*
+	     * For non-directories, we just copy the stat information over
+	     * so we correctly include this file.
+	     */
+	    if( follow_links
+	       && !S_ISDIR(statbuf.st_mode) ) 
+	      {
+		lstatbuf = statbuf;
+	      }
+    }
+
+    /*
+     * Add directories to the cache so that we don't waste space even
+     * if we are supposed to be following symlinks.
+     */
+    if( follow_links
+       && strcmp(d_entry->d_name, ".")
+       && strcmp(d_entry->d_name, "..")
+       && S_ISDIR(statbuf.st_mode) ) 
+	  {
+	    add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
+	  }
+#ifdef VMS
+    if(!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX && 
+				      statbuf.st_fab_rfm != FAB$C_STMLF)) {
+      fprintf(stderr,"Warning - file %s has an unsupported VMS record"
+	      " format (%d)\n",
+	      whole_path, statbuf.st_fab_rfm);
+    }
+#endif
+
+    if(S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK))){
+      fprintf(stderr, "File %s is not readable (errno = %d) - ignoring\n", 
+	      whole_path, errno);
+      continue;
+    }
+
+    /* Add this so that we can detect directory loops with hard links.
+     If we are set up to follow symlinks, then we skip this checking. */
+    if(   !follow_links 
+       && S_ISDIR(lstatbuf.st_mode) 
+       && strcmp(d_entry->d_name, ".") 
+       && strcmp(d_entry->d_name, "..") ) 
+      {
+	    if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) {
+		    fprintf(stderr,"Directory loop - fatal goof (%s %lx %lu).\n",
+			    whole_path, (unsigned long) statbuf.st_dev,
+			    (unsigned long) STAT_INODE(statbuf));
+		    exit(1);
+	    };
+	    add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
+    };
+
+    if (!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) &&
+	!S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode)
+	&& !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) &&
+	!S_ISDIR(lstatbuf.st_mode)) {
+      fprintf(stderr,"Unknown file type %s - ignoring and continuing.\n",
+	      whole_path);
+      continue;
+    };
+
+    /* Who knows what trash this is - ignore and continue */
+
+    if(status) {
+	    fprintf(stderr,
+		    "Unable to stat file %s - ignoring and continuing.\n",
+		    whole_path);
+	    continue; 
+    };
+
+    s_entry = (struct directory_entry *) 
+      e_malloc(sizeof (struct directory_entry));
+    s_entry->next = this_dir->contents;
+    memset(s_entry->isorec.extent, 0, 8);
+    this_dir->contents = s_entry;
+    deep_flag = 0;
+    s_entry->table = NULL;
+
+    s_entry->name = strdup(d_entry->d_name);
+    s_entry->whole_name = strdup (whole_path);
+
+    s_entry->de_flags = 0;
+    s_entry->filedir = this_dir;
+    s_entry->isorec.flags[0] = 0;
+    s_entry->isorec.ext_attr_length[0] = 0;
+    iso9660_date(s_entry->isorec.date, statbuf.st_mtime);
+    s_entry->isorec.file_unit_size[0] = 0;
+    s_entry->isorec.interleave[0] = 0;
+    if(parent && parent ==  reloc_dir && strcmp(d_entry->d_name,  "..") == 0){
+	    s_entry->inode = UNCACHED_INODE;
+	    s_entry->dev = (dev_t) UNCACHED_DEVICE;
+	    deep_flag  = NEED_PL;
+    } else  {
+	    s_entry->inode = STAT_INODE(statbuf);
+	    s_entry->dev = statbuf.st_dev;
+    };
+    set_723(s_entry->isorec.volume_sequence_number, DEF_VSN);
+    iso9660_file_length(d_entry->d_name, s_entry, S_ISDIR(statbuf.st_mode));
+    s_entry->rr_attr_size = 0;
+    s_entry->total_rr_attr_size = 0;
+    s_entry->rr_attributes = NULL;
+
+    /* Directories are assigned sizes later on */
+    if (!S_ISDIR(statbuf.st_mode)) {
+	set_733((char *) s_entry->isorec.size, statbuf.st_size); 
+
+	if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) || 
+	    S_ISFIFO(lstatbuf.st_mode) || S_ISSOCK(lstatbuf.st_mode)
+	  || S_ISLNK(lstatbuf.st_mode))
+	  s_entry->size = 0; 
+	else
+	  s_entry->size = statbuf.st_size; 
+    } else
+      s_entry->isorec.flags[0] = 2;
+
+    /*
+     * We always should create an entirely new directory tree whenever
+     * we generate a new session, unless there were *no* changes whatsoever
+     * to any of the directories, in which case it would be kind of pointless
+     * to generate a new session.
+     *
+     * I believe it is possible to rigorously prove that any change anywhere
+     * in the filesystem will force the entire tree to be regenerated
+     * because the modified directory will get a new extent number.  Since
+     * each subdirectory of the changed directory has a '..' entry, all of
+     * them will need to be rewritten too, and since the parent directory
+     * of the modified directory will have an extent pointer to the directory
+     * it too will need to be rewritten.  Thus we will never be able to reuse
+     * any directory information when writing new sessions.
+     *
+     * We still check the previous session so we can mark off the equivalent
+     * entry in the list we got from the original disc, however.
+     */
+    if(S_ISDIR(statbuf.st_mode) && orig_contents != NULL){
+      check_prev_session(orig_contents, n_orig, s_entry,
+			 &statbuf, &lstatbuf, &odpnt);
+    }
+
+    if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..") && 
+	S_ISDIR(statbuf.st_mode) && this_dir->depth >  RR_relocation_depth){
+		  if(!reloc_dir) generate_reloc_directory();
+
+		  s_entry1 = (struct directory_entry *) 
+			  e_malloc(sizeof (struct directory_entry));
+		  memcpy(s_entry1, this_dir->contents, 
+			 sizeof(struct directory_entry));
+		  s_entry1->table = NULL;
+		  s_entry1->name = strdup(this_dir->contents->name);
+		  s_entry1->whole_name = strdup(this_dir->contents->whole_name);
+		  s_entry1->next = reloc_dir->contents;
+		  reloc_dir->contents = s_entry1;
+		  s_entry1->priority  =  32768;
+		  s_entry1->parent_rec = this_dir->contents;
+
+		  deep_flag = NEED_RE;
+
+		  if(use_RockRidge) {
+			  generate_rock_ridge_attributes(whole_path,
+							 d_entry->d_name, s_entry1,
+							 &statbuf, &lstatbuf, deep_flag);
+		  }
+
+		  deep_flag = 0;
+
+		  /* We need to set this temporarily so that the parent to this is correctly
+		     determined. */
+		  s_entry1->filedir = reloc_dir;
+		  if( odpnt != NULL )
+		    {
+		      scan_directory_tree(whole_path, s_entry1, &odpnt->isorec);
+		    }
+		  else
+		    {
+		      scan_directory_tree(whole_path, s_entry1, NULL);
+		    }
+		  if( odpnt != NULL )
+		    {
+		      free(odpnt);
+		      odpnt = NULL;
+		    }
+		  s_entry1->filedir = this_dir;
+
+		  statbuf.st_size = 0;
+		  statbuf.st_mode &= 0777;
+		  set_733((char *) s_entry->isorec.size, 0);
+		  s_entry->size = 0;
+		  s_entry->isorec.flags[0] = 0;
+		  s_entry->inode = UNCACHED_INODE;
+		  deep_flag = NEED_CL;
+	  };
+ 
+    if(generate_tables && strcmp(s_entry->name, ".") && strcmp(s_entry->name, "..")) {
+	    char  buffer[2048];
+	    int nchar;
+	    switch(lstatbuf.st_mode & S_IFMT){
+	    case S_IFDIR:
+		    sprintf(buffer,"D\t%s\n",
+			    s_entry->name);
+		    break;
+#ifndef NON_UNIXFS
+	    case S_IFBLK:
+		    sprintf(buffer,"B\t%s\t%lu %lu\n",
+			    s_entry->name,
+			    (unsigned long) major(statbuf.st_rdev),
+			    (unsigned long) minor(statbuf.st_rdev));
+		    break;
+	    case S_IFIFO:
+		    sprintf(buffer,"P\t%s\n",
+			    s_entry->name);
+		    break;
+	    case S_IFCHR:
+		    sprintf(buffer,"C\t%s\t%lu %lu\n",
+			    s_entry->name,
+			    (unsigned long) major(statbuf.st_rdev),
+			    (unsigned long) minor(statbuf.st_rdev));
+		    break;
+	    case S_IFLNK:
+		    nchar = readlink(whole_path, 
+				     symlink_buff, 
+				     sizeof(symlink_buff));
+		    symlink_buff[nchar < 0 ? 0 : nchar] = 0;
+		    sprintf(buffer,"L\t%s\t%s\n",
+			    s_entry->name, symlink_buff);
+		    break;
+#ifdef S_IFSOCK
+	    case S_IFSOCK:
+		    sprintf(buffer,"S\t%s\n",
+			    s_entry->name);
+		    break;
+#endif
+#endif /* NON_UNIXFS */
+	    case S_IFREG:
+	    default:
+		    sprintf(buffer,"F\t%s\n",
+			    s_entry->name);
+		    break;
+	    };
+	    s_entry->table = strdup(buffer);
+    };
+    
+    /*
+     * See if we have an entry for this guy in the previous session.
+     */
+    if( orig_contents != NULL && !S_ISDIR(statbuf.st_mode))
+      {
+	check_prev_session(orig_contents, n_orig, s_entry, 
+			   &statbuf, &lstatbuf, NULL);
+      }
+
+    if(S_ISDIR(statbuf.st_mode)){
+            int dflag;
+	    if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..")) {
+	      if( odpnt != NULL )
+		{
+		  dflag = scan_directory_tree(whole_path, s_entry, 
+					      &odpnt->isorec);
+		}
+	      else
+		{
+		  dflag = scan_directory_tree(whole_path, s_entry, NULL);
+		}
+	    /* If unable to scan directory, mark this as a non-directory */
+	        if(!dflag)
+		  lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
+		if( odpnt != NULL )
+		  {
+		    free(odpnt);
+		    odpnt = NULL;
+		  }
+	      }
+	  }
+
+  if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".")  == 0)
+	  deep_flag |= NEED_CE | NEED_SP;  /* For extension record */
+
+    /* Now figure out how much room this file will take in the directory */
+
+    if(use_RockRidge) {
+	    generate_rock_ridge_attributes(whole_path,
+					   d_entry->d_name, s_entry,
+					   &statbuf, &lstatbuf, deep_flag);
+	    
+    }
+  }
+  closedir(current_dir);
+
+  if( orig_contents != NULL )
+    {
+      merge_remaining_entries(this_dir, orig_contents, n_orig);
+      free_mdinfo(orig_contents, n_orig);
+    }
+
+  if( this_dir->contents == NULL )
+    {
+      /*
+       * This directory must have been inaccessible.
+       */
+      return 0;
+    }
+  sort_n_finish(this_dir);
+
+  return 1;
+}
+
+
+void FDECL2(generate_iso9660_directories, struct directory *, node, FILE*, outfile){
+  struct directory * dpnt;
+
+  dpnt = node;
+
+  while (dpnt){
+    if( dpnt->extent > session_start )
+      {
+	generate_one_directory(dpnt, outfile);
+      }
+    if(dpnt->subdir) generate_iso9660_directories(dpnt->subdir, outfile);
+    dpnt = dpnt->next;
+  }
+}
+
+void FDECL1(dump_tree, struct directory *, node){
+  struct directory * dpnt;
+
+  dpnt = node;
+
+  while (dpnt){
+    fprintf(stderr,"%4d %5d %s\n",dpnt->extent, dpnt->size, dpnt->de_name);
+    if(dpnt->subdir) dump_tree(dpnt->subdir);
+    dpnt = dpnt->next;
+  }
+}
+
+/*
+ * something quick and dirty to locate a file given a path
+ * recursively walks down path in filename until it finds the
+ * directory entry for the desired file 
+ */
+struct directory_entry * FDECL2(search_tree_file, struct directory *, 
+				node,char *, filename)
+{
+  struct directory_entry * depnt;
+  struct directory	 * dpnt;
+  char			 * p1;
+  char			 * rest;
+  char			 * subdir;
+
+  /*
+   * strip off next directory name from filename 
+   */
+  subdir = strdup(filename);
+
+  if( (p1=strchr(subdir, '/')) == subdir )
+    {
+      fprintf(stderr,"call to search_tree_file with an absolute path, stripping\n");
+      fprintf(stderr,"initial path separator. Hope this was intended...\n");
+      memmove(subdir, subdir+1, strlen(subdir)-1);
+      p1 = strchr(subdir, '/');
+    }
+
+  /*
+   * do we need to find a subdirectory 
+   */
+  if (p1) 
+    {
+      *p1 = '\0';
+
+#ifdef DEBUG_TORITO
+      printf("Looking for subdir called %s\n",p1); 
+#endif
+
+      rest = p1+1;
+
+#ifdef DEBUG_TORITO
+      printf("Remainder of path name is now %s\n", rest); 
+#endif
+      
+      dpnt = node->subdir;
+     while( dpnt )
+       {
+#ifdef DEBUG_TORITO
+	 fprintf(stderr,"%4d %5d %s\n", dpnt->extent, dpnt->size, 
+		 dpnt->de_name); 
+#endif
+	 if (!strcmp(subdir, dpnt->de_name)) 
+	   {
+#ifdef DEBUG_TORITO
+	     printf("Calling next level with filename = %s", rest); 
+#endif
+	     return(search_tree_file( dpnt, rest ));
+	   }
+	 dpnt = dpnt->next;
+       }
+      
+     /* if we got here means we couldnt find the subdir */
+     return (NULL);
+    }    
+  else 
+    {
+      /* 
+       * look for a normal file now 
+       */
+      depnt = node->contents;
+      while (depnt)
+	{
+#ifdef DEBUG_TORITO
+	  fprintf(stderr,"%4d %5d %s\n",depnt->isorec.extent, 
+		  depnt->size, depnt->name); 
+#endif
+	  if (!strcmp(filename, depnt->name)) 
+	    {
+#ifdef DEBUG_TORITO
+	      printf("Found our file %s", filename); 
+#endif
+	      return(depnt);
+	    }
+	  depnt = depnt->next;
+	}
+      /* 
+       * if we got here means we couldnt find the subdir 
+       */
+      return (NULL);
+    }
+  fprintf(stderr,"We cant get here in search_tree_file :-/ \n");
+}
+
diff --git a/mass_storage/mkisofs-1.11.3/vms.c b/mass_storage/mkisofs-1.11.3/vms.c
new file mode 100644
index 0000000..5c7cc11
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/vms.c
@@ -0,0 +1,270 @@
+/*
+ * File vms.c - assorted bletcherous hacks for VMS.
+
+   Written by Eric Youngdale (1993).
+ */
+
+static char rcsid[] ="$Id: vms.c,v 1.2 1997/02/23 16:06:20 eric Rel $";
+
+#ifdef VMS
+#include <rms.h>
+#include <descrip.h>
+#include <ssdef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#define opendir fake_opendir
+#include "mkisofs.h"
+#undef opendir
+#include <stdio.h>
+
+static struct RAB *rab;	/* used for external mailfiles */
+static int rms_status;
+
+static error_exit(char * text){
+	fprintf(stderr,"%s\n", text);
+	exit(33);
+}
+
+
+char * strrchr(const char *, char);
+
+char * strdup(char * source){
+  char * pnt;
+  pnt = (char *) e_malloc(strlen(source) + 1);
+  strcpy(pnt, source);
+  return pnt;
+}
+
+int VMS_stat(char * path, struct stat * spnt){
+  char * spath;
+  char sbuffer[255];
+  char * pnt, *ppnt;
+  char * pnt1;
+
+  ppnt = strrchr(path,']');
+  if(ppnt) ppnt++;
+  else ppnt = path;
+
+  spath = path;
+
+  if(strcmp(ppnt,".") == 0 || strcmp(ppnt,"..") == 0){
+    strcpy(sbuffer, path);
+
+    /* Find end of actual name */
+    pnt = strrchr(sbuffer,']');
+    if(!pnt) return 0;
+
+    pnt1 = pnt;
+    while(*pnt1 != '[' && *pnt1 != '.') pnt1--;
+
+    if(*pnt1 != '[' && strcmp(ppnt,"..") == 0) {
+      pnt1--;
+      while(*pnt1 != '[' && *pnt1 != '.') pnt1--;
+    };
+
+    if(*pnt1 == '.') {
+      *pnt1 = ']';
+      pnt = pnt1;
+      while(*pnt != '.' && *pnt != ']') pnt++;
+      *pnt++ = ']';
+      while(*pnt != '.' && *pnt != ']') pnt++;
+      *pnt = 0;
+      strcat(sbuffer,".DIR;1");
+    };
+
+    if(*pnt1 == '[') {
+      pnt1++;
+      *pnt1 = 0;
+      strcat(pnt1,"000000]");
+      pnt1 = strrchr(path,'[') + 1;
+      pnt = sbuffer + strlen(sbuffer);
+      while(*pnt1 && *pnt1 != '.' && *pnt1 != ']') *pnt++ = *pnt1++;
+      *pnt = 0;
+      strcat(sbuffer,".DIR;1");
+    };
+
+    spath = sbuffer;
+  };
+  return stat_filter(spath, spnt);
+}
+
+static int dircontext[32] = {0,};
+static char * searchpath[32];
+static struct direct d_entry[32];
+
+int optind = 0;
+char * optarg;
+
+int  getopt(int argc, char *argv[], char * flags){
+  char * pnt;
+  char c;
+  optind++;
+  if(*argv[optind] != '-') return EOF;
+  optarg = 0;
+
+  c = *(argv[optind]+1);
+  pnt = (char *) strchr(flags, c);
+  if(!pnt) return c;  /* Not found */
+  if(pnt[1] == ':') {
+    optind++;
+    optarg = argv[optind];
+  };
+  return c;
+}
+
+void vms_path_fixup(char * name){
+  char * pnt1;
+  pnt1 = name + strlen(name) - 6;
+
+  /* First strip the .DIR;1 */
+  if(strcmp(pnt1, ".DIR;1") == 0) *pnt1 = 0;
+
+  pnt1 = (char*) strrchr(name, ']');
+  if(pnt1) {
+    if(pnt1[1] == 0) return;
+    *pnt1 = '.';
+    strcat(name,"]");
+    return;
+  };
+  pnt1 = (char*) strrchr(name, '>');
+  if(pnt1) {
+    if(pnt1[1] == 0) return;
+    *pnt1 = '.';
+    strcat(name,">");
+    return;
+  };
+}
+
+int opendir(char * path){
+  int i;
+  for(i=1; i<32; i++) {
+    if(dircontext[i] == 0){
+      dircontext[i] = -1;
+      searchpath[i] = (char *) e_malloc(strlen(path) + 6);
+      strcpy(searchpath[i], path);
+      vms_path_fixup(searchpath[i]);
+      strcat(searchpath[i],"*.*.*");
+      return i;
+    };
+  };
+  exit(0);
+}
+
+struct direct * readdir(int context){
+  int i;
+  char cresult[100];
+  char * pnt;
+  int status;
+  $DESCRIPTOR(dpath,searchpath[context]);
+  $DESCRIPTOR(result,cresult);
+
+  if(dircontext[context] == -1) {
+    dircontext[context] = -2;
+    strcpy(d_entry[context].d_name, ".");
+    return &d_entry[context];
+  };
+
+  if(dircontext[context] == -2) {
+    dircontext[context] = -3;
+    strcpy(d_entry[context].d_name, "..");
+    return &d_entry[context];
+  };
+
+  if(dircontext[context] == -3) dircontext[context] = 0;
+
+  dpath.dsc$w_length = strlen(searchpath[context]);
+  lib$find_file(&dpath, &result, &dircontext[context], 
+		0, 0, &status, 0);
+
+  if(status == SS$_NOMOREFILES) return 0;
+
+  /* Now trim trailing spaces from the name */
+  i = result.dsc$w_length - 1;
+  while(i && cresult[i] == ' ') i--;
+  cresult[i+1] = 0;
+
+  /* Now locate the actual portion of the file we want */
+
+  pnt = (char *) strrchr(cresult,']');
+  if(pnt) pnt++;
+  else
+    pnt = cresult;
+
+  strcpy(d_entry[context].d_name, pnt);
+  return &d_entry[context];
+}
+
+void closedir(int context){
+  lib$find_file_end(&dircontext[context]);
+  free(searchpath[context]);
+  searchpath[context] = (char *) 0;
+  dircontext[context] = 0;
+}
+
+static open_file(char* fn){
+/* this routine initializes a rab and  fab required to get the
+   correct definition of the external data file used by mail */
+	struct FAB * fab;
+
+	rab = (struct RAB*) e_malloc(sizeof(struct RAB));
+	fab = (struct FAB*) e_malloc(sizeof(struct FAB));
+
+	*rab = cc$rms_rab;	/* initialize RAB*/
+	rab->rab$l_fab = fab;
+
+	*fab = cc$rms_fab;	/* initialize FAB*/
+	fab->fab$l_fna = fn;
+	fab->fab$b_fns = strlen(fn);
+	fab->fab$w_mrs = 512;
+	fab->fab$b_fac = FAB$M_BIO | FAB$M_GET;
+	fab->fab$b_org = FAB$C_SEQ;
+	fab->fab$b_rfm = FAB$C_FIX;
+	fab->fab$l_xab = (char*) 0;
+
+	rms_status = sys$open(rab->rab$l_fab);
+	if(rms_status != RMS$_NORMAL && rms_status != RMS$_CREATED)
+		error_exit("$OPEN");
+	rms_status = sys$connect(rab);
+	if(rms_status != RMS$_NORMAL)
+		error_exit("$CONNECT");
+	return 1;
+}
+
+static close_file(struct RAB * prab){
+	rms_status = sys$close(prab->rab$l_fab);
+	free(prab->rab$l_fab);
+	free(prab);
+	if(rms_status != RMS$_NORMAL)
+		error_exit("$CLOSE");
+}
+
+#define NSECT 16
+extern unsigned int last_extent_written;
+
+int vms_write_one_file(char * filename, int size, FILE * outfile){
+	int status, i;
+	char buffer[SECTOR_SIZE * NSECT];
+	int count;
+	int use;
+	int remain;
+
+	open_file(filename);
+
+	remain = size;
+	
+	while(remain > 0){
+	  use =  (remain >  SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain);
+	  use = ROUND_UP(use); /* Round up to nearest sector boundary */
+	  memset(buffer, 0, use);
+	  rab->rab$l_ubf = buffer;
+	  rab->rab$w_usz = sizeof(buffer);
+	  status = sys$read(rab);
+	  fwrite(buffer, 1, use, outfile);
+	  last_extent_written += use/SECTOR_SIZE;
+	  if((last_extent_written % 1000) < use/SECTOR_SIZE) fprintf(stderr,"%d..", last_extent_written);
+	  remain -= use;
+	};
+	
+	close_file(rab);
+}
+#endif
diff --git a/mass_storage/mkisofs-1.11.3/vms.h b/mass_storage/mkisofs-1.11.3/vms.h
new file mode 100644
index 0000000..234db3d
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/vms.h
@@ -0,0 +1,20 @@
+/*
+ * Header file mkisofs.h - assorted structure definitions and typecasts.
+
+   Written by Eric Youngdale (1993).
+
+ * $Id: vms.h,v 1.1 1997/02/23 15:59:18 eric Rel $
+ */
+
+#ifdef VMS
+#define stat(X,Y) VMS_stat(X,Y)
+#define lstat VMS_stat
+
+/* gmtime not available under VMS - make it look like we are in Greenwich */
+#define gmtime localtime
+
+#define S_ISBLK(X) (0)
+#define S_ISCHR(X) (0)
+#define S_ISREG(X)  (((X) & S_IFMT) == S_IFREG)
+#define S_ISDIR(X)  (((X) & S_IFMT) == S_IFDIR)
+#endif
diff --git a/mass_storage/mkisofs-1.11.3/write.c b/mass_storage/mkisofs-1.11.3/write.c
new file mode 100644
index 0000000..cfc9b76
--- /dev/null
+++ b/mass_storage/mkisofs-1.11.3/write.c
@@ -0,0 +1,1142 @@
+/*
+ * Program write.c - dump memory  structures to  file for iso9660 filesystem.
+
+   Written by Eric Youngdale (1993).
+
+   Copyright 1993 Yggdrasil Computing, Incorporated
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+static char rcsid[] ="$Id: write.c,v 1.6.1.3 1997/11/13 05:07:13 eric Exp $";
+
+#include <string.h>
+#include <stdlib.h>
+#include "mkisofs.h"
+#include "iso9660.h"
+#include <time.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+ 
+#ifdef __svr4__
+extern char * strdup(const char *);
+#endif
+
+#ifdef VMS
+extern char * strdup(const char *);
+#endif
+
+
+/* Max number of sectors we will write at  one time */
+#define NSECT 16
+
+/* Counters for statistics */
+
+static int table_size = 0;
+static int total_dir_size = 0;
+static int rockridge_size = 0;
+static struct directory ** pathlist;
+static next_path_index = 1;
+
+/* Used to fill in some  of the information in the volume descriptor. */
+static struct tm local;
+static struct tm gmt;
+
+/* Routines to actually write the disc.  We write sequentially so that
+   we could write a tape, or write the disc directly */
+
+
+#define FILL_SPACE(X)   memset(vol_desc.X, ' ', sizeof(vol_desc.X))
+
+void FDECL2(set_721, char *, pnt, unsigned int, i)
+{
+     pnt[0] = i & 0xff;
+     pnt[1] = (i >> 8) &  0xff;
+}
+
+void FDECL2(set_722, char *, pnt, unsigned int, i)
+{
+     pnt[0] = (i >> 8) &  0xff;
+     pnt[1] = i & 0xff;
+}
+
+void FDECL2(set_723, char *, pnt, unsigned int, i)
+{
+     pnt[3] = pnt[0] = i & 0xff;
+     pnt[2] = pnt[1] = (i >> 8) &  0xff;
+}
+
+void FDECL2(set_731, char *, pnt, unsigned int, i)
+{
+     pnt[0] = i & 0xff;
+     pnt[1] = (i >> 8) &  0xff;
+     pnt[2] = (i >> 16) &  0xff;
+     pnt[3] = (i >> 24) &  0xff;
+}
+
+void FDECL2(set_732, char *, pnt, unsigned int, i)
+{
+     pnt[3] = i & 0xff;
+     pnt[2] = (i >> 8) &  0xff;
+     pnt[1] = (i >> 16) &  0xff;
+     pnt[0] = (i >> 24) &  0xff;
+}
+
+int FDECL1(get_733, char *, p)
+{
+     return ((p[0] & 0xff)
+	     | ((p[1] & 0xff) << 8)
+	     | ((p[2] & 0xff) << 16)
+	     | ((p[3] & 0xff) << 24));
+}
+
+void FDECL2(set_733, char *, pnt, unsigned int, i)
+{
+     pnt[7] = pnt[0] = i & 0xff;
+     pnt[6] = pnt[1] = (i >> 8) &  0xff;
+     pnt[5] = pnt[2] = (i >> 16) &  0xff;
+     pnt[4] = pnt[3] = (i >> 24) &  0xff;
+}
+
+void FDECL4(xfwrite, void *, buffer, int, count, int, size, FILE *, file)
+{
+     while(count) 
+     {
+	  int got = fwrite(buffer,size,count,file);
+
+	  if(got<=0) 
+	  {
+	       fprintf(stderr,"cannot fwrite %d*%d\n",size,count);
+	       exit(1);
+	  }
+	  count-=got,*(char**)&buffer+=size*got;
+     }
+}
+
+struct deferred_write
+{
+  struct deferred_write * next;
+  char			* table;
+  unsigned int		  extent;
+  unsigned int		  size;
+  char			* name;
+};
+
+static struct deferred_write * dw_head = NULL, * dw_tail = NULL;
+
+static struct directory_entry * sort_dir;
+static struct eltorito_boot_descriptor boot_desc;
+
+unsigned int last_extent_written  =0;
+static struct iso_primary_descriptor vol_desc;
+static path_table_index;
+static time_t begun;
+
+/* We recursively walk through all of the directories and assign extent
+   numbers to them.  We have already assigned extent numbers to everything that
+   goes in front of them */
+
+void FDECL1(assign_directory_addresses, struct directory *, node)
+{
+     int		dir_size;
+     struct directory * dpnt;
+
+     dpnt = node;
+     
+     while (dpnt)
+     {
+	  /*
+	   * If we already have an extent for this (i.e. it came from
+	   * a multisession disc), then don't reassign a new extent.
+	   */
+	  dpnt->path_index = next_path_index++;
+	  if( dpnt->extent == 0 )
+	  {
+	       dpnt->extent = last_extent;
+	       dir_size = (dpnt->size + (SECTOR_SIZE - 1)) >> 11;
+	       
+	       last_extent += dir_size;
+	       
+	       /* 
+		* Leave room for the CE entries for this directory.  Keep them
+		* close to the reference directory so that access will be 
+		* quick. 
+		*/
+	       if(dpnt->ce_bytes)
+	       {
+		    last_extent += ROUND_UP(dpnt->ce_bytes) >> 11;
+	       }
+	  }
+
+	  if(dpnt->subdir) 
+	  {
+	       assign_directory_addresses(dpnt->subdir);
+	  }
+
+	  dpnt = dpnt->next;
+     }
+}
+
+static void FDECL3(write_one_file, char *, filename, 
+		   unsigned int, size, FILE *, outfile)
+{
+     char		  buffer[SECTOR_SIZE * NSECT];
+     FILE		* infile;
+     int		  remain;
+     int		  use;
+
+
+     if ((infile = fopen(filename, "rb")) == NULL) 
+     {
+#if defined(sun) || defined(_AUX_SOURCE)
+	  fprintf(stderr, "cannot open %s: (%d)\n", filename, errno);
+#else
+	  fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
+#endif
+	  exit(1);
+     }
+     remain = size;
+
+     while(remain > 0)
+     {
+	  use =  (remain >  SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain);
+	  use = ROUND_UP(use); /* Round up to nearest sector boundary */
+	  memset(buffer, 0, use);
+	  if (fread(buffer, 1, use, infile) == 0) 
+	  {
+	       fprintf(stderr,"cannot read from %s\n",filename); 
+	       exit(1);
+	  }
+	  xfwrite(buffer, 1, use, outfile);
+	  last_extent_written += use/SECTOR_SIZE;
+#if 0
+	  if((last_extent_written % 1000) < use/SECTOR_SIZE) 
+	  {
+	       fprintf(stderr,"%d..", last_extent_written);
+	  }
+#else
+	  if((last_extent_written % 5000) < use/SECTOR_SIZE)
+	  {
+	       time_t now;
+	       time_t the_end;
+	       double frac;
+	       
+	       time(&now);
+	       frac = last_extent_written / (double)last_extent;
+	       the_end = begun + (now - begun) / frac;
+	       fprintf(stderr, "%6.2f%% done, estimate finish %s",
+		       frac * 100., ctime(&the_end));
+	  }
+#endif
+	  remain -= use;
+     }
+     fclose(infile);
+} /* write_one_file(... */
+
+static void FDECL1(write_files, FILE *, outfile)
+{
+     struct deferred_write * dwpnt, *dwnext;
+     dwpnt = dw_head;
+     while(dwpnt)
+     {
+	  if(dwpnt->table) 
+	  {
+	       xfwrite(dwpnt->table,  1, ROUND_UP(dwpnt->size), outfile);
+	       last_extent_written += ROUND_UP(dwpnt->size) / SECTOR_SIZE;
+	       table_size += dwpnt->size;
+/*		  fprintf(stderr,"Size %d ", dwpnt->size); */
+	       free(dwpnt->table);
+	  } 
+	  else 
+	  {
+
+#ifdef VMS
+	       vms_write_one_file(dwpnt->name, dwpnt->size, outfile);
+#else
+	       write_one_file(dwpnt->name, dwpnt->size, outfile);
+#endif
+	       free(dwpnt->name);
+	  }
+
+	  dwnext = dwpnt;
+	  dwpnt = dwpnt->next;
+	  free(dwnext);
+     }
+} /* write_files(... */
+
+#if 0
+static void dump_filelist()
+{
+     struct deferred_write * dwpnt;
+     dwpnt = dw_head;
+     while(dwpnt)
+     {
+	  fprintf(stderr, "File %s\n",dwpnt->name);
+	  dwpnt = dwpnt->next;
+     }
+     fprintf(stderr,"\n");
+}
+#endif
+
+int FDECL2(compare_dirs, const void *, rr, const void *, ll) 
+{
+     char * rpnt, *lpnt;
+     struct directory_entry ** r, **l;
+     
+     r = (struct directory_entry **) rr;
+     l = (struct directory_entry **) ll;
+     rpnt = (*r)->isorec.name;
+     lpnt = (*l)->isorec.name;
+     
+     /*
+      *  Put the '.' and '..' entries on the head of the sorted list.
+      *  For normal ASCII, this always happens to be the case, but out of
+      *  band characters cause this not to be the case sometimes.
+      */
+     if( strcmp(rpnt, ".") == 0 ) return -1;
+     if( strcmp(lpnt, ".") == 0 ) return  1;
+
+     if( strcmp(rpnt, "..") == 0 ) return -1;
+     if( strcmp(lpnt, "..") == 0 ) return  1;
+
+     while(*rpnt && *lpnt) 
+     {
+	  if(*rpnt == ';' && *lpnt != ';') return -1;
+	  if(*rpnt != ';' && *lpnt == ';') return 1;
+	  
+	  if(*rpnt == ';' && *lpnt == ';') return 0;
+	  
+	  if(*rpnt == '.' && *lpnt != '.') return -1;
+	  if(*rpnt != '.' && *lpnt == '.') return 1;
+	  
+	  if((unsigned char)*rpnt < (unsigned char)*lpnt) return -1;
+	  if((unsigned char)*rpnt > (unsigned char)*lpnt) return 1;
+	  rpnt++;  lpnt++;
+     }
+     if(*rpnt) return 1;
+     if(*lpnt) return -1;
+     return 0;
+}
+
+void FDECL1(sort_directory, struct directory_entry **, sort_dir)
+{
+     int dcount = 0;
+     int i, len;
+     struct directory_entry * s_entry;
+     struct directory_entry ** sortlist;
+     
+     s_entry = *sort_dir;
+     while(s_entry)
+     {
+	  dcount++;
+	  s_entry = s_entry->next;
+     }
+
+     /*
+      * OK, now we know how many there are.  Build a vector for sorting. 
+      */
+     sortlist =   (struct directory_entry **) 
+	  e_malloc(sizeof(struct directory_entry *) * dcount);
+
+     dcount = 0;
+     s_entry = *sort_dir;
+     while(s_entry)
+     {
+	  sortlist[dcount] = s_entry;
+	  len = s_entry->isorec.name_len[0];
+	  s_entry->isorec.name[len] = 0;
+	  dcount++;
+	  s_entry = s_entry->next;
+     }
+  
+     qsort(sortlist, dcount, sizeof(struct directory_entry *), 
+	   (int (*)(const void *, const void *))compare_dirs);
+     
+     /* 
+      * Now reassemble the linked list in the proper sorted order 
+      */
+     for(i=0; i<dcount-1; i++)
+     {
+	  sortlist[i]->next = sortlist[i+1];
+     }
+
+     sortlist[dcount-1]->next = NULL;
+     *sort_dir = sortlist[0];
+     
+     free(sortlist);
+     
+}
+
+void generate_root_record()
+{
+     time_t ctime;
+     
+     time (&ctime);
+
+     local = *localtime(&ctime);
+     gmt   = *gmtime(&ctime);
+     
+     root_record.length[0] = 1 + sizeof(struct iso_directory_record)
+	  - sizeof(root_record.name);
+     root_record.ext_attr_length[0] = 0;
+     set_733((char *) root_record.extent, root->extent);
+     set_733((char *) root_record.size, ROUND_UP(root->size));
+     iso9660_date(root_record.date, ctime);
+     root_record.flags[0] = 2;
+     root_record.file_unit_size[0] = 0;
+     root_record.interleave[0] = 0;
+     set_723(root_record.volume_sequence_number, DEF_VSN);
+     root_record.name_len[0] = 1;
+}
+
+static void FDECL1(assign_file_addresses, struct directory *, dpnt)
+{
+     struct directory * finddir;
+     struct directory_entry * s_entry;
+     struct file_hash *s_hash;
+     struct deferred_write * dwpnt;
+     char whole_path[1024];
+     
+     while (dpnt)
+     {
+	  s_entry = dpnt->contents;
+	  for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next)
+	  {
+	       
+	       /*
+		* If we already have an  extent for this entry,
+		* then don't assign a new one.  It must have come
+		* from a previous session on the disc.  Note that
+		* we don't end up scheduling the thing for writing
+		* either.
+		*/
+	       if( isonum_733((unsigned char *) s_entry->isorec.extent) != 0 )
+	       {
+		    continue;
+	       }
+	       
+	       /* 
+		* This saves some space if there are symlinks present 
+		*/
+	       s_hash = find_hash(s_entry->dev, s_entry->inode);
+	       if(s_hash)
+	       {
+		    if(verbose)
+		    {
+			 fprintf(stderr, "Cache hit for %s%s%s\n",s_entry->filedir->de_name, 
+				 SPATH_SEPARATOR, s_entry->name);
+		    }
+		    set_733((char *) s_entry->isorec.extent, s_hash->starting_block);
+		    set_733((char *) s_entry->isorec.size, s_hash->size);
+		    continue;
+	       }
+
+	       /*
+		* If this is for a directory that is not a . or a .. entry, 
+		* then look up the information for the entry.  We have already
+		* assigned extents for directories, so we just need to
+		* fill in the blanks here.
+		*/
+	       if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..") && 
+		   s_entry->isorec.flags[0] == 2)
+	       {
+		    finddir = dpnt->subdir;
+		    while(1==1)
+		    {
+			 if(finddir->self == s_entry) break;
+			 finddir = finddir->next;
+			 if(!finddir) 
+			 {
+			      fprintf(stderr,"Fatal goof\n"); exit(1);
+			 }
+		    }
+		    set_733((char *) s_entry->isorec.extent, finddir->extent);
+		    s_entry->starting_block = finddir->extent;
+		    s_entry->size = ROUND_UP(finddir->size);
+		    total_dir_size += s_entry->size;
+		    add_hash(s_entry);
+		    set_733((char *) s_entry->isorec.size, ROUND_UP(finddir->size));
+		    continue;
+	       }
+
+
+	       /*
+		* If this is . or .., then look up the relevant info from the
+		* tables.
+		*/
+	       if(strcmp(s_entry->name,".") == 0) 
+	       {
+		    set_733((char *) s_entry->isorec.extent, dpnt->extent);
+		    
+		    /* 
+		     * Set these so that the hash table has the
+		     * correct information
+		     */
+		    s_entry->starting_block = dpnt->extent;
+		    s_entry->size = ROUND_UP(dpnt->size);
+		    
+		    add_hash(s_entry);
+		    s_entry->starting_block = dpnt->extent;
+		    set_733((char *) s_entry->isorec.size, ROUND_UP(dpnt->size));
+		    continue;
+	       }
+
+	       if(strcmp(s_entry->name,"..") == 0) 
+	       {
+		    if(dpnt == root)
+		    { 
+			 total_dir_size += root->size;
+		    }
+		    set_733((char *) s_entry->isorec.extent, dpnt->parent->extent);
+		    
+		    /* 
+		     * Set these so that the hash table has the
+		     * correct information
+		     */
+		    s_entry->starting_block = dpnt->parent->extent;
+		    s_entry->size = ROUND_UP(dpnt->parent->size);
+		    
+		    add_hash(s_entry);
+		    s_entry->starting_block = dpnt->parent->extent;
+		    set_733((char *) s_entry->isorec.size, ROUND_UP(dpnt->parent->size));
+		    continue;
+	       }
+
+	       /* 
+		* Some ordinary non-directory file.  Just schedule the
+		* file to be written.  This is all quite
+		* straightforward, just make a list and assign extents
+		* as we go.  Once we get through writing all of the
+		* directories, we should be ready write out these
+		* files
+		*/
+	       if(s_entry->size) 
+	       {
+		    dwpnt = (struct deferred_write *) 
+			 e_malloc(sizeof(struct deferred_write));
+		    if(dw_tail)
+		    {
+			 dw_tail->next = dwpnt;
+			 dw_tail = dwpnt;
+		    } 
+		    else 
+		    {
+			 dw_head = dwpnt;
+			 dw_tail = dwpnt;
+		    }
+		    if(s_entry->inode  ==  TABLE_INODE) 
+		    {
+			 dwpnt->table = s_entry->table;
+			 dwpnt->name = NULL;
+			 sprintf(whole_path,"%s%sTRANS.TBL",
+				 s_entry->filedir->whole_name, SPATH_SEPARATOR);
+		    } 
+		    else 
+		    {
+			 dwpnt->table = NULL;
+			 strcpy(whole_path, s_entry->whole_name);
+			 dwpnt->name = strdup(whole_path);
+		    }
+		    dwpnt->next = NULL;
+		    dwpnt->size = s_entry->size;
+		    dwpnt->extent = last_extent;
+		    set_733((char *) s_entry->isorec.extent, last_extent);
+		    s_entry->starting_block = last_extent;
+		    add_hash(s_entry);
+		    last_extent += ROUND_UP(s_entry->size) >> 11;
+		    if(verbose)
+		    {
+			 fprintf(stderr,"%d %d %s\n", s_entry->starting_block,
+				 last_extent-1, whole_path);
+		    }
+#ifdef DBG_ISO
+		    if((ROUND_UP(s_entry->size) >> 11) > 500)
+		    {
+			 fprintf(stderr,"Warning: large file %s\n", whole_path);
+			 fprintf(stderr,"Starting block is %d\n", s_entry->starting_block);
+			 fprintf(stderr,"Reported file size is %d extents\n", s_entry->size);
+			 
+		    }
+#endif
+		    if(last_extent > (800000000 >> 11)) 
+		    { 
+			 /*
+			  * More than 800Mb? Punt 
+			  */
+			 fprintf(stderr,"Extent overflow processing file %s\n", whole_path);
+			 fprintf(stderr,"Starting block is %d\n", s_entry->starting_block);
+			 fprintf(stderr,"Reported file size is %d extents\n", s_entry->size);
+			 exit(1);
+		    }
+		    continue;
+	       }
+
+	       /*
+		* This is for zero-length files.  If we leave the extent 0,
+		* then we get screwed, because many readers simply drop files
+		* that have an extent of zero.  Thus we leave the size 0,
+		* and just assign the extent number.
+		*/
+	       set_733((char *) s_entry->isorec.extent, last_extent);
+	  }
+	  if(dpnt->subdir) 
+	  {
+	       assign_file_addresses(dpnt->subdir);
+	  }
+	  dpnt = dpnt->next;
+     }
+} /* assign_file_addresses(... */
+
+void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile)
+{
+     unsigned int			  ce_address = 0;
+     char				* ce_buffer;
+     unsigned int			  ce_index = 0;
+     unsigned int			  ce_size;
+     unsigned int			  dir_index;
+     char				* directory_buffer;
+     int				  new_reclen;
+     struct directory_entry		* s_entry;
+     struct directory_entry		* s_entry_d;
+     unsigned int			  total_size;
+     
+     total_size = (dpnt->size + (SECTOR_SIZE - 1)) &  ~(SECTOR_SIZE - 1);
+     directory_buffer = (char *) e_malloc(total_size);
+     memset(directory_buffer, 0, total_size);
+     dir_index = 0;
+     
+     ce_size = (dpnt->ce_bytes + (SECTOR_SIZE - 1)) &  ~(SECTOR_SIZE - 1);
+     ce_buffer = NULL;
+     
+     if(ce_size) 
+     {
+	  ce_buffer = (char *) e_malloc(ce_size);
+	  memset(ce_buffer, 0, ce_size);
+	  
+	  ce_index = 0;
+	  
+	  /*
+	   * Absolute byte address of CE entries for this directory 
+	   */
+	  ce_address = last_extent_written + (total_size >> 11);
+	  ce_address = ce_address << 11;
+     }
+     
+     s_entry = dpnt->contents;
+     while(s_entry) 
+     {
+
+	  /* 
+	   * We do not allow directory entries to cross sector boundaries.  
+	   * Simply pad, and then start the next entry at the next sector 
+	   */
+	  new_reclen = s_entry->isorec.length[0];
+	  if( (dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE )
+	  {
+	       dir_index = (dir_index + (SECTOR_SIZE - 1)) & 
+		    ~(SECTOR_SIZE - 1);
+	  }
+
+	  memcpy(directory_buffer + dir_index, &s_entry->isorec, 
+		 sizeof(struct iso_directory_record) -
+		 sizeof(s_entry->isorec.name) + s_entry->isorec.name_len[0]);
+	  dir_index += sizeof(struct iso_directory_record) - 
+	       sizeof (s_entry->isorec.name)+ s_entry->isorec.name_len[0];
+
+	  /*
+	   * Add the Rock Ridge attributes, if present 
+	   */
+	  if(s_entry->rr_attr_size)
+	  {
+	       if(dir_index & 1)
+	       {
+		    directory_buffer[dir_index++] = 0;
+	       }
+
+	       /* 
+		* If the RR attributes were too long, then write the
+		* CE records, as required.
+		*/
+	       if(s_entry->rr_attr_size != s_entry->total_rr_attr_size) 
+	       {
+		    unsigned char * pnt;
+		    int len, nbytes;
+		    
+		    /* 
+		     * Go through the entire record and fix up the CE entries
+		     * so that the extent and offset are correct 
+		     */
+		    
+		    pnt = s_entry->rr_attributes;
+		    len = s_entry->total_rr_attr_size;
+		    while(len > 3)
+		    {
+#ifdef DEBUG
+			 if (!ce_size)
+			 {
+			      fprintf(stderr,"Warning: ce_index(%d) && ce_address(%d) not initialized\n",
+				      ce_index, ce_address);
+			 }
+#endif
+			 
+			 if(pnt[0] == 'C' && pnt[1] == 'E') 
+			 {
+			      nbytes = get_733( (char *) pnt+20);
+			      
+			      if((ce_index & (SECTOR_SIZE - 1)) + nbytes >=
+				 SECTOR_SIZE) 
+			      {
+				   ce_index = ROUND_UP(ce_index);
+			      }
+			      
+			      set_733( (char *) pnt+4, 
+				       (ce_address + ce_index) >> 11);
+			      set_733( (char *) pnt+12, 
+				       (ce_address + ce_index) & (SECTOR_SIZE - 1));
+			      
+			      
+			      /* 
+			       * Now store the block in the ce buffer 
+			       */
+			      memcpy(ce_buffer + ce_index, 
+				     pnt + pnt[2], nbytes);
+			      ce_index += nbytes;
+			      if(ce_index & 1) 
+			      {
+				   ce_index++;
+			      }
+			 }
+			 len -= pnt[2];
+			 pnt += pnt[2];
+		    }
+		    
+	       }
+
+	       rockridge_size += s_entry->total_rr_attr_size;
+	       memcpy(directory_buffer + dir_index, s_entry->rr_attributes, 
+		      s_entry->rr_attr_size);
+	       dir_index += s_entry->rr_attr_size;
+	  }
+	  if(dir_index & 1)
+	  {
+	       directory_buffer[dir_index++] = 0;
+	  }
+	  
+	  s_entry_d = s_entry;
+	  s_entry = s_entry->next;
+	  
+	  if (s_entry_d->rr_attributes) free(s_entry_d->rr_attributes);
+	  if( s_entry_d->name != NULL )
+	    {
+	      free (s_entry_d->name);
+	    }
+	  if( s_entry_d->whole_name != NULL )
+	    {
+	      free (s_entry_d->whole_name);
+	    }
+	  free (s_entry_d);
+     }
+     sort_dir = NULL;
+
+     if(dpnt->size != dir_index)
+     {
+	  fprintf(stderr,"Unexpected directory length %d %d %s\n",dpnt->size, 
+	    dir_index, dpnt->de_name);
+     }
+
+     xfwrite(directory_buffer, 1, total_size, outfile);
+     last_extent_written += total_size >> 11;
+     free(directory_buffer);
+
+     if(ce_size)
+     {
+	  if(ce_index != dpnt->ce_bytes)
+	  {
+	       fprintf(stderr,"Continuation entry record length mismatch (%d %d).\n",
+		       ce_index, dpnt->ce_bytes);
+	  }
+	  xfwrite(ce_buffer, 1, ce_size, outfile);
+	  last_extent_written += ce_size >> 11;
+	  free(ce_buffer);
+     }
+     
+} /* generate_one_directory(... */
+
+static 
+void FDECL1(build_pathlist, struct directory *, node)
+{
+     struct directory * dpnt;
+     
+     dpnt = node;
+     
+     while (dpnt)
+     {
+	  pathlist[dpnt->path_index] = dpnt;
+	  if(dpnt->subdir) build_pathlist(dpnt->subdir);
+	  dpnt = dpnt->next;
+     }
+} /* build_pathlist(... */
+
+int FDECL2(compare_paths, void const *, r, void const *, l) 
+{
+  struct directory const *ll = *(struct directory * const *)l;
+  struct directory const *rr = *(struct directory * const *)r;
+
+  if (rr->parent->path_index < ll->parent->path_index)
+  {
+       return -1;
+  }
+
+  if (rr->parent->path_index > ll->parent->path_index) 
+  {
+       return 1;
+  }
+
+  return strcmp(rr->self->isorec.name, ll->self->isorec.name);
+  
+} /* compare_paths(... */
+
+void generate_path_tables()
+{
+  struct directory_entry * de;
+  struct directory	 * dpnt;
+  int			   fix;
+  int			   i;
+  int			   j;
+  int			   namelen;
+  char			 * npnt;
+  char			 * npnt1;
+  int			   tablesize;
+
+  /*
+   * First allocate memory for the tables and initialize the memory 
+   */
+  tablesize = path_blocks << 11;
+  path_table_m = (char *) e_malloc(tablesize);
+  path_table_l = (char *) e_malloc(tablesize);
+  memset(path_table_l, 0, tablesize);
+  memset(path_table_m, 0, tablesize);
+
+  /*
+   * Now start filling in the path tables.  Start with root directory 
+   */
+  path_table_index = 0;
+  pathlist = (struct directory **) e_malloc(sizeof(struct directory *) 
+					    * next_path_index);
+  memset(pathlist, 0, sizeof(struct directory *) * next_path_index);
+  build_pathlist(root);
+
+  do
+  {
+       fix = 0;
+       qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *), 
+	     (int (*)(const void *, const void *))compare_paths);
+
+       for(j=1; j<next_path_index; j++)
+       {
+	    if(pathlist[j]->path_index != j)
+	    {
+		 pathlist[j]->path_index = j;
+		 fix++;
+	    }
+       }
+  } while(fix);
+
+  for(j=1; j<next_path_index; j++)
+  {
+       dpnt = pathlist[j];
+       if(!dpnt)
+       {
+	    fprintf(stderr,"Entry %d not in path tables\n", j);
+	    exit(1);
+       }
+       npnt = dpnt->de_name;
+       
+       /* 
+	* So the root comes out OK 
+	*/
+       if( (*npnt == 0) || (dpnt == root) ) 
+       {
+	    npnt = ".";  
+       }
+       npnt1 = strrchr(npnt, PATH_SEPARATOR);
+       if(npnt1) 
+       { 
+	    npnt = npnt1 + 1;
+       }
+       
+       de = dpnt->self;
+       if(!de) 
+       {
+	    fprintf(stderr,"Fatal goof\n"); 
+	    exit(1);
+       }
+       
+       
+       namelen = de->isorec.name_len[0];
+       
+       path_table_l[path_table_index] = namelen;
+       path_table_m[path_table_index] = namelen;
+       path_table_index += 2;
+       
+       set_731(path_table_l + path_table_index, dpnt->extent); 
+       set_732(path_table_m + path_table_index, dpnt->extent); 
+       path_table_index += 4;
+       
+       set_721(path_table_l + path_table_index, 
+	       dpnt->parent->path_index); 
+       set_722(path_table_m + path_table_index, 
+	       dpnt->parent->path_index); 
+       path_table_index += 2;
+       
+       for(i =0; i<namelen; i++)
+       {
+	    path_table_l[path_table_index] = de->isorec.name[i];
+	    path_table_m[path_table_index] = de->isorec.name[i];
+	    path_table_index++;
+       }
+       if(path_table_index & 1) 
+       {
+	    path_table_index++;  /* For odd lengths we pad */
+       }
+  }
+  
+  free(pathlist);
+  if(path_table_index != path_table_size)
+  {
+       fprintf(stderr,"Path table lengths do not match %d %d\n",
+	       path_table_index,
+	       path_table_size);
+  }
+} /* generate_path_tables(... */
+
+void
+FDECL3(memcpy_max, char *, to, char *, from, int, max)
+{
+  int n = strlen(from);
+  if (n > max)
+  {
+       n = max;
+  }
+  memcpy(to, from, n);
+
+} /* memcpy_max(... */
+
+int FDECL1(iso_write, FILE *, outfile)
+{
+  char				buffer[2048];
+  int				i;
+  char				iso_time[17];
+  int				should_write;
+
+  time(&begun);
+  assign_file_addresses(root);
+
+  memset(buffer, 0, sizeof(buffer));
+
+  /*
+   * This will break  in the year  2000, I supose, but there is no good way
+   * to get the top two digits of the year. 
+   */
+  sprintf(iso_time, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00", 1900 + local.tm_year,
+	  local.tm_mon+1, local.tm_mday,
+	  local.tm_hour, local.tm_min, local.tm_sec);
+
+  local.tm_min -= gmt.tm_min;
+  local.tm_hour -= gmt.tm_hour;
+  local.tm_yday -= gmt.tm_yday;
+  iso_time[16] = (local.tm_min + 60*(local.tm_hour + 24*local.tm_yday)) / 15;
+
+ /*
+   * First, we output 16 sectors of all zero 
+   */
+
+  for(i=0; i<16; i++)
+    {
+      xfwrite(buffer, 1, sizeof(buffer), outfile);
+    }
+
+  last_extent_written += 16;
+
+  /*
+   * Next we write out the primary descriptor for the disc 
+   */
+  memset(&vol_desc, 0, sizeof(vol_desc));
+  vol_desc.type[0] = ISO_VD_PRIMARY;
+  memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
+  vol_desc.version[0] = 1;
+  
+  memset(vol_desc.system_id, ' ', sizeof(vol_desc.system_id));
+  memcpy_max(vol_desc.system_id, system_id, strlen(system_id));
+  
+  memset(vol_desc.volume_id, ' ', sizeof(vol_desc.volume_id));
+  memcpy_max(vol_desc.volume_id, volume_id, strlen(volume_id));
+  
+  should_write = last_extent - session_start;
+  set_733((char *) vol_desc.volume_space_size, should_write);
+  set_723(vol_desc.volume_set_size, 1);
+  set_723(vol_desc.volume_sequence_number, DEF_VSN);
+  set_723(vol_desc.logical_block_size, 2048);
+  
+  /*
+   * The path tables are used by DOS based machines to cache directory
+   * locations 
+   */
+
+  set_733((char *) vol_desc.path_table_size, path_table_size);
+  set_731(vol_desc.type_l_path_table, path_table[0]);
+  set_731(vol_desc.opt_type_l_path_table, path_table[1]);
+  set_732(vol_desc.type_m_path_table, path_table[2]);
+  set_732(vol_desc.opt_type_m_path_table, path_table[3]);
+
+  /*
+   * Now we copy the actual root directory record 
+   */
+  memcpy(vol_desc.root_directory_record, &root_record, 
+	 sizeof(struct iso_directory_record) + 1);
+
+  /*
+   * The rest is just fluff.  It looks nice to fill in many of these fields,
+   * though.
+   */
+  FILL_SPACE(volume_set_id);
+  if(volset_id)  memcpy_max(vol_desc.volume_set_id,  volset_id, strlen(volset_id));
+
+  FILL_SPACE(publisher_id);
+  if(publisher)  memcpy_max(vol_desc.publisher_id,  publisher, strlen(publisher));
+
+  FILL_SPACE(preparer_id);
+  if(preparer)  memcpy_max(vol_desc.preparer_id,  preparer, strlen(preparer));
+
+  FILL_SPACE(application_id);
+  if(appid) memcpy_max(vol_desc.application_id, appid, strlen(appid));
+
+  FILL_SPACE(copyright_file_id);
+  if(copyright) memcpy_max(vol_desc.copyright_file_id, copyright, 
+		       strlen(copyright));
+
+  FILL_SPACE(abstract_file_id);
+  if(abstract) memcpy_max(vol_desc.abstract_file_id, abstract, 
+			  strlen(abstract));
+
+  FILL_SPACE(bibliographic_file_id);
+  if(biblio) memcpy_max(vol_desc.bibliographic_file_id, biblio, 
+		       strlen(biblio));
+
+  FILL_SPACE(creation_date);
+  FILL_SPACE(modification_date);
+  FILL_SPACE(expiration_date);
+  FILL_SPACE(effective_date);
+  vol_desc.file_structure_version[0] = 1;
+  FILL_SPACE(application_data);
+
+  memcpy(vol_desc.creation_date,  iso_time, 17);
+  memcpy(vol_desc.modification_date,  iso_time, 17);
+  memcpy(vol_desc.expiration_date, "0000000000000000", 17);
+  memcpy(vol_desc.effective_date,  iso_time,  17);
+
+  /*
+   * if not a bootable cd do it the old way 
+   */
+  xfwrite(&vol_desc, 1, 2048, outfile);
+  last_extent_written++;
+  if (use_eltorito) 
+    {
+      /*
+       * Next we write out the boot volume descriptor for the disc 
+       */
+      get_torito_desc(&boot_desc);
+      xfwrite(&boot_desc, 1, 2048, outfile);
+      last_extent_written ++;
+    }
+  
+  /*
+   * Now write the end volume descriptor.  Much simpler than the other one 
+   */
+  memset(&vol_desc, 0, sizeof(vol_desc));
+  vol_desc.type[0] = ISO_VD_END;
+  memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
+  vol_desc.version[0] = 1;
+  xfwrite(&vol_desc, 1, 2048, outfile);
+  last_extent_written += 1;
+
+  /*
+   * Next we write the path tables 
+   */
+  xfwrite(path_table_l, 1, path_blocks << 11, outfile);
+  xfwrite(path_table_m, 1, path_blocks << 11, outfile);
+  last_extent_written += 2*path_blocks;
+  free(path_table_l);
+  free(path_table_m);
+  path_table_l = NULL;
+  path_table_m = NULL;
+
+  /*
+   * OK, all done with that crap.  Now write out the directories.
+   * This is where the fur starts to fly, because we need to keep track of
+   * each file as we find it and keep track of where we put it. 
+   */
+
+#ifdef DBG_ISO
+  fprintf(stderr,"Total directory extents being written = %d\n", last_extent);
+#endif
+#if 0 
+ generate_one_directory(root, outfile);
+#endif
+  generate_iso9660_directories(root, outfile);
+
+  if(extension_record) 
+    {
+      xfwrite(extension_record, 1, SECTOR_SIZE, outfile);
+      last_extent_written++;
+    }
+
+  /* 
+   * Now write all of the files that we need. 
+   */
+  fprintf(stderr,"Total extents scheduled to be written = %d\n", 
+	  last_extent - session_start);
+  write_files(outfile);
+  
+  fprintf(stderr,"Total extents actually written = %d\n", 
+	  last_extent_written - session_start);
+  /* 
+   * Hard links throw us off here 
+   */
+  if(should_write != last_extent - session_start)
+    {
+      fprintf(stderr,"Number of extents written not what was predicted.  Please fix.\n");
+      fprintf(stderr,"Predicted = %d, written = %d\n", should_write, last_extent);
+    }
+
+  fprintf(stderr,"Total translation table size: %d\n", table_size);
+  fprintf(stderr,"Total rockridge attributes bytes: %d\n", rockridge_size);
+  fprintf(stderr,"Total directory bytes: %d\n", total_dir_size);
+  fprintf(stderr,"Path table size(bytes): %d\n", path_table_size);
+
+#ifdef DEBUG
+  fprintf(stderr, "next extent, last_extent, last_extent_written %d %d %d\n",
+	  next_extent, last_extent, last_extent_written);
+#endif
+
+  return 0;
+
+} /* iso_write(... */