From 6f50ceba0feae195ee57f4bd9cd51b1fcb9d7362 Mon Sep 17 00:00:00 2001 From: "Jordan K. Hubbard" Date: Sun, 12 Feb 1995 08:00:42 +0000 Subject: [PATCH] Original virgin sources for version 1.2 of mkisofs, by Eric Youngdale of Yggdrasil Computing Inc. This is a useful concession to us CDROM mastering weenies out here. Obtained from: Yggdrasil Computing, Inc. --- gnu/usr.bin/mkisofs/COPYING | 345 +++++++++++ gnu/usr.bin/mkisofs/ChangeLog | 660 +++++++++++++++++++++ gnu/usr.bin/mkisofs/Configure | 43 ++ gnu/usr.bin/mkisofs/Makefile | 50 ++ gnu/usr.bin/mkisofs/Makefile.in | 49 ++ gnu/usr.bin/mkisofs/README | 76 +++ gnu/usr.bin/mkisofs/TODO | 15 + gnu/usr.bin/mkisofs/config.h | 1 + gnu/usr.bin/mkisofs/defaults.h | 18 + gnu/usr.bin/mkisofs/diag/Makefile | 10 + gnu/usr.bin/mkisofs/diag/README | 74 +++ gnu/usr.bin/mkisofs/diag/dump.c | 201 +++++++ gnu/usr.bin/mkisofs/diag/isodump.c | 434 ++++++++++++++ gnu/usr.bin/mkisofs/diag/isovfy.c | 487 ++++++++++++++++ gnu/usr.bin/mkisofs/exclude.c | 54 ++ gnu/usr.bin/mkisofs/exclude.h | 8 + gnu/usr.bin/mkisofs/hash.c | 177 ++++++ gnu/usr.bin/mkisofs/iso9660.h | 107 ++++ gnu/usr.bin/mkisofs/make.com | 16 + gnu/usr.bin/mkisofs/mkisofs.8 | 237 ++++++++ gnu/usr.bin/mkisofs/mkisofs.c | 546 ++++++++++++++++++ gnu/usr.bin/mkisofs/mkisofs.h | 243 ++++++++ gnu/usr.bin/mkisofs/rock.c | 530 +++++++++++++++++ gnu/usr.bin/mkisofs/tree.c | 889 +++++++++++++++++++++++++++++ gnu/usr.bin/mkisofs/vms.c | 269 +++++++++ gnu/usr.bin/mkisofs/vms.h | 19 + gnu/usr.bin/mkisofs/write.c | 781 +++++++++++++++++++++++++ 27 files changed, 6339 insertions(+) create mode 100644 gnu/usr.bin/mkisofs/COPYING create mode 100644 gnu/usr.bin/mkisofs/ChangeLog create mode 100755 gnu/usr.bin/mkisofs/Configure create mode 100644 gnu/usr.bin/mkisofs/Makefile create mode 100644 gnu/usr.bin/mkisofs/Makefile.in create mode 100644 gnu/usr.bin/mkisofs/README create mode 100644 gnu/usr.bin/mkisofs/TODO create mode 100644 gnu/usr.bin/mkisofs/config.h create mode 100644 gnu/usr.bin/mkisofs/defaults.h create mode 100644 gnu/usr.bin/mkisofs/diag/Makefile create mode 100644 gnu/usr.bin/mkisofs/diag/README create mode 100644 gnu/usr.bin/mkisofs/diag/dump.c create mode 100644 gnu/usr.bin/mkisofs/diag/isodump.c create mode 100644 gnu/usr.bin/mkisofs/diag/isovfy.c create mode 100644 gnu/usr.bin/mkisofs/exclude.c create mode 100644 gnu/usr.bin/mkisofs/exclude.h create mode 100644 gnu/usr.bin/mkisofs/hash.c create mode 100644 gnu/usr.bin/mkisofs/iso9660.h create mode 100644 gnu/usr.bin/mkisofs/make.com create mode 100644 gnu/usr.bin/mkisofs/mkisofs.8 create mode 100644 gnu/usr.bin/mkisofs/mkisofs.c create mode 100644 gnu/usr.bin/mkisofs/mkisofs.h create mode 100644 gnu/usr.bin/mkisofs/rock.c create mode 100644 gnu/usr.bin/mkisofs/tree.c create mode 100644 gnu/usr.bin/mkisofs/vms.c create mode 100644 gnu/usr.bin/mkisofs/vms.h create mode 100644 gnu/usr.bin/mkisofs/write.c diff --git a/gnu/usr.bin/mkisofs/COPYING b/gnu/usr.bin/mkisofs/COPYING new file mode 100644 index 000000000000..946cb19c31a6 --- /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. + + + Copyright (C) 19yy + + 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. + + , 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 000000000000..b31a554e7d31 --- /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 on VMS systems. + + * tree.c: Include 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 000000000000..70151adcc017 --- /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 000000000000..3e2ed9cfd74d --- /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 000000000000..85cf95e97f54 --- /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 000000000000..f71e2d7ff7c8 --- /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 000000000000..923f66dd4432 --- /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 000000000000..0e0ae3322d99 --- /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 000000000000..7367c0a8b6bb --- /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 000000000000..4f2a697fc603 --- /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 000000000000..59b406921a72 --- /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 000000000000..0e9db391235e --- /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 +#ifdef USE_TERMIOS +#include +#include +#else +#include +#endif +#include + +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 +#ifdef USE_TERMIOS +#include +#include +#else +#include +#endif +#include + +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(§or[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; jname_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 +#include + +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(§or[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; jname_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 000000000000..3be700bf67ef --- /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 +#ifndef VMS +#ifdef HASMALLOC_H +#include +#else +#include +#endif +#endif +#include + +/* 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 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 000000000000..dc96c094b797 --- /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 000000000000..cfa145f27922 --- /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 +#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; inext; + 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 000000000000..2c202da5518c --- /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 000000000000..752ea4d52615 --- /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 000000000000..8eb29ec3a7a6 --- /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 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 000000000000..a77b81514954 --- /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 +#endif + +#include "iso9660.h" +#include + +#ifndef VMS +#include +#else +#include +#include "vms.h" +#endif + +#include +#include + +#ifndef VMS +#include +#endif + +#include "exclude.h" + +#ifdef __NetBSD__ +#include +#include +#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", ©right}, + {"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 000000000000..89e9423623f5 --- /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 + +/* 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 +#define dirent direct +#else +#include +#endif + +#include +#include +#include + +#ifdef linux +#include +#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 +#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 000000000000..6817a074ae4c --- /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 + +#ifndef VMS +#if defined(HASSYSMACROS) && !defined(HASMKDEV) +#include +#endif +#include +#endif +#ifdef HASMKDEV +#include +#include +#endif + +#include "mkisofs.h" +#include "iso9660.h" +#include + +#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 000000000000..fad1205a6abe --- /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 +#include +#include +#include + +#ifndef VMS +#include +#ifdef HASSYSMACROS +#include +#endif +#else +#include +#include +#include "vms.h" +extern char * strdup(const char *); +#endif + +#include "mkisofs.h" +#include "iso9660.h" + +#include + +#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 (¤t_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(""); + 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 (¤t_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 000000000000..0c086f0e89b6 --- /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 +#include +#include +#include +#include +#define opendir fake_opendir +#include "mkisofs.h" +#undef opendir +#include + +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 000000000000..b57a677a080c --- /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 000000000000..05450c7a4cd1 --- /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 +#include +#include "mkisofs.h" +#include "iso9660.h" +#include +#include + +#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; inext = 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; jpath_index != j){ + pathlist[j]->path_index = j; + fix++; + }; + } while(fix); + + for(j=1; jde_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; iisorec.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; +}