summaryrefslogtreecommitdiffstats
path: root/gnu
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-02-12 08:00:42 +0000
committerjkh <jkh@FreeBSD.org>1995-02-12 08:00:42 +0000
commit6a70b65aa13f5a9cfcea729d24e5448b1ad94c84 (patch)
treec89c72564efc8bd2d2e7f7cd06bd8c7f17666a2e /gnu
parent56d22b3beb7f306f834959bbb0e18d33ba47cd27 (diff)
parent2c427653c39c60269b3a6243237a5ee2deccdbfb (diff)
downloadFreeBSD-src-6a70b65aa13f5a9cfcea729d24e5448b1ad94c84.zip
FreeBSD-src-6a70b65aa13f5a9cfcea729d24e5448b1ad94c84.tar.gz
This commit was generated by cvs2svn to compensate for changes in r6318,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/mkisofs/COPYING345
-rw-r--r--gnu/usr.bin/mkisofs/ChangeLog660
-rwxr-xr-xgnu/usr.bin/mkisofs/Configure43
-rw-r--r--gnu/usr.bin/mkisofs/Makefile50
-rw-r--r--gnu/usr.bin/mkisofs/Makefile.in49
-rw-r--r--gnu/usr.bin/mkisofs/README76
-rw-r--r--gnu/usr.bin/mkisofs/TODO15
-rw-r--r--gnu/usr.bin/mkisofs/config.h1
-rw-r--r--gnu/usr.bin/mkisofs/defaults.h18
-rw-r--r--gnu/usr.bin/mkisofs/diag/Makefile10
-rw-r--r--gnu/usr.bin/mkisofs/diag/README74
-rw-r--r--gnu/usr.bin/mkisofs/diag/dump.c201
-rw-r--r--gnu/usr.bin/mkisofs/diag/isodump.c434
-rw-r--r--gnu/usr.bin/mkisofs/diag/isovfy.c487
-rw-r--r--gnu/usr.bin/mkisofs/exclude.c54
-rw-r--r--gnu/usr.bin/mkisofs/exclude.h8
-rw-r--r--gnu/usr.bin/mkisofs/hash.c177
-rw-r--r--gnu/usr.bin/mkisofs/iso9660.h107
-rw-r--r--gnu/usr.bin/mkisofs/make.com16
-rw-r--r--gnu/usr.bin/mkisofs/mkisofs.8237
-rw-r--r--gnu/usr.bin/mkisofs/mkisofs.c546
-rw-r--r--gnu/usr.bin/mkisofs/mkisofs.h243
-rw-r--r--gnu/usr.bin/mkisofs/rock.c530
-rw-r--r--gnu/usr.bin/mkisofs/tree.c889
-rw-r--r--gnu/usr.bin/mkisofs/vms.c269
-rw-r--r--gnu/usr.bin/mkisofs/vms.h19
-rw-r--r--gnu/usr.bin/mkisofs/write.c781
27 files changed, 6339 insertions, 0 deletions
diff --git a/gnu/usr.bin/mkisofs/COPYING b/gnu/usr.bin/mkisofs/COPYING
new file mode 100644
index 0000000..946cb19
--- /dev/null
+++ b/gnu/usr.bin/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.bin/mkisofs/ChangeLog b/gnu/usr.bin/mkisofs/ChangeLog
new file mode 100644
index 0000000..b31a554
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/ChangeLog
@@ -0,0 +1,660 @@
+Wed Jan 11 13:46:50 1995 Eric Youngdale (eric@localhost)
+
+ * 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.bin/mkisofs/Configure b/gnu/usr.bin/mkisofs/Configure
new file mode 100755
index 0000000..70151ad
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/Configure
@@ -0,0 +1,43 @@
+#!/bin/sh
+#
+# This script attempts to automatically configure for the host system.
+#
+MKDEV=
+MACROS=
+MALLOC=
+
+if [ -f /usr/include/sys/mkdev.h ]
+then
+MKDEV=-DHASMKDEV
+fi
+
+if [ -f /usr/include/sys/sysmacros.h ]
+then
+MACROS=-DHASSYSMACROS
+fi
+
+if [ -f /usr/include/malloc.h ]
+then
+MALLOC=-DHASMALLOC_H
+fi
+
+#
+# OK, we have all of the configuration stuff done. Now generate the Makefile.
+#
+
+echo XCFLAGS=${MKDEV} ${MACROS} ${MALLOC} > Makefrag
+
+sed -e "/XCFLAGS=/ r Makefrag" Makefile.in > Makefile
+rm -f Makefrag
+
+#
+# Now generate config.h
+#
+rm -rf config.h
+touch config.h
+if [ -f /usr/include/termios.h ]
+then
+echo "#define USE_TERMIOS" >> config.h
+fi
+
+echo "The Makefile is now properly configured for your system." \ No newline at end of file
diff --git a/gnu/usr.bin/mkisofs/Makefile b/gnu/usr.bin/mkisofs/Makefile
new file mode 100644
index 0000000..3e2ed9c
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/Makefile
@@ -0,0 +1,50 @@
+CFLAGS=-g -Wall -c
+CC=gcc
+
+#
+# XCFLAGS is automatically set by Configure.
+#
+XCFLAGS=
+XCFLAGS= -DHASSYSMACROS -DHASMALLOC_H
+CFLAGS=-g -c $(XCFLAGS)
+LDFLAGS=
+OBJS=mkisofs.o tree.o write.o hash.o rock.o exclude.o
+
+World: mkisofs
+
+Makefile: Makefile.in Configure
+ ./Configure
+ echo "Type make again to build mkisofs."
+
+mkisofs: Makefile $(OBJS)
+ $(CC) $(LDFLAGS) -o mkisofs $(OBJS)
+
+install: mkisofs mkisofs.8
+ strip mkisofs
+ cp mkisofs /usr/bin/
+ if [ -d /usr/man/man8 ]; then cp mkisofs.8 /usr/man/man8/; fi
+
+tree.o: tree.c mkisofs.h iso9660.h exclude.h
+ $(CC) $(CFLAGS) tree.c
+
+write.o: write.c mkisofs.h iso9660.h
+ $(CC) $(CFLAGS) write.c
+
+hash.o: hash.c mkisofs.h
+ $(CC) $(CFLAGS) hash.c
+
+rock.o: rock.c mkisofs.h iso9660.h
+ $(CC) $(CFLAGS) rock.c
+
+exclude.o: exclude.c exclude.h
+ $(CC) $(CFLAGS) exclude.c
+
+mkisofs.o: mkisofs.c iso9660.h mkisofs.h exclude.h
+ $(CC) $(CFLAGS) mkisofs.c
+
+clean:
+ /bin/rm -f *.o core mkisofs *~ #*#
+
+dist:
+ tar -cvf - README Configure Makefile.in make.com TODO COPYING ChangeLog *.8 *.c *.h diag | gzip > mkisofs-1.02.tar.gz
+
diff --git a/gnu/usr.bin/mkisofs/Makefile.in b/gnu/usr.bin/mkisofs/Makefile.in
new file mode 100644
index 0000000..85cf95e
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/Makefile.in
@@ -0,0 +1,49 @@
+#CFLAGS=-g -Wall -c
+#CC=gcc
+
+#
+# XCFLAGS is automatically set by Configure.
+#
+XCFLAGS=
+CFLAGS=-g -c $(XCFLAGS)
+LDFLAGS=
+OBJS=mkisofs.o tree.o write.o hash.o rock.o exclude.o
+
+World: mkisofs
+
+Makefile: Makefile.in Configure
+ ./Configure
+ echo "Type make again to build mkisofs."
+
+mkisofs: Makefile $(OBJS)
+ $(CC) $(LDFLAGS) -o mkisofs $(OBJS)
+
+install: mkisofs mkisofs.8
+ strip mkisofs
+ cp mkisofs /usr/bin/
+ if [ -d /usr/man/man8 ]; then cp mkisofs.8 /usr/man/man8/; fi
+
+tree.o: tree.c mkisofs.h iso9660.h exclude.h
+ $(CC) $(CFLAGS) tree.c
+
+write.o: write.c mkisofs.h iso9660.h
+ $(CC) $(CFLAGS) write.c
+
+hash.o: hash.c mkisofs.h
+ $(CC) $(CFLAGS) hash.c
+
+rock.o: rock.c mkisofs.h iso9660.h
+ $(CC) $(CFLAGS) rock.c
+
+exclude.o: exclude.c exclude.h
+ $(CC) $(CFLAGS) exclude.c
+
+mkisofs.o: mkisofs.c iso9660.h mkisofs.h exclude.h
+ $(CC) $(CFLAGS) mkisofs.c
+
+clean:
+ /bin/rm -f *.o core mkisofs *~ #*#
+
+dist:
+ tar -cvf - README Configure Makefile.in make.com TODO COPYING ChangeLog *.8 *.c *.h diag | gzip > mkisofs-1.02.tar.gz
+
diff --git a/gnu/usr.bin/mkisofs/README b/gnu/usr.bin/mkisofs/README
new file mode 100644
index 0000000..f71e2d7
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/README
@@ -0,0 +1,76 @@
+
+ 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.
+
+
+*****************************
+Notes for version 1.2.
+
+ 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.bin/mkisofs/TODO b/gnu/usr.bin/mkisofs/TODO
new file mode 100644
index 0000000..923f66d
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/TODO
@@ -0,0 +1,15 @@
+ 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.bin/mkisofs/config.h b/gnu/usr.bin/mkisofs/config.h
new file mode 100644
index 0000000..0e0ae33
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/config.h
@@ -0,0 +1 @@
+#define USE_TERMIOS
diff --git a/gnu/usr.bin/mkisofs/defaults.h b/gnu/usr.bin/mkisofs/defaults.h
new file mode 100644
index 0000000..7367c0a
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/defaults.h
@@ -0,0 +1,18 @@
+/*
+ * Header file defaults.h - assorted default values for character strings in
+ * the volume descriptor.
+ */
+
+#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"
+#ifdef __QNX__
+#define SYSTEM_ID_DEFAULT "QNX"
+#else
+#define SYSTEM_ID_DEFAULT "LINUX"
+#endif
diff --git a/gnu/usr.bin/mkisofs/diag/Makefile b/gnu/usr.bin/mkisofs/diag/Makefile
new file mode 100644
index 0000000..4f2a697
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/diag/Makefile
@@ -0,0 +1,10 @@
+all: dump isodump isovfy
+dump:dump.c
+ gcc -o dump dump.c
+isodump:isodump.c
+ gcc -o isodump isodump.c
+isovfy:isovfy.c
+ gcc -o isovfy isovfy.c
+
+clean:
+ rm dump isodump isovfy \ No newline at end of file
diff --git a/gnu/usr.bin/mkisofs/diag/README b/gnu/usr.bin/mkisofs/diag/README
new file mode 100644
index 0000000..59b4069
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/diag/README
@@ -0,0 +1,74 @@
+ 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.bin/mkisofs/diag/dump.c b/gnu/usr.bin/mkisofs/diag/dump.c
new file mode 100644
index 0000000..0e9db39
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/diag/dump.c
@@ -0,0 +1,201 @@
+/*
+ * 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. */
+
+#include "../config.h"
+
+#include <stdio.h>
+#ifdef USE_TERMIOS
+#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 USE_TERMIOS
+struct termios savetty;
+struct termios newtty;
+#else
+struct termio savetty;
+struct termio newtty;
+#endif
+
+reset_tty(){
+#ifdef USE_TERMIOS
+ 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 USE_TERMIOS
+ 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 */
+
+onsusp ()
+{
+ /* 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 USE_TERMIOS
+ 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.bin/mkisofs/diag/isodump.c b/gnu/usr.bin/mkisofs/diag/isodump.c
new file mode 100644
index 0000000..bca9a2f
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/diag/isodump.c
@@ -0,0 +1,434 @@
+/*
+ * 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. */
+
+#include "../config.h"
+
+#include <stdio.h>
+#ifdef USE_TERMIOS
+#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];
+
+#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 (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 [0];
+};
+
+#ifdef USE_TERMIOS
+struct termios savetty;
+struct termios newtty;
+#else
+struct termio savetty;
+struct termio newtty;
+#endif
+
+reset_tty(){
+#ifdef USE_TERMIOS
+ 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 USE_TERMIOS
+ 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 */
+
+onsusp ()
+{
+ /* 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];
+ 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) 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) printf("+");
+ 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 << 11, 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;
+ char * pnt;
+
+ len = idr->length[0] & 0xff;
+ len -= sizeof(struct iso_directory_record);
+ len -= idr->name_len[0];
+ pnt = (char *) idr;
+ pnt += sizeof(struct iso_directory_record);
+ 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 ", *((unsigned int *) idr->extent));
+ printf("%8d ", *((unsigned int *) 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>>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;
+ 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;
+
+ file_addr = isonum_733(idr->extent);
+
+ file_addr = file_addr << 11;
+
+/* Now setup the keyboard for single character input. */
+#ifdef USE_TERMIOS
+ 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.bin/mkisofs/diag/isovfy.c b/gnu/usr.bin/mkisofs/diag/isovfy.c
new file mode 100644
index 0000000..5da5314
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/diag/isovfy.c
@@ -0,0 +1,487 @@
+/*
+ * 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. */
+
+#include <stdio.h>
+#include <signal.h>
+
+FILE * infile;
+
+#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_721 (char * p)
+{
+ return ((p[0] & 0xff)
+ | ((p[1] & 0xff) << 8));
+}
+
+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 (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 << 11, 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 >> 11; /* Actual extent of this directory */
+ parent_file_addr = parent_addr >> 11;
+
+ 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 >> 11;
+
+ if(file_size & 0x3ff) printf("********Directory has unusual size\n");
+
+ for(k=0; k < (file_size >> 11); 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 || idr->name_len[0] < 0)
+ 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 !=*((unsigned int *) idr->extent))
+ 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 !=*((unsigned int *) idr->extent))
+ 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(size == 0 && extent) iline += sprintf(&lbuffer[iline],"****Extent!=0, size == 0", goof++);
+
+ if(idr->flags[0] & 0xfd)
+ iline += sprintf(&lbuffer[iline],"Flags=(%x) ", idr->flags[0], goof++);
+
+ if(idr->flags[0] & 0xfd)
+ 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((*((unsigned int *) idr->extent)) << 11,
+ *((unsigned int *) idr->size),
+ orig_file_addr << 11);
+ 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 << 11, 0);
+ read(fileno(infile), typel, path_table_size);
+
+ typem = (char *) malloc(path_table_size);
+ lseek(fileno(infile), typem_extent << 11, 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 = 16 << 11;
+ lseek(fileno(infile), file_addr, 0);
+ read(fileno(infile), &ipd, sizeof(ipd));
+
+ idr = (struct iso_directory_record *) &ipd.root_directory_record;
+
+ file_addr = isonum_733(idr->extent);
+ file_size = isonum_733(idr->size);
+
+ printf("Root at extent %x, %d bytes\n", file_addr, file_size);
+ file_addr = file_addr << 11;
+
+ 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.bin/mkisofs/exclude.c b/gnu/usr.bin/mkisofs/exclude.c
new file mode 100644
index 0000000..3be700b
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/exclude.c
@@ -0,0 +1,54 @@
+/*
+ * 9-Dec-93 R.-D. Marzusch, marzusch@odiehh.hanse.de:
+ * added 'exclude' option (-x) to specify pathnames NOT to be included in
+ * CD image.
+ */
+
+#include <stdio.h>
+#ifndef VMS
+#ifdef HASMALLOC_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] = 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.bin/mkisofs/exclude.h b/gnu/usr.bin/mkisofs/exclude.h
new file mode 100644
index 0000000..dc96c09
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/exclude.h
@@ -0,0 +1,8 @@
+/*
+ * 9-Dec-93 R.-D. Marzusch, marzusch@odiehh.hanse.de:
+ * added 'exclude' option (-x) to specify pathnames NOT to be included in
+ * CD image.
+ */
+
+void exclude();
+int is_excluded();
diff --git a/gnu/usr.bin/mkisofs/hash.c b/gnu/usr.bin/mkisofs/hash.c
new file mode 100644
index 0000000..cfa145f
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/hash.c
@@ -0,0 +1,177 @@
+/*
+ * 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. */
+
+#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,};
+
+static unsigned int FDECL1(name_hash, const char *, name){
+ unsigned int hash = 0;
+ const char * p;
+
+ p = name;
+
+ while (*p) 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;
+
+ for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
+ if(strcmp(nh->de->isorec.name, name) == 0) 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.bin/mkisofs/iso9660.h b/gnu/usr.bin/mkisofs/iso9660.h
new file mode 100644
index 0000000..2c202da
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/iso9660.h
@@ -0,0 +1,107 @@
+/*
+ * 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. */
+
+#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"
+
+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)];
+};
+
+/* 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.bin/mkisofs/make.com b/gnu/usr.bin/mkisofs/make.com
new file mode 100644
index 0000000..752ea4d
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/make.com
@@ -0,0 +1,16 @@
+$! Set the def dir to proper place for use in batch. Works for interactive too.
+$flnm = f$enviroment("PROCEDURE") ! get current procedure name
+$set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
+$!
+$!
+$if "''p1'".eqs."LINK" then goto link
+$gcc/debug mkisofs.c
+$gcc/debug write.c
+$gcc/debug tree.c
+$gcc/debug hash.c
+$gcc/debug rock.c
+$gcc/debug vms.c
+$gcc/debug exclude.c
+$link:
+$link mkisofs.obj+write.obj+tree.obj+hash.obj+rock.obj+vms.obj+exclude.obj+ -
+ gnu_cc:[000000]gcclib/lib+sys$library:vaxcrtl/lib
diff --git a/gnu/usr.bin/mkisofs/mkisofs.8 b/gnu/usr.bin/mkisofs/mkisofs.8
new file mode 100644
index 0000000..8eb29ec
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/mkisofs.8
@@ -0,0 +1,237 @@
+.\" -*- nroff -*-
+.TH MKISOFS 8 "August 1993" "Version 1.03"
+.SH NAME
+mkisofs \- create a iso9660 filesystem with optional Rock Ridge attributes.
+.SH SYNOPSIS
+.B mkisofs
+[
+.B \-R
+]
+[
+.B \-T
+]
+[
+.B \-v
+]
+[
+.B \-z
+]
+[
+.B \-a
+]
+[
+.B \-f
+]
+[
+.B \-d
+]
+[
+.B \-D
+]
+[
+.B \-l
+]
+[
+.B \-V
+]
+[
+.B \-V
+.I volid
+]
+[
+.B \-p
+.I preparer
+]
+[
+.B \-P
+.I publisher
+]
+[
+.B \-A
+.I application_id
+]
+[
+.B \-x
+.I path
+]
+.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
+.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 .mkisofsrc with APPL=id. If specified in both
+places, the command line version is used.
+.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 -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 -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
+.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
+.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 -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 .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 a file .mkisofsrc, first in the current working directory, and if not
+found there 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. Only the first four characters of the tag are used, and 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. These are the copyright information (COPY), the
+bibliographic information (BIBL), the abstract (ABST), the volume set
+ID (VOLS) and the system ID (SYSI).
+.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@cais.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 specfication 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/BETA/cdrom/mkisofs and many other mirror sites. With the 1.0
+release, it is no longer considered to be in beta testing. Most of the bugs
+that are being discovered now are very minor (and interestingly enough also
+seem to be present in the YM software). Reports indicate that people are
+gearing up for production runs using version 1.00.
diff --git a/gnu/usr.bin/mkisofs/mkisofs.c b/gnu/usr.bin/mkisofs/mkisofs.c
new file mode 100644
index 0000000..a77b815
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/mkisofs.c
@@ -0,0 +1,546 @@
+/*
+ * 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. */
+
+#include "mkisofs.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
+#include <unistd.h>
+#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.03";
+
+FILE * discimage;
+unsigned int next_extent = 0;
+unsigned int last_extent = 0;
+unsigned int path_table_size = 0;
+unsigned int path_table[4] = {0,};
+unsigned int path_blocks = 0;
+struct iso_directory_record root_record;
+static int timezone_offset;
+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_RockRidge = 0;
+int verbose = 0;
+int all_files = 0;
+int follow_links = 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;
+
+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 */
+
+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}
+};
+
+#ifdef ultrix
+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];
+ rcfile = fopen(".mkisofsrc","r");
+
+ if(!rcfile) {
+ if(strlen(appname)+sizeof(".mkisofsrc") > sizeof(linebuffer)) return;
+ strcpy(linebuffer, appname);
+ pnt = strrchr(linebuffer,'/');
+ if(!pnt) return;
+ pnt++;
+ strcpy(pnt, ".mkisofsrc");
+ rcfile = fopen(linebuffer,"r");
+ fprintf(stderr, "Using %s.\n", linebuffer);
+ } else {
+ fprintf(stderr, "Using ./.mkisofsrc.\n");
+ }
+
+ if(!rcfile) return;
+
+ /* OK, we got it. Now read in the lines and parse them */
+ while(!feof(rcfile))
+ {
+ fgets(linebuffer, sizeof(linebuffer), rcfile);
+ pnt = linebuffer;
+ while(1==1) {
+ if(*pnt == ' ' || *pnt == '\t' || *pnt == '\n' || *pnt == 0) break;
+ if(islower(*pnt)) *pnt = toupper(*pnt);
+ pnt++;
+ }
+ /* OK, now find the '=' sign */
+ while(*pnt && *pnt != '=' && *pnt != '#') pnt++;
+
+ if(*pnt == '#') continue; /* SKip comment */
+ if(*pnt != '=') continue; /* Skip to next line */
+ pnt++; /* Skip past '=' sign */
+
+ while(*pnt == ' ' || *pnt == '\t') pnt++; /* And skip past whitespace */
+
+ /* Now get rid of trailing newline */
+ pnt1 = pnt;
+ while(*pnt1) {
+ if(*pnt1 == '\n') *pnt1 = 0;
+ else
+ pnt1++;
+ };
+ pnt1 = linebuffer;
+ while(*pnt1 == ' ' || *pnt1 == '\t') pnt1++;
+ /* OK, now figure out which option we have */
+ for(rco = rcopt; rco->tag; rco++) {
+ if(strncmp(rco->tag, pnt1, 4) == 0)
+ {
+ *rco->variable = strdup(pnt);
+ break;
+ };
+ }
+ }
+ 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] [-p preparer] \
+[-P publisher] [ -A app_id ] [-z] \
+[-x path -x path ...] path\n");
+ exit(1);
+}
+
+int get_iso9660_timezone_offset(){
+ struct tm gm;
+ struct tm * pt;
+ time_t ctime;
+ int local_min, gmt_min;
+
+ time(&ctime);
+ pt = gmtime(&ctime);
+ gm = *pt;
+ pt = localtime(&ctime);
+
+ if(gm.tm_year < pt->tm_year)
+ gm.tm_yday = -1;
+
+ if(gm.tm_year > pt->tm_year)
+ pt->tm_yday = -1;
+
+ gmt_min = gm.tm_min + 60*(gm.tm_hour + 24*gm.tm_yday);
+ local_min = pt->tm_min + 60*(pt->tm_hour + 24*pt->tm_yday);
+ return (gmt_min - local_min)/15;
+}
+
+
+/* Fill in date in the iso9660 format */
+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;
+ result[6] = timezone_offset;
+ return 0;
+}
+
+int FDECL3(iso9660_file_length,const char*, name, struct directory_entry *, sresult,
+ int, dirflag){
+ int seen_dot = 0;
+ int seen_semic = 0;
+ char * result;
+ int priority = 32767;
+ int tildes = 0;
+ int ignore = 0;
+ int extra = 0;
+ int current_length = 0;
+ int chars_after_dot = 0;
+ int chars_before_dot = 0;
+ const char * pnt;
+ result = sresult->isorec.name;
+
+ if(strcmp(name,".") == 0){
+ if(result) *result = 0;
+ return 1;
+ };
+
+ if(strcmp(name,"..") == 0){
+ if(result) {
+ *result++ = 1;
+ *result++ = 0;
+ }
+ return 1;
+ };
+
+ pnt = name;
+ while(*pnt){
+#ifdef VMS
+ if(strcmp(pnt,".DIR;1") == 0) break;
+#endif
+ if(*pnt == '#') {priority = 1; pnt++; continue; };
+ if(*pnt == '~') {priority = 1; tildes++; pnt++; continue;};
+ if(*pnt == ';') {seen_semic = 1; *result++ = *pnt++; continue; };
+ if(ignore) {pnt++; continue;};
+ if(seen_semic){
+ if(*pnt >= '0' && *pnt <= '9') *result++ = *pnt;
+ extra++;
+ pnt++;
+ continue;
+ };
+ 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 */
+ if(*pnt == '.') {
+ if (seen_dot) {ignore++; continue;}
+ if(result) *result++ = '.';
+ seen_dot++;
+ } else if (seen_dot) {
+ if(chars_after_dot < 3) {
+ chars_after_dot++;
+ if(result) *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt);
+ }
+ } else {
+ if(chars_before_dot < 8) {
+ chars_before_dot++;
+ if(result) *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt);
+ };
+ };
+ };
+ current_length++;
+ pnt++;
+ };
+
+ 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 (!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;
+}
+
+int FDECL2(main, int, argc, char **, argv){
+ char * outfile;
+ struct directory_entry de;
+ unsigned int mem_start;
+ struct stat statbuf;
+ char * scan_tree;
+ int c;
+
+ if (argc < 2)
+ usage();
+
+ /* Get the defaults from the .mkisofsrc file */
+ read_rcfile(argv[0]);
+
+ outfile = NULL;
+ while ((c = getopt(argc, argv, "o:V:RfvaTp:P:x:dDlNzA:")) != EOF)
+ switch (c)
+ {
+ 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 '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 'l':
+ full_iso9660_filenames++;
+ break;
+ case 'N':
+ omit_version_number++;
+ break;
+ case 'o':
+ outfile = optarg;
+ break;
+ case 'f':
+ follow_links++;
+ break;
+ case 'R':
+ use_RockRidge++;
+ break;
+ case 'V':
+ volume_id = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'a':
+ all_files++;
+ break;
+ case 'T':
+ generate_tables++;
+ break;
+ case 'z':
+#ifdef VMS
+ fprintf(stderr,"Transparent compression not supported with VMS\n");
+ exit(1);
+#else
+ transparent_compression++;
+#endif
+ 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
+ mem_start = (unsigned int) sbrk(0);
+
+ if(verbose) fprintf(stderr,"%s\n", version_string);
+ /* Now find the timezone offset */
+
+ timezone_offset = get_iso9660_timezone_offset();
+
+ /* The first step is to scan the directory tree, and take some notes */
+
+ scan_tree = argv[optind];
+
+ 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
+ };
+
+ stat(argv[optind], &statbuf);
+ add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
+
+ de.filedir = root; /* We need this to bootstrap */
+ scan_directory_tree(argv[optind], &de);
+ 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);
+
+ 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] = 0x14;
+ path_table[1] = path_table[0] + path_blocks;
+ path_table[2] = path_table[1] + path_blocks;
+ path_table[3] = path_table[2] + path_blocks;
+
+ last_extent = path_table[3] + 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(s_entry->rr_attributes + s_entry->rr_attr_size - 24,
+ extension_record_extent);
+ set_733(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();
+
+ dump_tree(root);
+
+ iso_write(discimage);
+
+ fprintf(stderr,"Max brk space used %x\n",
+ ((unsigned int)sbrk(0)) - mem_start);
+ fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9);
+#ifdef VMS
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+void *e_malloc(size_t size)
+{
+void* pt;
+ if((pt=malloc(size))==NULL) {
+ printf("Not enougth memory\n");
+ exit (1);
+ }
+return pt;
+}
diff --git a/gnu/usr.bin/mkisofs/mkisofs.h b/gnu/usr.bin/mkisofs/mkisofs.h
new file mode 100644
index 0000000..89e9423
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/mkisofs.h
@@ -0,0 +1,243 @@
+/*
+ * 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. */
+
+#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;
+ struct directory * filedir;
+ struct directory_entry * parent_rec;
+ unsigned int 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;
+};
+
+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 void DECL(sort_n_finish,(struct directory *));
+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 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_RockRidge;
+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;
+
+extern int DECL(scan_directory_tree,(char * path, struct directory_entry * self));
+extern void DECL(dump_tree,(struct directory * node));
+extern void DECL(assign_directory_addresses,(struct directory * root));
+
+extern int DECL(iso9660_file_length,(const char* name,
+ struct directory_entry * sresult, int flag));
+extern int DECL(iso_write,(FILE * outfile));
+extern void generate_path_tables();
+extern void DECL(generate_iso9660_directories,(struct directory *, FILE*));
+extern void DECL(generate_one_directory,(struct directory *, FILE*));
+extern void generate_root_record();
+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 void finish_cl_pl_entries();
+extern int DECL(get_733,(char *));
+
+extern void DECL(set_723,(char *, unsigned int));
+extern void DECL(set_733,(char *, unsigned int));
+extern void DECL(sort_directory,(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 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 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 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
+
diff --git a/gnu/usr.bin/mkisofs/rock.c b/gnu/usr.bin/mkisofs/rock.c
new file mode 100644
index 0000000..6817a07
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/rock.c
@@ -0,0 +1,530 @@
+/*
+ * 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. */
+
+#include <stdlib.h>
+
+#ifndef VMS
+#if defined(HASSYSMACROS) && !defined(HASMKDEV)
+#include <sys/sysmacros.h>
+#endif
+#include <unistd.h>
+#endif
+#ifdef HASMKDEV
+#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 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(sizeof(dev_t) <= 4) {
+ set_733((char*)Rock + ipnt, 0);
+ ipnt += 8;
+ set_733((char*)Rock + ipnt, lstatbuf->st_rdev);
+ ipnt += 8;
+ }
+ else {
+#ifdef ultrix
+ set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 16) >> 16);
+#else
+ set_733((char*)Rock + ipnt, lstatbuf->st_rdev >> 32);
+#endif
+ ipnt += 8;
+ set_733((char*)Rock + ipnt, lstatbuf->st_rdev);
+ ipnt += 8;
+ }
+ };
+#endif
+ /*
+ * Check for and symbolic links. VMS does not have these.
+ */
+ if (S_ISLNK(lstatbuf->st_mode)){
+ int lenpos, lenval, j0, j1;
+ int cflag, nchar;
+ unsigned char * cpnt, *cpnt1;
+ nchar = readlink(whole_name, symlink_buff, sizeof(symlink_buff));
+ symlink_buff[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 = '/';
+ 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 = '/';
+ 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.bin/mkisofs/tree.c b/gnu/usr.bin/mkisofs/tree.c
new file mode 100644
index 0000000..fad1205
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/tree.c
@@ -0,0 +1,889 @@
+/*
+ * 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. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#ifndef VMS
+#include <unistd.h>
+#ifdef HASSYSMACROS
+#include <sys/sysmacros.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"
+
+#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
+#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#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(sort_n_finish, struct directory *, this_dir)
+{
+ struct directory_entry *s_entry, *s_entry1;
+ time_t current_time;
+ struct directory_entry * table;
+ int count;
+ int new_reclen;
+ char * c;
+ int tablesize = 0;
+ char newname[34], 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;
+ }
+ c = strchr(rootname, '.');
+ if (c) *c = 0;
+ count = 0;
+ while(count < 1000){
+ sprintf(newname,"%s.%3.3d%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 >= 1000){
+ 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)){
+ /* 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);
+ };
+ 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_ctime);
+ table->inode = TABLE_INODE;
+ table->dev = (dev_t) UNCACHED_DEVICE;
+ set_723(table->isorec.volume_sequence_number, 1);
+ set_733(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++;
+ if(use_RockRidge){
+ 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(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, 1);
+ 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(pnt+12);
+ set_733(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(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(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
+FDECL2(scan_directory_tree,char *, path, struct directory_entry *, de){
+ 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;
+ char * cpnt;
+ int new_reclen;
+ int deep_flag;
+
+ 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 */
+
+ if(current_dir) d_entry = readdir(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;
+ };
+ };
+
+/* 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(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;
+ }
+#if 0
+ if (verbose) fprintf(stderr, "%s\n",whole_path);
+#endif
+ status = stat(whole_path, &statbuf);
+
+ lstat(whole_path, &lstatbuf);
+
+ 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 */
+
+ else if(strcmp(d_entry->d_name, ".") &&
+ strcmp(d_entry->d_name, "..")) {
+ if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))){
+ fprintf(stderr, "Infinite loop detected (%s)\n", whole_path);
+ if(!use_RockRidge) 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));
+ };
+ };
+ };
+
+#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 %x %d).\n",
+ whole_path, statbuf.st_dev, 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;
+ this_dir->contents = s_entry;
+ deep_flag = 0;
+ s_entry->table = NULL;
+
+ s_entry->name = strdup(d_entry->d_name);
+
+ 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_ctime);
+ 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, 1);
+ 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(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;
+
+ 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;
+ scan_directory_tree(whole_path, s_entry1);
+ s_entry1->filedir = this_dir;
+
+ statbuf.st_size = 0;
+ statbuf.st_mode &= 0777;
+ set_733(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];
+ 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%d %d\n",
+ s_entry->name,
+ major(statbuf.st_rdev), 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%d %d\n",
+ s_entry->name,
+ major(statbuf.st_rdev), minor(statbuf.st_rdev));
+ break;
+ case S_IFLNK:
+ readlink(whole_path, symlink_buff, sizeof(symlink_buff));
+ sprintf(buffer,"L\t%s\t%s\n",
+ s_entry->name, symlink_buff);
+ break;
+ case S_IFSOCK:
+ sprintf(buffer,"S\t%s\n",
+ s_entry->name);
+ break;
+#endif /* NON_UNIXFS */
+ case S_IFREG:
+ default:
+ sprintf(buffer,"F\t%s\n",
+ s_entry->name);
+ break;
+ };
+ s_entry->table = strdup(buffer);
+ };
+
+ if(S_ISDIR(statbuf.st_mode)){
+ int dflag;
+ if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..")) {
+ dflag = scan_directory_tree(whole_path, s_entry);
+ /* If unable to scan directory, mark this as a non-directory */
+ if(!dflag)
+ lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
+ }
+ };
+
+ 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);
+ sort_n_finish(this_dir);
+ return 1;
+}
+
+
+void FDECL2(generate_iso9660_directories, struct directory *, node, FILE*, outfile){
+ struct directory * dpnt;
+
+ dpnt = node;
+
+ while (dpnt){
+ 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;
+ };
+}
+
diff --git a/gnu/usr.bin/mkisofs/vms.c b/gnu/usr.bin/mkisofs/vms.c
new file mode 100644
index 0000000..0c086f0
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/vms.c
@@ -0,0 +1,269 @@
+/*
+ * File vms.c - assorted bletcherous hacks for VMS.
+
+ Written by Eric Youngdale (1993).
+
+ */
+
+#ifdef VMS
+#include <rms.h>
+#include <descrip.h>
+#include <ssdef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#define opendir fake_opendir
+#include "mkisofs.h"
+#undef opendir
+#include <stdio.h>
+
+static struct RAB *rab; /* used for external mailfiles */
+static int rms_status;
+
+static error_exit(char * text){
+ fprintf(stderr,"%s\n", text);
+ exit(33);
+}
+
+
+char * strrchr(const char *, char);
+
+char * strdup(char * source){
+ char * pnt;
+ pnt = (char *) e_malloc(strlen(source) + 1);
+ strcpy(pnt, source);
+ return pnt;
+}
+
+int VMS_stat(char * path, struct stat * spnt){
+ char * spath;
+ char sbuffer[255];
+ char * pnt, *ppnt;
+ char * pnt1;
+
+ ppnt = strrchr(path,']');
+ if(ppnt) ppnt++;
+ else ppnt = path;
+
+ spath = path;
+
+ if(strcmp(ppnt,".") == 0 || strcmp(ppnt,"..") == 0){
+ strcpy(sbuffer, path);
+
+ /* Find end of actual name */
+ pnt = strrchr(sbuffer,']');
+ if(!pnt) return 0;
+
+ pnt1 = pnt;
+ while(*pnt1 != '[' && *pnt1 != '.') pnt1--;
+
+ if(*pnt1 != '[' && strcmp(ppnt,"..") == 0) {
+ pnt1--;
+ while(*pnt1 != '[' && *pnt1 != '.') pnt1--;
+ };
+
+ if(*pnt1 == '.') {
+ *pnt1 = ']';
+ pnt = pnt1;
+ while(*pnt != '.' && *pnt != ']') pnt++;
+ *pnt++ = ']';
+ while(*pnt != '.' && *pnt != ']') pnt++;
+ *pnt = 0;
+ strcat(sbuffer,".DIR;1");
+ };
+
+ if(*pnt1 == '[') {
+ pnt1++;
+ *pnt1 = 0;
+ strcat(pnt1,"000000]");
+ pnt1 = strrchr(path,'[') + 1;
+ pnt = sbuffer + strlen(sbuffer);
+ while(*pnt1 && *pnt1 != '.' && *pnt1 != ']') *pnt++ = *pnt1++;
+ *pnt = 0;
+ strcat(sbuffer,".DIR;1");
+ };
+
+ spath = sbuffer;
+ };
+ return stat(spath, spnt);
+}
+
+static int dircontext[32] = {0,};
+static char * searchpath[32];
+static struct direct d_entry[32];
+
+int optind = 0;
+char * optarg;
+
+int getopt(int argc, char *argv[], char * flags){
+ char * pnt;
+ char c;
+ optind++;
+ if(*argv[optind] != '-') return EOF;
+ optarg = 0;
+
+ c = *(argv[optind]+1);
+ pnt = (char *) strchr(flags, c);
+ if(!pnt) return c; /* Not found */
+ if(pnt[1] == ':') {
+ optind++;
+ optarg = argv[optind];
+ };
+ return c;
+}
+
+void vms_path_fixup(char * name){
+ char * pnt1;
+ pnt1 = name + strlen(name) - 6;
+
+ /* First strip the .DIR;1 */
+ if(strcmp(pnt1, ".DIR;1") == 0) *pnt1 = 0;
+
+ pnt1 = (char*) strrchr(name, ']');
+ if(pnt1) {
+ if(pnt1[1] == 0) return;
+ *pnt1 = '.';
+ strcat(name,"]");
+ return;
+ };
+ pnt1 = (char*) strrchr(name, '>');
+ if(pnt1) {
+ if(pnt1[1] == 0) return;
+ *pnt1 = '.';
+ strcat(name,">");
+ return;
+ };
+}
+
+int opendir(char * path){
+ int i;
+ for(i=1; i<32; i++) {
+ if(dircontext[i] == 0){
+ dircontext[i] = -1;
+ searchpath[i] = (char *) e_malloc(strlen(path) + 6);
+ strcpy(searchpath[i], path);
+ vms_path_fixup(searchpath[i]);
+ strcat(searchpath[i],"*.*.*");
+ return i;
+ };
+ };
+ exit(0);
+}
+
+struct direct * readdir(int context){
+ int i;
+ char cresult[100];
+ char * pnt;
+ int status;
+ $DESCRIPTOR(dpath,searchpath[context]);
+ $DESCRIPTOR(result,cresult);
+
+ if(dircontext[context] == -1) {
+ dircontext[context] = -2;
+ strcpy(d_entry[context].d_name, ".");
+ return &d_entry[context];
+ };
+
+ if(dircontext[context] == -2) {
+ dircontext[context] = -3;
+ strcpy(d_entry[context].d_name, "..");
+ return &d_entry[context];
+ };
+
+ if(dircontext[context] == -3) dircontext[context] = 0;
+
+ dpath.dsc$w_length = strlen(searchpath[context]);
+ lib$find_file(&dpath, &result, &dircontext[context],
+ 0, 0, &status, 0);
+
+ if(status == SS$_NOMOREFILES) return 0;
+
+ /* Now trim trailing spaces from the name */
+ i = result.dsc$w_length - 1;
+ while(i && cresult[i] == ' ') i--;
+ cresult[i+1] = 0;
+
+ /* Now locate the actual portion of the file we want */
+
+ pnt = (char *) strrchr(cresult,']');
+ if(pnt) pnt++;
+ else
+ pnt = cresult;
+
+ strcpy(d_entry[context].d_name, pnt);
+ return &d_entry[context];
+}
+
+void closedir(int context){
+ lib$find_file_end(&dircontext[context]);
+ free(searchpath[context]);
+ searchpath[context] = (char *) 0;
+ dircontext[context] = 0;
+}
+
+static open_file(char* fn){
+/* this routine initializes a rab and fab required to get the
+ correct definition of the external data file used by mail */
+ struct FAB * fab;
+
+ rab = (struct RAB*) e_malloc(sizeof(struct RAB));
+ fab = (struct FAB*) e_malloc(sizeof(struct FAB));
+
+ *rab = cc$rms_rab; /* initialize RAB*/
+ rab->rab$l_fab = fab;
+
+ *fab = cc$rms_fab; /* initialize FAB*/
+ fab->fab$l_fna = fn;
+ fab->fab$b_fns = strlen(fn);
+ fab->fab$w_mrs = 512;
+ fab->fab$b_fac = FAB$M_BIO | FAB$M_GET;
+ fab->fab$b_org = FAB$C_SEQ;
+ fab->fab$b_rfm = FAB$C_FIX;
+ fab->fab$l_xab = (char*) 0;
+
+ rms_status = sys$open(rab->rab$l_fab);
+ if(rms_status != RMS$_NORMAL && rms_status != RMS$_CREATED)
+ error_exit("$OPEN");
+ rms_status = sys$connect(rab);
+ if(rms_status != RMS$_NORMAL)
+ error_exit("$CONNECT");
+ return 1;
+}
+
+static close_file(struct RAB * prab){
+ rms_status = sys$close(prab->rab$l_fab);
+ free(prab->rab$l_fab);
+ free(prab);
+ if(rms_status != RMS$_NORMAL)
+ error_exit("$CLOSE");
+}
+
+#define NSECT 16
+extern unsigned int last_extent_written;
+
+int vms_write_one_file(char * filename, int size, FILE * outfile){
+ int status, i;
+ char buffer[SECTOR_SIZE * NSECT];
+ int count;
+ int use;
+ int remain;
+
+ open_file(filename);
+
+ remain = size;
+
+ while(remain > 0){
+ use = (remain > SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain);
+ use = ROUND_UP(use); /* Round up to nearest sector boundary */
+ memset(buffer, 0, use);
+ rab->rab$l_ubf = buffer;
+ rab->rab$w_usz = sizeof(buffer);
+ status = sys$read(rab);
+ fwrite(buffer, 1, use, outfile);
+ last_extent_written += use/SECTOR_SIZE;
+ if((last_extent_written % 1000) < use/SECTOR_SIZE) fprintf(stderr,"%d..", last_extent_written);
+ remain -= use;
+ };
+
+ close_file(rab);
+}
+#endif
diff --git a/gnu/usr.bin/mkisofs/vms.h b/gnu/usr.bin/mkisofs/vms.h
new file mode 100644
index 0000000..b57a677
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/vms.h
@@ -0,0 +1,19 @@
+/*
+ * Header file mkisofs.h - assorted structure definitions and typecasts.
+
+ Written by Eric Youngdale (1993).
+
+ */
+
+#ifdef VMS
+#define stat(X,Y) VMS_stat(X,Y)
+#define lstat VMS_stat
+
+/* gmtime not available under VMS - make it look like we are in Greenwich */
+#define gmtime localtime
+
+#define S_ISBLK(X) (0)
+#define S_ISCHR(X) (0)
+#define S_ISREG(X) (((X) & S_IFMT) == S_IFREG)
+#define S_ISDIR(X) (((X) & S_IFMT) == S_IFDIR)
+#endif
diff --git a/gnu/usr.bin/mkisofs/write.c b/gnu/usr.bin/mkisofs/write.c
new file mode 100644
index 0000000..05450c7
--- /dev/null
+++ b/gnu/usr.bin/mkisofs/write.c
@@ -0,0 +1,781 @@
+/*
+ * 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. */
+
+#include <string.h>
+#include <stdlib.h>
+#include "mkisofs.h"
+#include "iso9660.h"
+#include <time.h>
+#include <errno.h>
+
+#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;
+}
+
+static 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;
+
+unsigned int last_extent_written =0;
+static struct iso_primary_descriptor vol_desc;
+static path_table_index;
+
+/* 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){
+ struct directory * dpnt;
+ int dir_size;
+
+ dpnt = node;
+
+ while (dpnt){
+ dpnt->extent = last_extent;
+ dpnt->path_index = next_path_index++;
+ 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){
+ FILE * infile;
+ char buffer[SECTOR_SIZE * NSECT];
+ int use;
+ int remain;
+ if ((infile = fopen(filename, "rb")) == NULL) {
+#ifdef sun
+ 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((last_extent_written % 1000) < use/SECTOR_SIZE) fprintf(stderr,"%d..", last_extent_written);
+ remain -= use;
+ };
+ fclose(infile);
+}
+
+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);
+ };
+}
+
+#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 struct directory_entry **, r, const struct directory_entry **, l) {
+ char * rpnt, *lpnt;
+
+ rpnt = (*r)->isorec.name;
+ lpnt = (*l)->isorec.name;
+
+ 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;
+ 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 *), 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);
+ root_record.ext_attr_length[0] = 0;
+ set_733(root_record.extent, root->extent);
+ set_733(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, 1);
+ 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){
+
+ /* 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(s_entry->isorec.extent, s_hash->starting_block);
+ set_733(s_entry->isorec.size, s_hash->size);
+ continue;
+ };
+ 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(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(s_entry->isorec.size, ROUND_UP(finddir->size));
+ } else {
+ if(strcmp(s_entry->name,".") ==0 || strcmp(s_entry->name,"..") == 0) {
+ if(strcmp(s_entry->name,".") == 0) {
+ set_733(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(s_entry->isorec.size, ROUND_UP(dpnt->size));
+ } else {
+ if(dpnt == root) total_dir_size += root->size;
+ set_733(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(s_entry->isorec.size, ROUND_UP(dpnt->parent->size));
+ };
+ } else {
+ /* Now we 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;
+ } else {
+ dwpnt->table = NULL;
+ strcpy(whole_path, s_entry->filedir->whole_name);
+#ifndef VMS
+ if(strlen(whole_path)) strcat(whole_path, "/");
+#endif
+ strcat(whole_path, s_entry->name);
+ dwpnt->name = strdup(whole_path);
+ };
+ dwpnt->next = NULL;
+ dwpnt->size = s_entry->size;
+ dwpnt->extent = last_extent;
+ set_733(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 > (700000000 >> 11)) { /* More than 700Mb? 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);
+ };
+ } else
+ set_733(s_entry->isorec.extent, 0);
+ };
+ };
+ };
+ if(dpnt->subdir) assign_file_addresses(dpnt->subdir);
+ dpnt = dpnt->next;
+ };
+}
+
+void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile){
+ unsigned int total_size, ce_size;
+ char * directory_buffer;
+ char * ce_buffer;
+ unsigned int ce_address;
+ struct directory_entry * s_entry, *s_entry_d;
+ int new_reclen;
+ unsigned int dir_index, ce_index;
+
+ 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){
+ if(pnt[0] == 'C' && pnt[1] == 'E') {
+ nbytes = get_733(pnt+20);
+
+ if((ce_index & (SECTOR_SIZE - 1)) + nbytes >=
+ SECTOR_SIZE) ce_index = ROUND_UP(ce_index);
+
+ set_733(pnt+4, (ce_address + ce_index) >> 11);
+ set_733(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);
+ }
+
+}
+
+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;
+ };
+}
+
+int FDECL2(compare_paths, const struct directory **, r, const struct directory **, l) {
+ if((*r)->parent->path_index < (*l)->parent->path_index) return -1;
+ if((*r)->parent->path_index > (*l)->parent->path_index) return 1;
+ return strcmp((*r)->self->isorec.name, (*l)->self->isorec.name);
+
+}
+
+void generate_path_tables(){
+ struct directory * dpnt;
+ char * npnt, *npnt1;
+ int namelen;
+ struct directory_entry * de;
+ int fix;
+ int tablesize;
+ int i,j;
+ /* 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 *), 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;
+ if(*npnt == 0 || dpnt == root) npnt = "."; /* So the root comes out OK */
+ 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);
+}
+
+int FDECL1(iso_write, FILE *, outfile){
+ char buffer[2048];
+ char iso_time[17];
+ int should_write;
+ int i;
+
+ 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(vol_desc.system_id, system_id, strlen(system_id));
+
+ memset(vol_desc.volume_id, ' ', sizeof(vol_desc.volume_id));
+ memcpy(vol_desc.volume_id, volume_id, strlen(volume_id));
+
+ should_write = last_extent;
+ set_733(vol_desc.volume_space_size, last_extent);
+ set_723(vol_desc.volume_set_size, 1);
+ set_723(vol_desc.volume_sequence_number, 1);
+ set_723(vol_desc.logical_block_size, 2048);
+
+ /* The path tables are used by DOS based machines to cache directory
+ locations */
+
+ set_733(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(vol_desc.volume_set_id, volset_id, strlen(volset_id));
+
+ FILL_SPACE(publisher_id);
+ if(publisher) memcpy(vol_desc.publisher_id, publisher, strlen(publisher));
+
+ FILL_SPACE(preparer_id);
+ if(preparer) memcpy(vol_desc.preparer_id, preparer, strlen(preparer));
+
+ FILL_SPACE(application_id);
+ if(appid) memcpy(vol_desc.application_id, appid, strlen(appid));
+
+ FILL_SPACE(copyright_file_id);
+ if(appid) memcpy(vol_desc.copyright_file_id, appid, strlen(appid));
+
+ FILL_SPACE(abstract_file_id);
+ if(appid) memcpy(vol_desc.abstract_file_id, appid, strlen(appid));
+
+ FILL_SPACE(bibliographic_file_id);
+ if(appid) memcpy(vol_desc.bibliographic_file_id, appid, strlen(appid));
+
+ 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, 16);
+ memcpy(vol_desc.modification_date, iso_time, 16);
+ memcpy(vol_desc.expiration_date, "0000000000000000", 16);
+ memcpy(vol_desc.effective_date, iso_time, 16);
+
+ /* For some reason, Young Minds writes this twice. Aw, what the heck */
+ xfwrite(&vol_desc, 1, 2048, outfile);
+ xfwrite(&vol_desc, 1, 2048, outfile);
+ 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_l, 1, path_blocks << 11, outfile);
+ xfwrite(path_table_m, 1, path_blocks << 11, outfile);
+ xfwrite(path_table_m, 1, path_blocks << 11, outfile);
+ last_extent_written += 4*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);
+ write_files(outfile);
+
+ fprintf(stderr,"Total extents actually written = %d\n", last_extent_written);
+ /* Hard links throw us off here */
+ if(should_write != last_extent){
+ 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;
+}
OpenPOWER on IntegriCloud