summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gnu/usr.sbin/mkisofs/COPYING345
-rw-r--r--gnu/usr.sbin/mkisofs/ChangeLog840
-rw-r--r--gnu/usr.sbin/mkisofs/Makefile11
-rw-r--r--gnu/usr.sbin/mkisofs/README125
-rw-r--r--gnu/usr.sbin/mkisofs/README.eltorito98
-rw-r--r--gnu/usr.sbin/mkisofs/README.session42
-rw-r--r--gnu/usr.sbin/mkisofs/TODO17
-rw-r--r--gnu/usr.sbin/mkisofs/config.h54
-rw-r--r--gnu/usr.sbin/mkisofs/defaults.h45
-rw-r--r--gnu/usr.sbin/mkisofs/diag/README78
-rw-r--r--gnu/usr.sbin/mkisofs/diag/dump.c205
-rw-r--r--gnu/usr.sbin/mkisofs/diag/isodump.c478
-rw-r--r--gnu/usr.sbin/mkisofs/diag/isoinfo.8125
-rw-r--r--gnu/usr.sbin/mkisofs/diag/isoinfo.c554
-rw-r--r--gnu/usr.sbin/mkisofs/diag/isovfy.c514
-rw-r--r--gnu/usr.sbin/mkisofs/eltorito.c262
-rw-r--r--gnu/usr.sbin/mkisofs/exclude.c57
-rw-r--r--gnu/usr.sbin/mkisofs/exclude.h11
-rw-r--r--gnu/usr.sbin/mkisofs/files.c363
-rw-r--r--gnu/usr.sbin/mkisofs/fnmatch.c227
-rw-r--r--gnu/usr.sbin/mkisofs/fnmatch.h81
-rw-r--r--gnu/usr.sbin/mkisofs/hash.c227
-rw-r--r--gnu/usr.sbin/mkisofs/iso9660.h158
-rw-r--r--gnu/usr.sbin/mkisofs/match.c57
-rw-r--r--gnu/usr.sbin/mkisofs/match.h15
-rw-r--r--gnu/usr.sbin/mkisofs/mkisofs.8428
-rw-r--r--gnu/usr.sbin/mkisofs/mkisofs.c661
-rw-r--r--gnu/usr.sbin/mkisofs/mkisofs.h334
-rw-r--r--gnu/usr.sbin/mkisofs/mkisofs.spec45
-rw-r--r--gnu/usr.sbin/mkisofs/multi.c989
-rw-r--r--gnu/usr.sbin/mkisofs/name.c376
-rw-r--r--gnu/usr.sbin/mkisofs/rock.c557
-rw-r--r--gnu/usr.sbin/mkisofs/tree.c1275
-rw-r--r--gnu/usr.sbin/mkisofs/write.c1140
34 files changed, 10794 insertions, 0 deletions
diff --git a/gnu/usr.sbin/mkisofs/COPYING b/gnu/usr.sbin/mkisofs/COPYING
new file mode 100644
index 00000000000..946cb19c31a
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/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/gnu/usr.sbin/mkisofs/ChangeLog b/gnu/usr.sbin/mkisofs/ChangeLog
new file mode 100644
index 00000000000..62d713abcff
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/ChangeLog
@@ -0,0 +1,840 @@
+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/gnu/usr.sbin/mkisofs/Makefile b/gnu/usr.sbin/mkisofs/Makefile
new file mode 100644
index 00000000000..9979bfbe608
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/Makefile
@@ -0,0 +1,11 @@
+# $OpenBSD: Makefile,v 1.1 1997/09/15 06:01:53 downsj Exp $
+
+PROG= mkisofs
+MAN= mkisofs.8
+
+SRCS= mkisofs.c tree.c write.c hash.c rock.c exclude.c multi.c \
+ files.c fnmatch.c match.c name.c eltorito.c
+
+CFLAGS+=-DSYSTEM_ID_DEFAULT=\"OpenBSD\" -I${.CURDIR}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.sbin/mkisofs/README b/gnu/usr.sbin/mkisofs/README
new file mode 100644
index 00000000000..4c1c8c7d351
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/README
@@ -0,0 +1,125 @@
+# $OpenBSD: README,v 1.1 1997/09/15 06:01:52 downsj Exp $
+# $From: 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/gnu/usr.sbin/mkisofs/README.eltorito b/gnu/usr.sbin/mkisofs/README.eltorito
new file mode 100644
index 00000000000..4e78f10ef88
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/README.eltorito
@@ -0,0 +1,98 @@
+# $OpenBSD: README.eltorito,v 1.1 1997/09/15 06:01:52 downsj Exp $
+# $From: 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/gnu/usr.sbin/mkisofs/README.session b/gnu/usr.sbin/mkisofs/README.session
new file mode 100644
index 00000000000..a519f019cbe
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/README.session
@@ -0,0 +1,42 @@
+# $OpenBSD: README.session,v 1.1 1997/09/15 06:01:53 downsj Exp $
+# $From: 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/gnu/usr.sbin/mkisofs/TODO b/gnu/usr.sbin/mkisofs/TODO
new file mode 100644
index 00000000000..b8f377c0d49
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/TODO
@@ -0,0 +1,17 @@
+# $OpenBSD: TODO,v 1.1 1997/09/15 06:01:52 downsj Exp $
+# $From: TODO,v 1.2 1997/02/23 15:46:38 eric Rel $
+ 1) Allow multiple input paths to be concatenated together.
+ This is a little tricky, because the directory entries need to be
+ correctly sorted as per iso9660 specifications. It would be better to
+ force the user to add hard links or copies of the files rather than do
+ the wrong thing. Leave alone for the time being, I am not sure that
+ this feature is really needed.
+
+ 2) For symlinks, we may need to strip out the leading path
+ information if the link is to an absolute file, and the absolute
+ address is in the space that we are dumping to the CDROM. Who the
+ hell knows what we should really do with this, actually. Leave it
+ for now and see if anyone squalks.
+
+ 3) Find out if output needs to be written at a particular
+ blocksize or not.
diff --git a/gnu/usr.sbin/mkisofs/config.h b/gnu/usr.sbin/mkisofs/config.h
new file mode 100644
index 00000000000..3fccfd7a7b9
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/config.h
@@ -0,0 +1,54 @@
+/* $OpenBSD: config.h,v 1.1 1997/09/15 06:01:52 downsj Exp $ */
+/* 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. */
+/* #undef HAVE_MALLOC_H */
+
+/* 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. */
+/* #undef HAVE_SYS_SYSMACROS_H */
+
+/* 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/gnu/usr.sbin/mkisofs/defaults.h b/gnu/usr.sbin/mkisofs/defaults.h
new file mode 100644
index 00000000000..db740d3771e
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/defaults.h
@@ -0,0 +1,45 @@
+/* $OpenBSD: defaults.h,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * Header file defaults.h - assorted default values for character strings in
+ * the volume descriptor.
+ *
+ * $From: 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/gnu/usr.sbin/mkisofs/diag/README b/gnu/usr.sbin/mkisofs/diag/README
new file mode 100644
index 00000000000..92315118f7a
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/diag/README
@@ -0,0 +1,78 @@
+# $OpenBSD: README,v 1.1 1997/09/15 06:01:53 downsj Exp $
+#
+# $From: README,v 1.1 1997/02/23 16:14:56 eric Rel $
+#
+ I am enclosing 3 test programs that I use to verify the
+integrity of an iso9660 disc. The first one (isodump) is pretty
+simple - it dumps to the screen the contents of the various
+directories. The second one (isovfy) goes through and looks for
+problems of one kind or another.
+
+ To use, type something like "./isodump /dev/ramdisk" or
+"./isodump /dev/scd0", depending upon where the iso9660 disc is. It
+starts by displaying the files in the first sector of the root
+directory. It has some pretty simple one letter commands that you
+can use to traverse the directory tree.
+
+ a - move back one sector.
+ b - move forward one sector.
+ g - go to new logical sector.
+ q - quit
+
+The a and b commands do not try and stop you from going past the
+beginning or end of a sector, and the g command does not have any way
+of knowing whether the sector you request is actually a directory or
+not.
+
+ The output is displayed in several columns. The first column
+is the total length of the directory record for the file. The second
+column (in [] brackets) is the volume number. Next comes the starting
+extent number (in hex), and then comes the file size in bytes. Then
+cones the filename (not the Rock Ridge version), and this is preceeded
+by an "*" if the file is a directory. After this is a summary of the
+Rock Ridge fields present along with a display of the translation of
+the symbolic link name if the SL Rock Ridge record is present.
+
+ I tailored this program for debugging some of the problems
+that I was having earlier. The idea is that you can tailor it
+to test for problems that you might be having, so it is not intended
+as a be-all and end-all dump program.
+
+ If you move to a sector that does not contain directory
+information, the results are unpredictable.
+
+ The second program, isovfy, is run in the same way as isodump,
+except that you do not have to do much except let it run. I have it
+written to verify all kinds of different things, and as people find
+other sorts of problems other tests could be added.
+
+ The third program, dump.c, basically does a hexdump of the cd.
+This is screen oriented, and there are some simple commands:
+
+ a - move back one sector.
+ b - move forward one sector.
+ f - enter new search string.
+ + - search forward for search string.
+ g - go to new logical sector.
+ q - quit
+
+
+ Note that with the 'g' command, sectors are always given in
+hex, and represent 2048 byte sectors (as on the cdrom). If you know
+how to decode a raw iso9660 directory, you can pick out the starting
+extent number from the hexdump and know where to go from there. The
+starting extent appears something like 30 bytes prior to the start of
+the iso9660 (not Rock Ridge) filename, and it appears in a 7.3.3
+format (meaning that it occupies 8 bytes, 4 in little endian format,
+and 4 in big endian format). Thus you should see a mirror image of
+the bytes when looking at the extent number.
+
+ The isovfy program can also dump the contents of the path
+tables, but this capability is commented out right now. Feel free
+to enable this to see what is in the tables. Ultimately I may fix
+it so that this checks the integrity of the tables as well.
+
+ The isovfy program gives warnings about things like files that
+have a size of 0 but have an extent number assigned. The mkisofs program
+should never do this, but the YM software does leave these around.
+I think it is probably harmless in the YM case.~
diff --git a/gnu/usr.sbin/mkisofs/diag/dump.c b/gnu/usr.sbin/mkisofs/diag/dump.c
new file mode 100644
index 00000000000..be97d711482
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/diag/dump.c
@@ -0,0 +1,205 @@
+/* $OpenBSD: dump.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * File dump.c - dump a file/device both in hex and in ASCII.
+
+ 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[] ="$From: dump.c,v 1.2 1997/02/23 19:10:49 eric Rel $";
+
+#include "../config.h"
+
+#include <stdio.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#include <sys/ioctl.h>
+#else
+#include <termio.h>
+#endif
+#include <signal.h>
+
+FILE * infile;
+int file_addr;
+unsigned char buffer[256];
+unsigned char search[64];
+
+#define PAGE 256
+
+#ifdef HAVE_TERMIOS_H
+struct termios savetty;
+struct termios newtty;
+#else
+struct termio savetty;
+struct termio newtty;
+#endif
+
+reset_tty(){
+#ifdef HAVE_TERMIOS_H
+ if(tcsetattr(0, TCSANOW, &savetty) == -1)
+#else
+ if(ioctl(0, TCSETAF, &savetty)==-1)
+#endif
+ {
+ printf("cannot put tty into normal mode\n");
+ exit(1);
+ }
+}
+
+set_tty(){
+#ifdef HAVE_TERMIOS_H
+ if(tcsetattr(0, TCSANOW, &newtty) == -1)
+#else
+ if(ioctl(0, TCSETAF, &newtty)==-1)
+#endif
+ {
+ printf("cannot put tty into raw mode\n");
+ exit(1);
+ }
+}
+
+
+/* Come here when we get a suspend signal from the terminal */
+
+void
+onsusp (int sig)
+{
+ /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
+ signal(SIGTTOU, SIG_IGN);
+ reset_tty ();
+ fflush (stdout);
+ signal(SIGTTOU, SIG_DFL);
+ /* Send the TSTP signal to suspend our process group */
+ signal(SIGTSTP, SIG_DFL);
+/* sigsetmask(0);*/
+ kill (0, SIGTSTP);
+ /* Pause for station break */
+
+ /* We're back */
+ signal (SIGTSTP, onsusp);
+ set_tty ();
+}
+
+
+
+crsr2(int row, int col){
+ printf("\033[%d;%dH",row,col);
+}
+
+showblock(int flag){
+ unsigned int k;
+ int i, j;
+ lseek(fileno(infile), file_addr, 0);
+ read(fileno(infile), buffer, sizeof(buffer));
+ if(flag) {
+ for(i=0;i<16;i++){
+ crsr2(i+3,1);
+ printf("%8.8x ",file_addr+(i<<4));
+ for(j=15;j>=0;j--){
+ printf("%2.2x",buffer[(i<<4)+j]);
+ if(!(j & 0x3)) printf(" ");
+ };
+ for(j=0;j< 16;j++){
+ k = buffer[(i << 4) + j];
+ if(k >= ' ' && k < 0x80) printf("%c",k);
+ else printf(".");
+ };
+ }
+ };
+ crsr2(20,1);
+ printf(" Zone, zone offset: %6x %4.4x ",file_addr>>11, file_addr & 0x7ff);
+ fflush(stdout);
+}
+
+getbyte()
+{
+ char c1;
+ c1 = buffer[file_addr & (PAGE-1)];
+ file_addr++;
+ if ((file_addr & (PAGE-1)) == 0) showblock(0);
+ return c1;
+}
+
+main(int argc, char * argv[]){
+ char c;
+ int nbyte;
+ int i,j;
+ if(argc < 2) return 0;
+ infile = fopen(argv[1],"rb");
+ for(i=0;i<30;i++) printf("\n");
+ file_addr = 0;
+/* Now setup the keyboard for single character input. */
+#ifdef HAVE_TERMIOS_H
+ if(tcgetattr(0, &savetty) == -1)
+#else
+ if(ioctl(0, TCGETA, &savetty) == -1)
+#endif
+ {
+ printf("stdin must be a tty\n");
+ exit(1);
+ }
+ newtty=savetty;
+ newtty.c_lflag&=~ICANON;
+ newtty.c_lflag&=~ECHO;
+ newtty.c_cc[VMIN]=1;
+ set_tty();
+ signal(SIGTSTP, onsusp);
+
+ do{
+ if(file_addr < 0) file_addr = 0;
+ showblock(1);
+ read (0, &c, 1);
+ if (c == 'a') file_addr -= PAGE;
+ if (c == 'b') file_addr += PAGE;
+ if (c == 'g') {
+ crsr2(20,1);
+ printf("Enter new starting block (in hex):");
+ scanf("%x",&file_addr);
+ file_addr = file_addr << 11;
+ crsr2(20,1);
+ printf(" ");
+ };
+ if (c == 'f') {
+ crsr2(20,1);
+ printf("Enter new search string:");
+ fgets(search,sizeof(search),stdin);
+ while(search[strlen(search)-1] == '\n') search[strlen(search)-1] = 0;
+ crsr2(20,1);
+ printf(" ");
+ };
+ if (c == '+') {
+ while(1==1){
+ while(1==1){
+ c = getbyte(&file_addr);
+ if (c == search[0]) break;
+ };
+ for (j=1;j<strlen(search);j++)
+ if(search[j] != getbyte()) break;
+ if(j==strlen(search)) break;
+ };
+ file_addr &= ~(PAGE-1);
+ showblock(1);
+ };
+ if (c == 'q') break;
+ } while(1==1);
+ reset_tty();
+ fclose(infile);
+}
+
+
+
+
diff --git a/gnu/usr.sbin/mkisofs/diag/isodump.c b/gnu/usr.sbin/mkisofs/diag/isodump.c
new file mode 100644
index 00000000000..f15dae69b64
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/diag/isodump.c
@@ -0,0 +1,478 @@
+/* $OpenBSD: isodump.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * File isodump.c - dump iso9660 directory information.
+ *
+
+ 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[] ="$From: isodump.c,v 1.2 1997/02/23 19:11:24 eric Rel $";
+
+#include "../config.h"
+
+#include <stdio.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#include <sys/ioctl.h>
+#else
+#include <termio.h>
+#endif
+#include <signal.h>
+
+FILE * infile;
+int file_addr;
+unsigned char buffer[2048];
+unsigned char search[64];
+int blocksize;
+
+#define PAGE sizeof(buffer)
+
+#define ISODCL(from, to) (to - from + 1)
+
+
+int
+isonum_731 (char * p)
+{
+ return ((p[0] & 0xff)
+ | ((p[1] & 0xff) << 8)
+ | ((p[2] & 0xff) << 16)
+ | ((p[3] & 0xff) << 24));
+}
+
+int
+isonum_721 (char * p)
+{
+ return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
+}
+
+int
+isonum_723 (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_733 (unsigned char * p)
+{
+ return (isonum_731 (p));
+}
+
+struct iso_primary_descriptor {
+ unsigned char type [ISODCL ( 1, 1)]; /* 711 */
+ unsigned char id [ISODCL ( 2, 6)];
+ unsigned char version [ISODCL ( 7, 7)]; /* 711 */
+ unsigned char unused1 [ISODCL ( 8, 8)];
+ unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */
+ unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */
+ unsigned char unused2 [ISODCL ( 73, 80)];
+ unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
+ unsigned char unused3 [ISODCL ( 89, 120)];
+ unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */
+ unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
+ unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */
+ unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */
+ unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */
+ unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
+ unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */
+ unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
+ unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
+ unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */
+ unsigned char publisher_id [ISODCL (319, 446)]; /* achars */
+ unsigned char preparer_id [ISODCL (447, 574)]; /* achars */
+ unsigned char application_id [ISODCL (575, 702)]; /* achars */
+ unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
+ unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
+ unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
+ unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
+ unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
+ unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
+ unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
+ unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */
+ unsigned char unused4 [ISODCL (883, 883)];
+ unsigned char application_data [ISODCL (884, 1395)];
+ unsigned char unused5 [ISODCL (1396, 2048)];
+};
+
+struct iso_directory_record {
+ unsigned char length [ISODCL (1, 1)]; /* 711 */
+ unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */
+ unsigned char extent [ISODCL (3, 10)]; /* 733 */
+ unsigned char size [ISODCL (11, 18)]; /* 733 */
+ unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */
+ unsigned char flags [ISODCL (26, 26)];
+ unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */
+ unsigned char interleave [ISODCL (28, 28)]; /* 711 */
+ unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
+ unsigned char name_len [ISODCL (33, 33)]; /* 711 */
+ unsigned char name [1];
+};
+
+#ifdef HAVE_TERMIOS_H
+struct termios savetty;
+struct termios newtty;
+#else
+struct termio savetty;
+struct termio newtty;
+#endif
+
+reset_tty(){
+#ifdef HAVE_TERMIOS_H
+ if(tcsetattr(0, TCSANOW, &savetty) == -1)
+#else
+ if(ioctl(0, TCSETAF, &savetty)==-1)
+#endif
+ {
+ printf("cannot put tty into normal mode\n");
+ exit(1);
+ }
+}
+
+set_tty(){
+#ifdef HAVE_TERMIOS_H
+ if(tcsetattr(0, TCSANOW, &newtty) == -1)
+#else
+ if(ioctl(0, TCSETAF, &newtty)==-1)
+#endif
+ {
+ printf("cannot put tty into raw mode\n");
+ exit(1);
+ }
+}
+
+/* Come here when we get a suspend signal from the terminal */
+
+void
+onsusp (int signo)
+{
+ /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
+ signal(SIGTTOU, SIG_IGN);
+ reset_tty ();
+ fflush (stdout);
+ signal(SIGTTOU, SIG_DFL);
+ /* Send the TSTP signal to suspend our process group */
+ signal(SIGTSTP, SIG_DFL);
+/* sigsetmask(0);*/
+ kill (0, SIGTSTP);
+ /* Pause for station break */
+
+ /* We're back */
+ signal (SIGTSTP, onsusp);
+ set_tty ();
+}
+
+
+
+crsr2(int row, int col){
+ printf("\033[%d;%dH",row,col);
+}
+
+int parse_rr(unsigned char * pnt, int len, int cont_flag)
+{
+ int slen;
+ int ncount;
+ int extent;
+ int cont_extent, cont_offset, cont_size;
+ int flag1, flag2;
+ unsigned char *pnts;
+ char symlink[1024];
+ char name[1024];
+ int goof;
+/* printf(" RRlen=%d ", len); */
+
+ symlink[0] = 0;
+
+ cont_extent = cont_offset = cont_size = 0;
+
+ ncount = 0;
+ flag1 = flag2 = 0;
+ while(len >= 4){
+ if(ncount) printf(",");
+ else printf("[");
+ printf("%c%c", pnt[0], pnt[1]);
+ if(pnt[3] != 1) {
+ printf("**BAD RRVERSION");
+ return;
+ };
+ ncount++;
+ if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
+ if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1;
+ if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2;
+ if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4;
+ if(strncmp(pnt, "NM", 2) == 0) {
+ slen = pnt[2] - 5;
+ pnts = pnt+5;
+ if( (pnt[4] & 6) != 0 )
+ {
+ printf("*");
+ }
+ memset(name, 0, sizeof(name));
+ memcpy(name, pnts, slen);
+ printf("=%s", name);
+ flag2 |= 8;
+ }
+ if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16;
+ if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32;
+ if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64;
+ if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128;
+
+ if(strncmp(pnt, "PX", 2) == 0) {
+ extent = isonum_733(pnt+12);
+ printf("=%x", extent);
+ };
+
+ if(strncmp(pnt, "CE", 2) == 0) {
+ cont_extent = isonum_733(pnt+4);
+ cont_offset = isonum_733(pnt+12);
+ cont_size = isonum_733(pnt+20);
+ printf("=[%x,%x,%d]", cont_extent, cont_offset,
+ cont_size);
+ };
+
+ if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) {
+ extent = isonum_733(pnt+4);
+ printf("=%x", extent);
+ };
+
+ if(strncmp(pnt, "SL", 2) == 0) {
+ int cflag;
+
+ cflag = pnt[4];
+ pnts = pnt+5;
+ slen = pnt[2] - 5;
+ while(slen >= 1){
+ switch(pnts[0] & 0xfe){
+ case 0:
+ strncat(symlink, pnts+2, pnts[1]);
+ break;
+ case 2:
+ strcat (symlink, ".");
+ break;
+ case 4:
+ strcat (symlink, "..");
+ break;
+ case 8:
+ if((pnts[0] & 1) == 0)strcat (symlink, "/");
+ break;
+ case 16:
+ strcat(symlink,"/mnt");
+ printf("Warning - mount point requested");
+ break;
+ case 32:
+ strcat(symlink,"kafka");
+ printf("Warning - host_name requested");
+ break;
+ default:
+ printf("Reserved bit setting in symlink", goof++);
+ break;
+ };
+ if((pnts[0] & 0xfe) && pnts[1] != 0) {
+ printf("Incorrect length in symlink component");
+ };
+ if((pnts[0] & 1) == 0) strcat(symlink,"/");
+
+ slen -= (pnts[1] + 2);
+ pnts += (pnts[1] + 2);
+
+ };
+ if(cflag) strcat(symlink, "+");
+ printf("=%s", symlink);
+ symlink[0] = 0;
+ };
+
+ len -= pnt[2];
+ pnt += pnt[2];
+ if(len <= 3 && cont_extent) {
+ unsigned char sector[2048];
+ lseek(fileno(infile), cont_extent * blocksize, 0);
+ read(fileno(infile), sector, sizeof(sector));
+ flag2 |= parse_rr(&sector[cont_offset], cont_size, 1);
+ };
+ };
+ if(ncount) printf("]");
+ if (!cont_flag && flag1 != flag2)
+ printf("Flag %x != %x", flag1, flag2, goof++);
+ return flag2;
+}
+
+int
+dump_rr(struct iso_directory_record * idr)
+{
+ int len;
+ unsigned char * pnt;
+
+ len = idr->length[0] & 0xff;
+ len -= sizeof(struct iso_directory_record);
+ len += sizeof(idr->name);
+ len -= idr->name_len[0];
+ pnt = (unsigned char *) idr;
+ pnt += sizeof(struct iso_directory_record);
+ pnt -= sizeof(idr->name);
+ pnt += idr->name_len[0];
+ if((idr->name_len[0] & 1) == 0){
+ pnt++;
+ len--;
+ };
+ parse_rr(pnt, len, 0);
+}
+
+
+showblock(int flag){
+ unsigned int k;
+ int i, j;
+ int line;
+ struct iso_directory_record * idr;
+ lseek(fileno(infile), file_addr, 0);
+ read(fileno(infile), buffer, sizeof(buffer));
+ for(i=0;i<60;i++) printf("\n");
+ fflush(stdout);
+ i = line = 0;
+ if(flag) {
+ while(1==1){
+ crsr2(line+3,1);
+ idr = (struct iso_directory_record *) &buffer[i];
+ if(idr->length[0] == 0) break;
+ printf("%3d ", idr->length[0]);
+ printf("[%2d] ", idr->volume_sequence_number[0]);
+ printf("%5x ", isonum_733(idr->extent));
+ printf("%8d ", isonum_733(idr->size));
+ printf ((idr->flags[0] & 2) ? "*" : " ");
+ if(idr->name_len[0] == 1 && idr->name[0] == 0)
+ printf(". ");
+ else if(idr->name_len[0] == 1 && idr->name[0] == 1)
+ printf(".. ");
+ else {
+ for(j=0; j<idr->name_len[0]; j++) printf("%c", idr->name[j]);
+ for(j=0; j<14 -idr->name_len[0]; j++) printf(" ");
+ };
+ dump_rr(idr);
+ printf("\n");
+ i += buffer[i];
+ if (i > 2048 - sizeof(struct iso_directory_record)) break;
+ line++;
+ };
+ };
+ printf("\n");
+ printf(" Zone, zone offset: %6x %4.4x ",file_addr / blocksize,
+ file_addr & (blocksize - 1));
+ fflush(stdout);
+}
+
+getbyte()
+{
+ char c1;
+ c1 = buffer[file_addr & (blocksize-1)];
+ file_addr++;
+ if ((file_addr & (blocksize-1)) == 0) showblock(0);
+ return c1;
+}
+
+main(int argc, char * argv[]){
+ char c;
+ char buffer[2048];
+ int nbyte;
+ int i,j;
+ struct iso_primary_descriptor ipd;
+ struct iso_directory_record * idr;
+
+ if(argc < 2) return 0;
+ infile = fopen(argv[1],"rb");
+
+ file_addr = 16 << 11;
+ lseek(fileno(infile), file_addr, 0);
+ read(fileno(infile), &ipd, sizeof(ipd));
+
+ idr = (struct iso_directory_record *) &ipd.root_directory_record;
+
+ blocksize = isonum_723(ipd.logical_block_size);
+ if( blocksize != 512 && blocksize != 1024 && blocksize != 2048 )
+ {
+ blocksize = 2048;
+ }
+
+ file_addr = isonum_733(idr->extent);
+
+ file_addr = file_addr * blocksize;
+
+/* Now setup the keyboard for single character input. */
+#ifdef HAVE_TERMIOS_H
+ if(tcgetattr(0, &savetty) == -1)
+#else
+ if(ioctl(0, TCGETA, &savetty) == -1)
+#endif
+ {
+ printf("stdin must be a tty\n");
+ exit(1);
+ }
+ newtty=savetty;
+ newtty.c_lflag&=~ICANON;
+ newtty.c_lflag&=~ECHO;
+ newtty.c_cc[VMIN]=1;
+ set_tty();
+ signal(SIGTSTP, onsusp);
+
+ do{
+ if(file_addr < 0) file_addr = 0;
+ showblock(1);
+ read (0, &c, 1);
+ if (c == 'a') file_addr -= blocksize;
+ if (c == 'b') file_addr += blocksize;
+ if (c == 'g') {
+ crsr2(20,1);
+ printf("Enter new starting block (in hex):");
+ scanf("%x",&file_addr);
+ file_addr = file_addr * blocksize;
+ crsr2(20,1);
+ printf(" ");
+ };
+ if (c == 'f') {
+ crsr2(20,1);
+ printf("Enter new search string:");
+ fgets(search,sizeof(search),stdin);
+ while(search[strlen(search)-1] == '\n') search[strlen(search)-1] = 0;
+ crsr2(20,1);
+ printf(" ");
+ };
+ if (c == '+') {
+ while(1==1){
+ while(1==1){
+ c = getbyte(&file_addr);
+ if (c == search[0]) break;
+ };
+ for (j=1;j<strlen(search);j++)
+ if(search[j] != getbyte()) break;
+ if(j==strlen(search)) break;
+ };
+ file_addr &= ~(blocksize-1);
+ showblock(1);
+ };
+ if (c == 'q') break;
+ } while(1==1);
+ reset_tty();
+ fclose(infile);
+}
+
+
+
+
diff --git a/gnu/usr.sbin/mkisofs/diag/isoinfo.8 b/gnu/usr.sbin/mkisofs/diag/isoinfo.8
new file mode 100644
index 00000000000..041e5d2af42
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/diag/isoinfo.8
@@ -0,0 +1,125 @@
+.\" $OpenBSD: isoinfo.8,v 1.1 1997/09/15 06:01:53 downsj Exp $
+.\"
+.\" $From: isoinfo.8,v 1.1 1997/02/23 19:08:53 eric Rel $
+.\"
+.\" -*- nroff -*-
+.TH ISOINFO 8 "23 Feb 1997" "Version 1.10b8"
+.SH NAME
+isoinfo, isovfy, inodump \- Utility programs for dumping and verifying iso9660
+images.
+.SH SYNOPSIS
+.B isodump
+.I isoimage
+.PP
+.B isoinfo
+[
+.B \-R
+]
+[
+.B \-f
+]
+[
+.B \-l
+]
+[
+.B \-T
+]
+[
+.B \-N
+]
+[
+.B \-i
+.I isoimage
+]
+[
+.B \-x
+.I path
+]
+.PP
+.B isovfy
+.I isoimage
+.SH DESCRIPTION
+.B isodump
+is a crude utility to interactively display the contents of iso9660 images
+in order to verify directory integrity. The initial screen is a display
+of the first part of the root directory, and the prompt shows you the
+extent number and offset in the extent. You can use the 'a' and 'b'
+commands to move backwards and forwards within the image. The 'g' command
+allows you to goto an arbitrary extent, and the 'f' command specifies
+a search string to be used. The '+' command searches forward for the next
+instance of the search string, and the 'q' command exits
+.B isodump.
+.PP
+.B isoinfo
+is a utility to perform directory like listings of iso9660 images.
+.PP
+.B isovfy
+is a utility to verify the integrity of an iso9660 image. Most of the tests
+in
+.B isovfy
+were added after bugs were discovered in early versions of
+.B mkisofs.
+It isn't all that clear how useful this is anymore, but it doesn't hurt to
+have this around.
+
+.SH OPTIONS
+Only the
+.B isoinfo
+program has any command line options. These are:
+.TP
+.I -f
+generate output as if a 'find . -print' command had been run on the iso9660
+image. You should not use the
+.B -l
+image with the
+.B -f
+option.
+.TP
+.I -i iso_image
+Specifies the path of the iso9660 image that we wish to examine.
+.TP
+.I -l
+generate output as if a 'ls -lR' command had been run on the iso9660 image.
+You should not use the
+.B -f
+image with the
+.B -l
+option.
+.TP
+.I -N sector
+Quick hack to help examine single session disc files that are to be written to
+a multi-session disc. The sector number specified is the sector number at
+which the iso9660 image should be written when send to the cd-writer. Not
+used for the first session on the disc.
+.TP
+.I \-R
+Extract information from Rock Ridge extensions (if present) for permissions,
+file names and ownerships.
+.TP
+.I -T sector
+Quick hack to help examine multi-session images that have already been burned
+to a multi-session disc. The sector number specified is the sector number for
+the start of the session we wish to display.
+.TP
+.I -x pathname
+Extract specified file to stdout.
+.SH AUTHOR
+Eric Youngdale <ericy@gnu.ai.mit.edu> or <eric@andante.jic.com> is to blame
+for these shoddy hacks. Patches to improve general usability would be
+gladly accepted.
+.SH BUGS
+The user interface really sucks.
+.SH FUTURE IMPROVEMENTS
+These utilities are really quick hacks, which are very useful for debugging
+problems in mkisofs or in an iso9660 filesystem. In the long run, it would
+be nice to have a daemon that would NFS export a iso9660 image.
+.PP
+The isoinfo program is probably the program that is of the most use to
+the general user.
+.SH AVAILABILITY
+These utilities come with the mkisofs package, and the primary ftp site
+is tsx-11.mit.edu in /pub/linux/BETA/cdrom/mkisofs and many other mirror
+sites. Despite the name, the software is not beta.
+.SH SEE ALSO
+mkisofs(8)
+
diff --git a/gnu/usr.sbin/mkisofs/diag/isoinfo.c b/gnu/usr.sbin/mkisofs/diag/isoinfo.c
new file mode 100644
index 00000000000..f0bc41798d2
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/diag/isoinfo.c
@@ -0,0 +1,554 @@
+/* $OpenBSD: isoinfo.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * File isodump.c - dump iso9660 directory information.
+ *
+
+ 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[] ="$From: isoinfo.c,v 1.2 1997/03/22 02:20:28 eric Rel $";
+
+/*
+ * Simple program to dump contents of iso9660 image in more usable format.
+ *
+ * Usage:
+ * To list contents of image (with or without RR):
+ * isoinfo -l [-R] -i imagefile
+ * To extract file from image:
+ * isoinfo -i imagefile -x xtractfile > outfile
+ * To generate a "find" like list of files:
+ * isoinfo -f -i imagefile
+ */
+
+#include "../config.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/stat.h>
+
+#ifdef __svr4__
+#include <stdlib.h>
+#else
+extern int optind;
+extern char *optarg;
+/* extern int getopt (int __argc, char **__argv, char *__optstring); */
+#endif
+
+FILE * infile;
+int use_rock = 0;
+int do_listing = 0;
+int do_find = 0;
+char * xtract = 0;
+
+struct stat fstat_buf;
+char name_buf[256];
+char xname[256];
+unsigned char date_buf[9];
+unsigned int sector_offset = 0;
+
+unsigned char buffer[2048];
+
+#define PAGE sizeof(buffer)
+
+#define ISODCL(from, to) (to - from + 1)
+
+
+int
+isonum_731 (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));
+}
+
+struct iso_primary_descriptor {
+ unsigned char type [ISODCL ( 1, 1)]; /* 711 */
+ unsigned char id [ISODCL ( 2, 6)];
+ unsigned char version [ISODCL ( 7, 7)]; /* 711 */
+ unsigned char unused1 [ISODCL ( 8, 8)];
+ unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */
+ unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */
+ unsigned char unused2 [ISODCL ( 73, 80)];
+ unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
+ unsigned char unused3 [ISODCL ( 89, 120)];
+ unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */
+ unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
+ unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */
+ unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */
+ unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */
+ unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
+ unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */
+ unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
+ unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
+ unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */
+ unsigned char publisher_id [ISODCL (319, 446)]; /* achars */
+ unsigned char preparer_id [ISODCL (447, 574)]; /* achars */
+ unsigned char application_id [ISODCL (575, 702)]; /* achars */
+ unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
+ unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
+ unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
+ unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
+ unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
+ unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
+ unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
+ unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */
+ unsigned char unused4 [ISODCL (883, 883)];
+ unsigned char application_data [ISODCL (884, 1395)];
+ unsigned char unused5 [ISODCL (1396, 2048)];
+};
+
+struct iso_directory_record {
+ unsigned char length [ISODCL (1, 1)]; /* 711 */
+ unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */
+ unsigned char extent [ISODCL (3, 10)]; /* 733 */
+ unsigned char size [ISODCL (11, 18)]; /* 733 */
+ unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */
+ unsigned char flags [ISODCL (26, 26)];
+ unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */
+ unsigned char interleave [ISODCL (28, 28)]; /* 711 */
+ unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
+ unsigned char name_len [ISODCL (33, 33)]; /* 711 */
+ unsigned char name [1];
+};
+
+
+int parse_rr(unsigned char * pnt, int len, int cont_flag)
+{
+ int slen;
+ int ncount;
+ int extent;
+ int cont_extent, cont_offset, cont_size;
+ int flag1, flag2;
+ unsigned char *pnts;
+ char symlink[1024];
+ int goof;
+
+ symlink[0] = 0;
+
+ cont_extent = cont_offset = cont_size = 0;
+
+ ncount = 0;
+ flag1 = flag2 = 0;
+ while(len >= 4){
+ if(pnt[3] != 1) {
+ printf("**BAD RRVERSION");
+ return;
+ };
+ ncount++;
+ if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
+ if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1;
+ if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2;
+ if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4;
+ if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8;
+ if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16;
+ if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32;
+ if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64;
+ if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128;
+
+ if(strncmp(pnt, "PX", 2) == 0) {
+ fstat_buf.st_mode = isonum_733(pnt+4);
+ fstat_buf.st_nlink = isonum_733(pnt+12);
+ fstat_buf.st_uid = isonum_733(pnt+20);
+ fstat_buf.st_gid = isonum_733(pnt+28);
+ };
+
+ if(strncmp(pnt, "NM", 2) == 0) {
+ strncpy(name_buf, pnt+5, pnt[2] - 5);
+ name_buf[pnt[2] - 5] = 0;
+ }
+
+ if(strncmp(pnt, "CE", 2) == 0) {
+ cont_extent = isonum_733(pnt+4);
+ cont_offset = isonum_733(pnt+12);
+ cont_size = isonum_733(pnt+20);
+ };
+
+ if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) {
+ extent = isonum_733(pnt+4);
+ };
+
+ if(strncmp(pnt, "SL", 2) == 0) {
+ int cflag;
+
+ cflag = pnt[4];
+ pnts = pnt+5;
+ slen = pnt[2] - 5;
+ while(slen >= 1){
+ switch(pnts[0] & 0xfe){
+ case 0:
+ strncat(symlink, pnts+2, pnts[1]);
+ break;
+ case 2:
+ strcat (symlink, ".");
+ break;
+ case 4:
+ strcat (symlink, "..");
+ break;
+ case 8:
+ if((pnts[0] & 1) == 0)strcat (symlink, "/");
+ break;
+ case 16:
+ strcat(symlink,"/mnt");
+ printf("Warning - mount point requested");
+ break;
+ case 32:
+ strcat(symlink,"kafka");
+ printf("Warning - host_name requested");
+ break;
+ default:
+ printf("Reserved bit setting in symlink", goof++);
+ break;
+ };
+ if((pnts[0] & 0xfe) && pnts[1] != 0) {
+ printf("Incorrect length in symlink component");
+ };
+ if((pnts[0] & 1) == 0) strcat(symlink,"/");
+
+ slen -= (pnts[1] + 2);
+ pnts += (pnts[1] + 2);
+ if(xname[0] == 0) strcpy(xname, "-> ");
+ strcat(xname, symlink);
+ };
+ symlink[0] = 0;
+ };
+
+ len -= pnt[2];
+ pnt += pnt[2];
+ if(len <= 3 && cont_extent) {
+ unsigned char sector[2048];
+ lseek(fileno(infile), (cont_extent - sector_offset) << 11, 0);
+ read(fileno(infile), sector, sizeof(sector));
+ flag2 |= parse_rr(&sector[cont_offset], cont_size, 1);
+ };
+ };
+ return flag2;
+}
+
+int
+dump_rr(struct iso_directory_record * idr)
+{
+ int len;
+ unsigned char * pnt;
+
+ len = idr->length[0] & 0xff;
+ len -= sizeof(struct iso_directory_record);
+ len += sizeof(idr->name);
+ len -= idr->name_len[0];
+ pnt = (unsigned char *) idr;
+ pnt += sizeof(struct iso_directory_record);
+ pnt -= sizeof(idr->name);
+ pnt += idr->name_len[0];
+ if((idr->name_len[0] & 1) == 0){
+ pnt++;
+ len--;
+ };
+ parse_rr(pnt, len, 0);
+}
+
+struct todo
+{
+ struct todo * next;
+ char * name;
+ int extent;
+ int length;
+};
+
+struct todo * todo_idr = NULL;
+
+char * months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
+ "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+dump_stat(int extent)
+{
+ int i;
+ char outline[80];
+
+ memset(outline, ' ', sizeof(outline));
+
+ if(S_ISREG(fstat_buf.st_mode))
+ outline[0] = '-';
+ else if(S_ISDIR(fstat_buf.st_mode))
+ outline[0] = 'd';
+ else if(S_ISLNK(fstat_buf.st_mode))
+ outline[0] = 'l';
+ else if(S_ISCHR(fstat_buf.st_mode))
+ outline[0] = 'c';
+ else if(S_ISBLK(fstat_buf.st_mode))
+ outline[0] = 'b';
+ else if(S_ISFIFO(fstat_buf.st_mode))
+ outline[0] = 'f';
+ else if(S_ISSOCK(fstat_buf.st_mode))
+ outline[0] = 's';
+ else
+ outline[0] = '?';
+
+ memset(outline+1, '-', 9);
+ if( fstat_buf.st_mode & S_IRUSR )
+ outline[1] = 'r';
+ if( fstat_buf.st_mode & S_IWUSR )
+ outline[2] = 'w';
+ if( fstat_buf.st_mode & S_IXUSR )
+ outline[3] = 'x';
+
+ if( fstat_buf.st_mode & S_IRGRP )
+ outline[4] = 'r';
+ if( fstat_buf.st_mode & S_IWGRP )
+ outline[5] = 'w';
+ if( fstat_buf.st_mode & S_IXGRP )
+ outline[6] = 'x';
+
+ if( fstat_buf.st_mode & S_IROTH )
+ outline[7] = 'r';
+ if( fstat_buf.st_mode & S_IWOTH )
+ outline[8] = 'w';
+ if( fstat_buf.st_mode & S_IXOTH )
+ outline[9] = 'x';
+
+ sprintf(outline+11, "%3d", fstat_buf.st_nlink);
+ sprintf(outline+15, "%4o", fstat_buf.st_uid);
+ sprintf(outline+20, "%4o", fstat_buf.st_gid);
+ sprintf(outline+33, "%8d", fstat_buf.st_size);
+
+ if( date_buf[1] >= 1 && date_buf[1] <= 12 )
+ {
+ memcpy(outline+42, months[date_buf[1]-1], 3);
+ }
+
+ sprintf(outline+46, "%2d", date_buf[2]);
+ sprintf(outline+49, "%4d", date_buf[0]+1900);
+
+ sprintf(outline+54, "[%6d]", extent);
+
+ for(i=0; i<63; i++)
+ if(outline[i] == 0) outline[i] = ' ';
+ outline[63] = 0;
+
+ printf("%s %s %s\n", outline, name_buf, xname);
+}
+
+extract_file(struct iso_directory_record * idr)
+{
+ int extent, len, tlen;
+ unsigned char buff[2048];
+
+ extent = isonum_733(idr->extent);
+ len = isonum_733(idr->size);
+
+ while(len > 0)
+ {
+ lseek(fileno(infile), (extent - sector_offset) << 11, 0);
+ tlen = (len > sizeof(buff) ? sizeof(buff) : len);
+ read(fileno(infile), buff, tlen);
+ len -= tlen;
+ extent++;
+ write(1, buff, tlen);
+ }
+}
+
+parse_dir(char * rootname, int extent, int len){
+ unsigned int k;
+ char testname[256];
+ struct todo * td;
+ int i, j;
+ struct iso_directory_record * idr;
+
+
+ if( do_listing)
+ printf("\nDirectory listing of %s\n", rootname);
+
+ while(len > 0 )
+ {
+ lseek(fileno(infile), (extent - sector_offset) << 11, 0);
+ read(fileno(infile), buffer, sizeof(buffer));
+ len -= sizeof(buffer);
+ extent++;
+ i = 0;
+ while(1==1){
+ idr = (struct iso_directory_record *) &buffer[i];
+ if(idr->length[0] == 0) break;
+ memset(&fstat_buf, 0, sizeof(fstat_buf));
+ name_buf[0] = xname[0] = 0;
+ fstat_buf.st_size = isonum_733(idr->size);
+ if( idr->flags[0] & 2)
+ fstat_buf.st_mode |= S_IFDIR;
+ else
+ fstat_buf.st_mode |= S_IFREG;
+ if(idr->name_len[0] == 1 && idr->name[0] == 0)
+ strcpy(name_buf, ".");
+ else if(idr->name_len[0] == 1 && idr->name[0] == 1)
+ strcpy(name_buf, "..");
+ else {
+ strncpy(name_buf, idr->name, idr->name_len[0]);
+ name_buf[idr->name_len[0]] = 0;
+ };
+ memcpy(date_buf, idr->date, 9);
+ if(use_rock) dump_rr(idr);
+ if( (idr->flags[0] & 2) != 0
+ && (idr->name_len[0] != 1
+ || (idr->name[0] != 0 && idr->name[0] != 1)))
+ {
+ /*
+ * Add this directory to the todo list.
+ */
+ td = todo_idr;
+ if( td != NULL )
+ {
+ while(td->next != NULL) td = td->next;
+ td->next = (struct todo *) malloc(sizeof(*td));
+ td = td->next;
+ }
+ else
+ {
+ todo_idr = td = (struct todo *) malloc(sizeof(*td));
+ }
+ td->next = NULL;
+ td->extent = isonum_733(idr->extent);
+ td->length = isonum_733(idr->size);
+ td->name = (char *) malloc(strlen(rootname)
+ + strlen(name_buf) + 2);
+ strcpy(td->name, rootname);
+ strcat(td->name, name_buf);
+ strcat(td->name, "/");
+ }
+ else
+ {
+ strcpy(testname, rootname);
+ strcat(testname, name_buf);
+ if(xtract && strcmp(xtract, testname) == 0)
+ {
+ extract_file(idr);
+ }
+ }
+ if( do_find
+ && (idr->name_len[0] != 1
+ || (idr->name[0] != 0 && idr->name[0] != 1)))
+ {
+ strcpy(testname, rootname);
+ strcat(testname, name_buf);
+ printf("%s\n", testname);
+ }
+ if(do_listing)
+ dump_stat(isonum_733(idr->extent));
+ i += buffer[i];
+ if (i > 2048 - sizeof(struct iso_directory_record)) break;
+ }
+ }
+}
+
+usage()
+{
+ fprintf(stderr, "isoinfo -i filename [-l] [-R] [-x filename] [-f] [-N nsect]\n");
+}
+
+main(int argc, char * argv[]){
+ int c;
+ char buffer[2048];
+ int nbyte;
+ char * filename = NULL;
+ int i,j;
+ int toc_offset = 0;
+ struct todo * td;
+ struct iso_primary_descriptor ipd;
+ struct iso_directory_record * idr;
+
+ if(argc < 2) return 0;
+ while ((c = getopt(argc, argv, "i:Rlx:fN:T:")) != EOF)
+ switch (c)
+ {
+ case 'f':
+ do_find++;
+ break;
+ case 'R':
+ use_rock++;
+ break;
+ case 'l':
+ do_listing++;
+ break;
+ case 'T':
+ /*
+ * This is used if we have a complete multi-session
+ * disc that we want/need to play with.
+ * Here we specify the offset where we want to
+ * start searching for the TOC.
+ */
+ toc_offset = atol(optarg);
+ break;
+ case 'N':
+ /*
+ * Use this if we have an image of a single session
+ * and we need to list the directory contents.
+ * This is the session block number of the start
+ * of the session.
+ */
+ sector_offset = atol(optarg);
+ break;
+ case 'i':
+ filename = optarg;
+ break;
+ case 'x':
+ xtract = optarg;
+ break;
+ default:
+ usage();
+ exit(1);
+ }
+
+ if( filename == NULL )
+ {
+ fprintf(stderr, "Error - file not specified\n");
+ exit(1);
+ }
+
+ infile = fopen(filename,"rb");
+
+ if( infile == NULL )
+ {
+ fprintf(stderr,"Unable to open file %s\n", filename);
+ exit(1);
+ }
+
+ /*
+ * Absolute sector offset, so don't subtract sector_offset here.
+ */
+ lseek(fileno(infile), (16 + toc_offset) <<11, 0);
+ read(fileno(infile), &ipd, sizeof(ipd));
+
+ idr = (struct iso_directory_record *) &ipd.root_directory_record;
+
+ parse_dir("/", isonum_733(idr->extent), isonum_733(idr->size));
+ td = todo_idr;
+ while(td)
+ {
+ parse_dir(td->name, td->extent, td->length);
+ td = td->next;
+ }
+
+ fclose(infile);
+}
+
+
+
+
diff --git a/gnu/usr.sbin/mkisofs/diag/isovfy.c b/gnu/usr.sbin/mkisofs/diag/isovfy.c
new file mode 100644
index 00000000000..f10447889f3
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/diag/isovfy.c
@@ -0,0 +1,514 @@
+/* $OpenBSD: isovfy.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * File isovfy.c - verify consistency of 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[] ="$From: isovfy.c,v 1.2 1997/02/23 19:13:23 eric Rel $";
+
+#include <stdio.h>
+#include <signal.h>
+
+FILE * infile;
+int blocksize;
+
+#define PAGE sizeof(buffer)
+
+#define ISODCL(from, to) (to - from + 1)
+
+struct iso_primary_descriptor {
+ unsigned char type [ISODCL ( 1, 1)]; /* 711 */
+ unsigned char id [ISODCL ( 2, 6)];
+ unsigned char version [ISODCL ( 7, 7)]; /* 711 */
+ unsigned char unused1 [ISODCL ( 8, 8)];
+ unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */
+ unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */
+ unsigned char unused2 [ISODCL ( 73, 80)];
+ unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
+ unsigned char unused3 [ISODCL ( 89, 120)];
+ unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */
+ unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
+ unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */
+ unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */
+ unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */
+ unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
+ unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */
+ unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
+ unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
+ unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */
+ unsigned char publisher_id [ISODCL (319, 446)]; /* achars */
+ unsigned char preparer_id [ISODCL (447, 574)]; /* achars */
+ unsigned char application_id [ISODCL (575, 702)]; /* achars */
+ unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
+ unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
+ unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
+ unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
+ unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
+ unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
+ unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
+ unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */
+ unsigned char unused4 [ISODCL (883, 883)];
+ unsigned char application_data [ISODCL (884, 1395)];
+ unsigned char unused5 [ISODCL (1396, 2048)];
+};
+
+struct iso_directory_record {
+ unsigned char length [ISODCL (1, 1)]; /* 711 */
+ unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */
+ unsigned char extent [ISODCL (3, 10)]; /* 733 */
+ unsigned char size [ISODCL (11, 18)]; /* 733 */
+ unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */
+ unsigned char flags [ISODCL (26, 26)];
+ unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */
+ unsigned char interleave [ISODCL (28, 28)]; /* 711 */
+ unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
+ unsigned char name_len [ISODCL (33, 33)]; /* 711 */
+ unsigned char name [38];
+};
+
+int
+isonum_723 (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_721 (char * p)
+{
+ return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
+}
+
+int
+isonum_711 (char * p)
+{
+ return (*p & 0xff);
+}
+
+int
+isonum_731 (char * p)
+{
+ return ((p[0] & 0xff)
+ | ((p[1] & 0xff) << 8)
+ | ((p[2] & 0xff) << 16)
+ | ((p[3] & 0xff) << 24));
+}
+
+int
+isonum_722 (char * p)
+{
+ return ((p[1] & 0xff)
+ | ((p[0] & 0xff) << 8));
+}
+
+int
+isonum_732 (char * p)
+{
+ return ((p[3] & 0xff)
+ | ((p[2] & 0xff) << 8)
+ | ((p[1] & 0xff) << 16)
+ | ((p[0] & 0xff) << 24));
+}
+
+int
+isonum_733 (unsigned char * p)
+{
+ return (isonum_731 (p));
+}
+
+char lbuffer[1024];
+int iline;
+int rr_goof;
+
+
+int
+dump_rr(struct iso_directory_record * idr){
+ int len;
+ char * pnt;
+
+ len = idr->length[0] & 0xff;
+ len -= (sizeof(struct iso_directory_record) - sizeof(idr->name));
+ len -= idr->name_len[0];
+ pnt = (char *) idr;
+ pnt += (sizeof(struct iso_directory_record) - sizeof(idr->name));
+ pnt += idr->name_len[0];
+
+ if((idr->name_len[0] & 1) == 0){
+ pnt++;
+ len--;
+ };
+
+ rr_goof = 0;
+ parse_rr(pnt, len, 0);
+ return rr_goof;
+}
+
+int parse_rr(unsigned char * pnt, int len, int cont_flag)
+{
+ int slen;
+ int ncount;
+ int flag1, flag2;
+ int extent;
+ unsigned char *pnts;
+ int cont_extent, cont_offset, cont_size;
+ char symlink[1024];
+ iline += sprintf(lbuffer+iline," RRlen=%d ", len);
+
+ cont_extent = cont_offset = cont_size = 0;
+
+ symlink[0] = 0;
+
+ ncount = 0;
+ flag1 = flag2 = 0;
+ while(len >= 4){
+ if(ncount) iline += sprintf(lbuffer+iline,",");
+ else iline += sprintf(lbuffer+iline,"[");
+ iline += sprintf(lbuffer+iline,"%c%c", pnt[0], pnt[1]);
+
+ if(pnt[0] < 'A' || pnt[0] > 'Z' || pnt[1] < 'A' ||
+ pnt[1] > 'Z') {
+ iline += sprintf(lbuffer+iline,"**BAD SUSP %d %d]",
+ pnt[0], pnt[1], rr_goof++);
+ return flag2;
+ };
+
+ if(pnt[3] != 1) {
+ iline += sprintf(lbuffer+iline,"**BAD RRVERSION", rr_goof++);
+ return flag2;
+ };
+ ncount++;
+ if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
+ if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1;
+ if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2;
+ if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4;
+ if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8;
+ if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16;
+ if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32;
+ if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64;
+ if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128;
+
+ if(strncmp(pnt, "CE", 2) == 0) {
+ cont_extent = isonum_733(pnt+4);
+ cont_offset = isonum_733(pnt+12);
+ cont_size = isonum_733(pnt+20);
+ iline += sprintf(lbuffer+iline, "=[%x,%x,%d]",
+ cont_extent, cont_offset, cont_size);
+ };
+
+ if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) {
+ extent = isonum_733(pnt+4);
+ iline += sprintf(lbuffer+iline,"=%x", extent);
+ if(extent == 0) rr_goof++;
+ };
+ if(strncmp(pnt, "SL", 2) == 0) {
+ pnts = pnt+5;
+ slen = pnt[2] - 5;
+ while(slen >= 1){
+ switch(pnts[0] & 0xfe){
+ case 0:
+ strncat(symlink, pnts+2, pnts[1]);
+ break;
+ case 2:
+ strcat (symlink, ".");
+ break;
+ case 4:
+ strcat (symlink, "..");
+ break;
+ case 8:
+ strcat (symlink, "/");
+ break;
+ case 16:
+ strcat(symlink,"/mnt");
+ iline += sprintf(lbuffer+iline,"Warning - mount point requested");
+ break;
+ case 32:
+ strcat(symlink,"kafka");
+ iline += sprintf(lbuffer+iline,"Warning - host_name requested");
+ break;
+ default:
+ iline += sprintf(lbuffer+iline,"Reserved bit setting in symlink", rr_goof++);
+ break;
+ };
+ if((pnts[0] & 0xfe) && pnts[1] != 0) {
+ iline += sprintf(lbuffer+iline,"Incorrect length in symlink component");
+ };
+ if((pnts[0] & 1) == 0)
+ strcat(symlink,"/");
+ slen -= (pnts[1] + 2);
+ pnts += (pnts[1] + 2);
+
+ };
+ if(symlink[0] != 0) {
+ iline += sprintf(lbuffer+iline,"=%s", symlink);
+ symlink[0] = 0;
+ }
+ };
+
+ len -= pnt[2];
+ pnt += pnt[2];
+ if(len <= 3 && cont_extent) {
+ unsigned char sector[2048];
+ lseek(fileno(infile), cont_extent * blocksize, 0);
+ read(fileno(infile), sector, sizeof(sector));
+ flag2 |= parse_rr(&sector[cont_offset], cont_size, 1);
+ };
+ };
+ if(ncount) iline += sprintf(lbuffer+iline,"]");
+ if (!cont_flag && flag1 && flag1 != flag2)
+ iline += sprintf(lbuffer+iline,"Flag %x != %x", flag1, flag2, rr_goof++);
+ return flag2;
+}
+
+
+int dir_count = 0;
+int dir_size_count = 0;
+int ngoof = 0;
+
+
+check_tree(int file_addr, int file_size, int parent_addr){
+ unsigned char buffer[2048];
+ unsigned int k;
+ int rflag;
+ int i, i1, j, goof;
+ int extent, size;
+ int line;
+ int orig_file_addr, parent_file_addr;
+ struct iso_directory_record * idr;
+
+ i1 = 0;
+
+ orig_file_addr = file_addr / blocksize; /* Actual extent of this directory */
+ parent_file_addr = parent_addr / blocksize;
+
+ if((dir_count % 100) == 0) printf("[%d %d]\n", dir_count, dir_size_count);
+#if 0
+ printf("Starting directory %d %d %d\n", file_addr, file_size, parent_addr);
+#endif
+
+ dir_count++;
+ dir_size_count += file_size / blocksize;
+
+ if(file_size & 0x3ff) printf("********Directory has unusual size\n");
+
+ for(k=0; k < (file_size / sizeof(buffer)); k++){
+ lseek(fileno(infile), file_addr, 0);
+ read(fileno(infile), buffer, sizeof(buffer));
+ i = 0;
+ while(1==1){
+ goof = iline=0;
+ idr = (struct iso_directory_record *) &buffer[i];
+ if(idr->length[0] == 0) break;
+ iline += sprintf(&lbuffer[iline],"%3d ", idr->length[0]);
+ extent = isonum_733(idr->extent);
+ size = isonum_733(idr->size);
+ iline += sprintf(&lbuffer[iline],"%5x ", extent);
+ iline += sprintf(&lbuffer[iline],"%8d ", size);
+ iline += sprintf (&lbuffer[iline], "%c", (idr->flags[0] & 2) ? '*' : ' ');
+
+ if(idr->name_len[0] > 33)
+ iline += sprintf(&lbuffer[iline],"File name length=(%d)",
+ idr->name_len[0], goof++);
+ else if(idr->name_len[0] == 1 && idr->name[0] == 0) {
+ iline += sprintf(&lbuffer[iline],". ");
+ rflag = 0;
+ if(orig_file_addr !=isonum_733(idr->extent) + isonum_711(idr->ext_attr_length))
+ iline += sprintf(&lbuffer[iline],"***** Directory has null extent.", goof++);
+ if(i1)
+ iline += sprintf(&lbuffer[iline],"***** . not first entry.", rr_goof++);
+ } else if(idr->name_len[0] == 1 && idr->name[0] == 1) {
+ iline += sprintf(&lbuffer[iline],".. ");
+ rflag = 0;
+ if(parent_file_addr !=isonum_733(idr->extent) + isonum_711(idr->ext_attr_length))
+ iline += sprintf(&lbuffer[iline],"***** Directory has null extent.", goof++);
+ if(i1 != 1)
+ iline += sprintf(&lbuffer[iline],"***** .. not second entry.", rr_goof++);
+
+ } else {
+ if(i1 < 2) iline += sprintf(&lbuffer[iline]," Improper sorting.", rr_goof++);
+ for(j=0; j<idr->name_len[0]; j++) iline += sprintf(&lbuffer[iline],"%c", idr->name[j]);
+ for(j=0; j<14 -idr->name_len[0]; j++) iline += sprintf(&lbuffer[iline]," ");
+ rflag = 1;
+ };
+
+ if(size && extent == 0) iline += sprintf(&lbuffer[iline],"****Extent==0, size != 0", goof++);
+#if 0
+ /* This is apparently legal. */
+ if(size == 0 && extent) iline += sprintf(&lbuffer[iline],"****Extent!=0, size == 0", goof++);
+#endif
+
+ if(idr->flags[0] & 0xf5)
+ iline += sprintf(&lbuffer[iline],"Flags=(%x) ", idr->flags[0], goof++);
+
+ if(idr->interleave[0])
+ iline += sprintf(&lbuffer[iline],"Interleave=(%d) ", idr->interleave[0], goof++);
+
+ if(idr->file_unit_size[0])
+ iline += sprintf(&lbuffer[iline],"File unit size=(%d) ", idr->file_unit_size[0], goof++);
+
+ if(idr->volume_sequence_number[0] != 1)
+ iline += sprintf(&lbuffer[iline],"Volume sequence number=(%d) ", idr->volume_sequence_number[0], goof++);
+
+ goof += dump_rr(idr);
+ iline += sprintf(&lbuffer[iline],"\n");
+
+
+ if(goof){
+ ngoof++;
+ lbuffer[iline++] = 0;
+ printf("%x: %s", orig_file_addr, lbuffer);
+ };
+
+
+
+ if(rflag && (idr->flags[0] & 2)) check_tree((isonum_733(idr->extent) + isonum_711(idr->ext_attr_length)) * blocksize,
+ isonum_733(idr->size),
+ orig_file_addr * blocksize);
+ i += buffer[i];
+ i1++;
+ if (i > 2048 - sizeof(struct iso_directory_record)) break;
+ };
+ file_addr += sizeof(buffer);
+ };
+ fflush(stdout);
+}
+
+
+/* This function simply dumps the contents of the path tables. No
+ consistency checking takes place, although this would proably be a good
+ idea. */
+
+struct path_table_info{
+ char * name;
+ unsigned int extent;
+ unsigned short index;
+ unsigned short parent;
+};
+
+
+check_path_tables(int typel_extent, int typem_extent, int path_table_size){
+ int file_addr;
+ int count;
+ int j;
+ char * pnt;
+ char * typel, *typem;
+
+ /* Now read in the path tables */
+
+ typel = (char *) malloc(path_table_size);
+ lseek(fileno(infile), typel_extent * blocksize, 0);
+ read(fileno(infile), typel, path_table_size);
+
+ typem = (char *) malloc(path_table_size);
+ lseek(fileno(infile), typem_extent * blocksize, 0);
+ read(fileno(infile), typem, path_table_size);
+
+ j = path_table_size;
+ pnt = typel;
+ count = 1;
+ while(j){
+ int namelen, extent, index;
+ char name[32];
+ namelen = *pnt++; pnt++;
+ extent = isonum_731(pnt); pnt += 4;
+ index = isonum_721(pnt); pnt+= 2;
+ j -= 8+namelen;
+ memset(name, 0, sizeof(name));
+
+ strncpy(name, pnt, namelen);
+ pnt += namelen;
+ if(j & 1) { j--; pnt++;};
+ printf("%4.4d %4.4d %8.8x %s\n",count++, index, extent, name);
+ };
+
+ j = path_table_size;
+ pnt = typem;
+ count = 1;
+ while(j){
+ int namelen, extent, index;
+ char name[32];
+ namelen = *pnt++; pnt++;
+ extent = isonum_732(pnt); pnt += 4;
+ index = isonum_722(pnt); pnt+= 2;
+ j -= 8+namelen;
+ memset(name, 0, sizeof(name));
+
+ strncpy(name, pnt, namelen);
+ pnt += namelen;
+ if(j & 1) { j--; pnt++;};
+ printf("%4.4d %4.4d %8.8x %s\n", count++, index, extent, name);
+ };
+
+}
+
+main(int argc, char * argv[]){
+ int file_addr, file_size;
+ char c;
+ int nbyte;
+ struct iso_primary_descriptor ipd;
+ struct iso_directory_record * idr;
+ int typel_extent, typem_extent;
+ int path_table_size;
+ int i,j;
+ if(argc < 2) return 0;
+ infile = fopen(argv[1],"rb");
+
+
+ file_addr = 32768;
+ lseek(fileno(infile), file_addr, 0);
+ read(fileno(infile), &ipd, sizeof(ipd));
+
+ idr = (struct iso_directory_record *) &ipd.root_directory_record;
+
+ blocksize = isonum_723(ipd.logical_block_size);
+ if( blocksize != 512 && blocksize != 1024 && blocksize != 2048 )
+ {
+ blocksize = 2048;
+ }
+
+ file_addr = isonum_733(idr->extent) + isonum_711(idr->ext_attr_length);
+ file_size = isonum_733(idr->size);
+
+ printf("Root at extent %x, %d bytes\n", file_addr, file_size);
+ file_addr = file_addr * blocksize;
+
+ check_tree(file_addr, file_size, file_addr);
+
+ typel_extent = isonum_731(ipd.type_l_path_table);
+ typem_extent = isonum_732(ipd.type_m_path_table);
+ path_table_size = isonum_733(ipd.path_table_size);
+
+ /* Enable this to get the dump of the path tables */
+#if 0
+ check_path_tables(typel_extent, typem_extent, path_table_size);
+#endif
+
+ fclose(infile);
+
+ if(!ngoof) printf("No errors found\n");
+}
+
+
+
+
diff --git a/gnu/usr.sbin/mkisofs/eltorito.c b/gnu/usr.sbin/mkisofs/eltorito.c
new file mode 100644
index 00000000000..1f91eb8d1c7
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/eltorito.c
@@ -0,0 +1,262 @@
+/* $OpenBSD: eltorito.c,v 1.1 1997/09/15 06:01:52 downsj Exp $ */
+/*
+ * 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[] ="$From: eltorito.c,v 1.5 1997/03/08 17:27:01 eric Rel $";
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "mkisofs.h"
+#include "iso9660.h"
+
+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, 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/gnu/usr.sbin/mkisofs/exclude.c b/gnu/usr.sbin/mkisofs/exclude.c
new file mode 100644
index 00000000000..0ce5a79a250
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/exclude.c
@@ -0,0 +1,57 @@
+/* $OpenBSD: exclude.c,v 1.1 1997/09/15 06:01:52 downsj Exp $ */
+/*
+ * 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[] ="$From: 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/gnu/usr.sbin/mkisofs/exclude.h b/gnu/usr.sbin/mkisofs/exclude.h
new file mode 100644
index 00000000000..3488b55c7cb
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/exclude.h
@@ -0,0 +1,11 @@
+/* $OpenBSD: exclude.h,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * 9-Dec-93 R.-D. Marzusch, marzusch@odiehh.hanse.de:
+ * added 'exclude' option (-x) to specify pathnames NOT to be included in
+ * CD image.
+ *
+ * $From: exclude.h,v 1.1 1997/02/23 15:53:19 eric Rel $
+ */
+
+void exclude();
+int is_excluded();
diff --git a/gnu/usr.sbin/mkisofs/files.c b/gnu/usr.sbin/mkisofs/files.c
new file mode 100644
index 00000000000..4026ab8dcbb
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/files.c
@@ -0,0 +1,363 @@
+/* $OpenBSD: files.c,v 1.1 1997/09/15 06:01:52 downsj Exp $ */
+/*
+ * 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[] ="$From: 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/gnu/usr.sbin/mkisofs/fnmatch.c b/gnu/usr.sbin/mkisofs/fnmatch.c
new file mode 100644
index 00000000000..6e7c110e047
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/fnmatch.c
@@ -0,0 +1,227 @@
+/* $OpenBSD: fnmatch.c,v 1.1 1997/09/15 06:01:52 downsj Exp $ */
+/* 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[] ="$From: 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__)
+
+
+#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
+extern int errno;
+#endif
+
+/* 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/gnu/usr.sbin/mkisofs/fnmatch.h b/gnu/usr.sbin/mkisofs/fnmatch.h
new file mode 100644
index 00000000000..ffca8351d27
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/fnmatch.h
@@ -0,0 +1,81 @@
+/* $OpenBSD: fnmatch.h,v 1.1 1997/09/15 06:01:52 downsj Exp $ */
+/* 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. */
+
+/*
+ * $From: 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/gnu/usr.sbin/mkisofs/hash.c b/gnu/usr.sbin/mkisofs/hash.c
new file mode 100644
index 00000000000..c5051378514
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/hash.c
@@ -0,0 +1,227 @@
+/* $OpenBSD: hash.c,v 1.1 1997/09/15 06:01:52 downsj Exp $ */
+/*
+ * 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[] ="$From: 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/gnu/usr.sbin/mkisofs/iso9660.h b/gnu/usr.sbin/mkisofs/iso9660.h
new file mode 100644
index 00000000000..0f98f83fba0
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/iso9660.h
@@ -0,0 +1,158 @@
+/* $OpenBSD: iso9660.h,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * 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. */
+
+/*
+ * $From: 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/gnu/usr.sbin/mkisofs/match.c b/gnu/usr.sbin/mkisofs/match.c
new file mode 100644
index 00000000000..5a5abb109b1
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/match.c
@@ -0,0 +1,57 @@
+/* $OpenBSD: match.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * 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[] ="$From: 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/gnu/usr.sbin/mkisofs/match.h b/gnu/usr.sbin/mkisofs/match.h
new file mode 100644
index 00000000000..395d42d0144
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/match.h
@@ -0,0 +1,15 @@
+/* $OpenBSD: match.h,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * 27th March 1996. Added by Jan-Piet Mens for matching regular expressions
+ * in paths.
+ *
+ */
+
+/*
+ * $From: match.h,v 1.1 1997/02/23 15:56:12 eric Rel $
+ */
+
+#include "fnmatch.h"
+
+void add_match();
+int matches();
diff --git a/gnu/usr.sbin/mkisofs/mkisofs.8 b/gnu/usr.sbin/mkisofs/mkisofs.8
new file mode 100644
index 00000000000..a7d1a9fa20d
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/mkisofs.8
@@ -0,0 +1,428 @@
+.\" $OpenBSD: mkisofs.8,v 1.1 1997/09/15 06:01:52 downsj Exp $
+.\" $From: mkisofs.8,v 1.5 1997/04/10 02:45:50 eric Rel $
+.\" -*- nroff -*-
+.TH MKISOFS 8 "9 Apr 1997" "Version 1.11"
+.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/gnu/usr.sbin/mkisofs/mkisofs.c b/gnu/usr.sbin/mkisofs/mkisofs.c
new file mode 100644
index 00000000000..5c72ca8ceab
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/mkisofs.c
@@ -0,0 +1,661 @@
+/* $OpenBSD: mkisofs.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * 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[] ="$From: mkisofs.c,v 1.9 1997/04/10 02:45:09 eric Rel $";
+
+/* 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";
+
+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 + 0x14;
+ 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/gnu/usr.sbin/mkisofs/mkisofs.h b/gnu/usr.sbin/mkisofs/mkisofs.h
new file mode 100644
index 00000000000..983ccf57f5d
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/mkisofs.h
@@ -0,0 +1,334 @@
+/* $OpenBSD: mkisofs.h,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * 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. */
+
+/*
+ * $From: mkisofs.h,v 1.4 1997/03/08 17:29:12 eric Rel $
+ */
+
+/* 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 <sys/dir.h>
+#define dirent direct
+#else
+#include <dirent.h>
+#endif
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef linux
+#include <sys/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 **));
+
+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/gnu/usr.sbin/mkisofs/mkisofs.spec b/gnu/usr.sbin/mkisofs/mkisofs.spec
new file mode 100644
index 00000000000..3c9c8e18d5b
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/mkisofs.spec
@@ -0,0 +1,45 @@
+# $OpenBSD: mkisofs.spec,v 1.1 1997/09/15 06:01:53 downsj Exp $
+# $From: mkisofs.spec,v 1.3 1997/04/10 02:46:57 eric Rel $
+Summary: Creates a ISO9660 filesystem image
+Name: mkisofs
+Version: 1.11
+Release: 1
+Copyright: GPL
+Group: Utilities/System
+Source: tsx-11.mit.edu:/pub/linux/packages/mkisofs/mkisofs-1.11.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/gnu/usr.sbin/mkisofs/multi.c b/gnu/usr.sbin/mkisofs/multi.c
new file mode 100644
index 00000000000..e7af4bba399
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/multi.c
@@ -0,0 +1,989 @@
+/* $OpenBSD: multi.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * 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[] ="$From: multi.c,v 1.4 1997/03/08 17:08:53 eric Rel $";
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.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(mrootp->size));
+
+ readsecs(isonum_733(mrootp->extent), dirbuff,
+ isonum_733(mrootp->size)/SECTOR_SIZE);
+
+ /*
+ * Next look over the directory, and count up how many entries we
+ * have.
+ */
+ len = isonum_733(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(idr->extent);
+ (*pnt)->size = isonum_733(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)->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);
+ }
+ (*pnt)->name = strdup("<translation table>");
+ tt_extent = isonum_733(idr->extent);
+ tt_size = isonum_733(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 = strdup((char *) cpnt);
+ 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)->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).
+ */
+
+ in_image = fopen(path, "rb");
+ if( in_image == NULL )
+ {
+ return NULL;
+ }
+
+ 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(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 (pri->logical_block_size) != SECTOR_SIZE)
+ || (isonum_723 (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(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);
+
+ /*
+ * 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/gnu/usr.sbin/mkisofs/name.c b/gnu/usr.sbin/mkisofs/name.c
new file mode 100644
index 00000000000..ff02cd1f1aa
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/name.c
@@ -0,0 +1,376 @@
+/* $OpenBSD: name.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * 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[] ="$From: name.c,v 1.4 1997/04/10 02:58:26 eric Rel $";
+
+#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)
+ {
+ *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)
+ || ((chars_before_dot < 8) && ++chars_before_dot) )
+ {
+ if(result)
+ {
+ switch (*pnt)
+ {
+ default:
+ *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 ':':
+ 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/gnu/usr.sbin/mkisofs/rock.c b/gnu/usr.sbin/mkisofs/rock.c
new file mode 100644
index 00000000000..592bb79229f
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/rock.c
@@ -0,0 +1,557 @@
+/* $OpenBSD: rock.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * 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[] ="$From: rock.c,v 1.2 1997/02/23 16:08:07 eric Rel $";
+
+#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 MAJOR_IN_SYSMACROS == 0 && MAJOR_IN_MKDEV == 0
+ 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/gnu/usr.sbin/mkisofs/tree.c b/gnu/usr.sbin/mkisofs/tree.c
new file mode 100644
index 00000000000..fc0bbd12f1d
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/tree.c
@@ -0,0 +1,1275 @@
+/* $OpenBSD: tree.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * 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[] ="$From: tree.c,v 1.7 1997/03/25 03:55:28 eric Rel $";
+
+/* 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 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;
+ }
+ count = 0;
+ while(count < 0x1000)
+ {
+ sprintf(newname,"%s.%3.3X%s", rootname, count,
+ (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)) break;
+ count++;
+ }
+ if(count >= 0x1000)
+ {
+ fprintf(stderr,"Unable to generate unique name for file %s\n", s_entry->name);
+ exit(1);
+ }
+
+ /*
+ * 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, 1);
+
+ 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)
+ {
+ char buffer[1024];
+ 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;
+
+ sprintf(buffer,"%c %-34s%s",s_entry->table[0],
+ s_entry->isorec.name, s_entry->table+1);
+ memcpy(table->table + count, buffer, strlen(buffer));
+ count += strlen(buffer);
+ 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->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);
+ }
+
+ 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/gnu/usr.sbin/mkisofs/write.c b/gnu/usr.sbin/mkisofs/write.c
new file mode 100644
index 00000000000..a81dab5e0ec
--- /dev/null
+++ b/gnu/usr.sbin/mkisofs/write.c
@@ -0,0 +1,1140 @@
+/* $OpenBSD: write.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */
+/*
+ * 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[] ="$From: write.c,v 1.4 1997/04/10 03:33:25 eric Rel $";
+
+#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;
+
+/* 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(*rpnt < *lpnt) return -1;
+ if(*rpnt > *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);
+
+ 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(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);
+ free (s_entry_d->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);
+
+ /*
+ * 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);
+ if (!use_eltorito)
+ {
+ /*
+ * For some reason, Young Minds writes this twice. Aw, what the heck
+ */
+ xfwrite(&vol_desc, 1, 2048, outfile);
+ }
+ else
+ {
+ /*
+ * Next we write out the boot volume descriptor for the disc
+ */
+ get_torito_desc(&boot_desc);
+ xfwrite(&boot_desc, 1, 2048, outfile);
+ }
+
+ /*
+ * either way, we've written two more
+ */
+
+ last_extent_written += 2;
+
+ /*
+ * 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);
+ xfwrite(&vol_desc, 1, 2048, outfile);
+ last_extent_written += 2;
+
+ /*
+ * 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(... */