diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-12-31 05:04:42 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-12-31 05:04:42 +0400 |
commit | 71dc8760ff4de5f365330d1bc571d934deb54af9 (patch) | |
tree | 7346d42a282562a3937d82307012b5857d642ce6 /genisoimage | |
download | cdrkit-71dc8760ff4de5f365330d1bc571d934deb54af9.tar.gz |
Imported Upstream version 1.1.11upstream/1.1.11upstream
Diffstat (limited to 'genisoimage')
95 files changed, 46375 insertions, 0 deletions
diff --git a/genisoimage/CMakeLists.txt b/genisoimage/CMakeLists.txt new file mode 100644 index 0000000..303ba4d --- /dev/null +++ b/genisoimage/CMakeLists.txt @@ -0,0 +1,70 @@ +PROJECT (MKISOFS C) + +INCLUDE(../include/AddScgBits.cmake) +INCLUDE(../include/AddSchilyBits.cmake) + +INCLUDE_DIRECTORIES(../include ../libhfs_iso ../wodim ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/include) + +INCLUDE(CheckIncludeFiles) +CHECK_INCLUDE_FILES("magic.h" USE_MAGIC) +IF(USE_MAGIC) + ADD_DEFINITIONS(-DUSE_MAGIC) + SET(MAGICLIBS magic) +ENDIF(USE_MAGIC) + +CHECK_INCLUDE_FILES("pthread.h" USE_PTHREAD) +IF(USE_PTHREAD) + ADD_DEFINITIONS(-DTHREADED_CHECKSUMS) + LIST(APPEND EXTRA_LIBS "pthread") +ENDIF(USE_PTHREAD) + + IF(HAVE_ICONV_H) + ADD_DEFINITIONS(-DUSE_ICONV) + #INCLUDE(CheckLibraryExists) +# CHECK_LIBRARY_EXISTS (iconv "iconv_open(argv[0],argv[0])" "" USE_LIBICONV) +IF(USE_LIBICONV) + LIST(APPEND EXTRA_LIBS "iconv") +ELSE(USE_LIBICONV) +# MESSAGE("No additional libiconv found, maybe not required. If required, change linker flags, see TROUBLESHOOTING in the INSTALL file") +ENDIF(USE_LIBICONV) +ENDIF(HAVE_ICONV_H) + +ADD_DEFINITIONS(-DUSE_LARGEFILES -DABORT_DEEP_ISO_ONLY -DAPPLE_HYB -DUDF -DDVD_VIDEO -DSORTING -DHAVE_CONFIG_H -DUSE_LIBSCHILY -DUSE_SCG -DJIGDO_TEMPLATE) + +SET(MKISOFS_MOST_SRCS apple.c boot.c desktop.c dvd_file.c dvd_reader.c eltorito.c exclude.c files.c fnmatch.c hash.c ifo_read.c joliet.c mac_label.c match.c multi.c name.c rock.c scsi.c stream.c tree.c udf.c vms.c volume.c write.c boot-alpha.c boot-hppa.c boot-mips.c md5.c jte.c rsync.c boot-mipsel.c endian.c sha1.c sha256.c sha512.c checksum.c ) + +INCLUDE(CheckFunctionExists) +SET(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) +CHECK_FUNCTION_EXISTS("getopt_long" HAVE_GETOPT_LONG) +IF(NOT HAVE_GETOPT_LONG) + LIST ( APPEND MKISOFS_MOST_SRCS getopt.c getopt1.c ) +ENDIF(NOT HAVE_GETOPT_LONG) + + +#SET_SOURCE_FILES_PROPERTIES(${MKISOFS_MOST_SRCS} PROPERTIES ) +LINK_DIRECTORIES(../libhfs_iso ../librols ../libusal ../libunls ../wodim) + +ADD_EXECUTABLE (genisoimage genisoimage.c ${MKISOFS_MOST_SRCS}) +TARGET_LINK_LIBRARIES(genisoimage wodimstuff hfs_iso ${MAGICLIBS} c unls z bz2 ${EXTRA_LIBICONV} ${EXTRA_LIBS}) + +# common lib set and genisoimage source parts for the rest +LINK_LIBRARIES(wodimstuff ${EXTRA_LIBS} unls ${EXTRA_LIBICONV} ) +ADD_EXECUTABLE(devdump diag/dump.c scsi.c) +ADD_EXECUTABLE(isodebug diag/isodebug.c scsi.c) +ADD_EXECUTABLE(isodump diag/isodump.c scsi.c) +ADD_EXECUTABLE(isoinfo diag/isoinfo.c scsi.c) +ADD_EXECUTABLE(isovfy diag/isovfy.c scsi.c) + + +SET_TARGET_PROPERTIES(genisoimage devdump isodebug isodump isoinfo isovfy PROPERTIES SKIP_BUILD_RPATH TRUE) + +INSTALL(TARGETS genisoimage devdump isodebug isodump isoinfo isovfy DESTINATION bin) +INSTALL(FILES +genisoimage.1 +diag/devdump.1 +diag/isodebug.1 +diag/isodump.1 +diag/isoinfo.1 +diag/isovfy.1 +DESTINATION ${MANSUBDIR}/man1) +INSTALL(FILES genisoimagerc.5 DESTINATION "${MANSUBDIR}/man5") diff --git a/genisoimage/COPYING b/genisoimage/COPYING new file mode 100644 index 0000000..946cb19 --- /dev/null +++ b/genisoimage/COPYING @@ -0,0 +1,345 @@ + The GPL below is copyrighted by the Free Software + Foundation, but the instance of code that it refers to (the mkisofs + utility is copyrighted by Yggdrasil Computing, Incorporated). + +---------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/genisoimage/ChangeLog b/genisoimage/ChangeLog new file mode 100644 index 0000000..681a6ce --- /dev/null +++ b/genisoimage/ChangeLog @@ -0,0 +1,3866 @@ +****** Version 2.01 ****** + +Wed Sep 8 20:28:58 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.47 + * isovfy.c 1.23 + * dump.c 1.21 + * isodebug.c 1.9 + * isodump.c 1.24 + * mkisofs.c 1.161 + Version -> 2.01 + +Thu Sep 2 13:05:11 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.108 + -D Hinweis auf ISO9660:1999 + +Mon Aug 30 12:24:17 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.107 + ISO-9690 -> ISO-9660 + +Tue Aug 24 19:21:54 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.85 + Intermediate Cast auf (void *) damit GCC nicht wegen "strict-aliasing rules" meckert + +Tue Aug 3 21:21:54 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.106 + Hinweis auf Bugfix fuer -no-split-symlink-components / -no-split-symlink-fields + +Sat Jul 31 17:11:30 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.105 + Schreibfehler beseitigt + +Sat Jul 17 23:42:14 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.104 + * mkisofs.c 1.160 + Version -> 2.01a34 + -volset-size ist nun auf 1 begrenzt + +Sun Jul 11 18:30:27 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.159 + Fehlermeldung bei -L/-H/-P weis nun korrekt auf 2.02 hin + +Sun Jul 11 02:03:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.158 + -> NEED_O_BINARY + +Fri Jul 9 17:34:41 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.157 + Version -> 2.01a33 + +Fri Jul 9 16:06:36 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * volume.c 1.14 + * write.c 1.84 + static -> LOCAL + EXPORT + +Fri Jul 9 15:32:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.83 + 'VIDEO_TS' wird jetzt immer gefunden und mkisofs bricht ab wenn es nicht gefunden werden konnte und -dvd-video + +Fri Jun 18 11:17:08 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * hash.c 1.18 + Nachdenken ueber Speedup + +Thu Jun 17 12:25:43 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.156 + Version -> 2.01a32 + +Thu Jun 17 11:22:11 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * dump.c 1.20 + * isodump.c 1.23 + For Schleife ohne strlen() in Ende Bedingung + +Sat Jun 12 16:15:16 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.82 + sprintf() zur besseren Geschwindigkeit beim Erzeugen von 8.3 Filenamen in sort_n_finish() vermeiden + +Mon Jun 7 13:02:01 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.103 + Dokumentation der maximalen Stringlaenge der Eintraege im PVD nun auch bei den Optionen + +Sat Jun 5 16:48:02 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.102 + * mkisofs.c 1.155 + Optionen -H/-L/-P sind veraltet und werden mit 2.02 POSIX.1-2001 konform + +Tue Jun 1 18:27:04 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.154 + Version -> 2.01a31 + +Tue Jun 1 16:53:24 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.81 + Bei DJGPP auch alle Files eXecutable machen. + +Tue Jun 1 16:52:47 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.153 + load_nls("cp437") per Default auch fuer DJGPP + +Tue Jun 1 16:51:47 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * defaults.h 1.18 + SYSTEM_ID -> DOS fuer DJGPP + +Tue Jun 1 16:50:58 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.46 + setmode(fileno(stdout), O_BINARY) beim Extrahieren von Dateien nach STDOUT + +Tue Jun 1 14:07:06 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isodebug.c 1.8 + Funktionen moeglichst LOCAL + +Tue Jun 1 13:50:50 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * dump.mk 1.4 + * dump.c 1.19 + * isoinfo.8 1.7 + * isodump.c 1.22 + * isoinfo.mk 1.5 + * isodump.mk 1.4 + * isovfy.mk 1.4 + * isovfy.c 1.22 + * isodebug.mk 1.2 + * isodebug.c 1.7 + Umstellung auf libusal + +Sat May 29 17:46:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.45 + cdr_defaults() nur mit libusal rufen + +Sat May 29 16:55:08 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isodebug.c 1.6 + Version -> 2.01a31 + Cstyle + +Fri May 28 13:51:13 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.44 + Support fuer cdr_defaults() (/etc/default/cdrecord) neu + +Fri May 28 13:39:35 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.43 + Cstyle + +Fri May 28 13:37:39 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.42 + Version -> 2.01a31 + Umbau auf libusal + +Fri May 28 13:36:25 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isodump.c 1.21 + * isovfy.c 1.21 + Version -> 2.01a31 + Cstyle + +Fri May 28 01:09:55 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * dump.c 1.18 + Version -> 2.01a31 + Cstyle + +Thu May 27 01:54:59 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.94 + scsi.c Prototypen -> scsi.h + +Thu May 27 01:54:31 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.h 1.1 + date and time created 04/05/27 00:54:31 by joerg + +Sun May 23 23:46:05 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.32 + Debug Messages beseitigt + +Sun May 23 23:23:27 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.101 + * tree.c 1.80 + * eltorito.c 1.31 + * match.h 1.9 + * mkisofs.c 1.152 + * match.c 1.18 + Version -> 2.01a30 + Eltorito Boot Images per Default nach Vorne Sortieren + +Thu May 20 13:38:31 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.30 + Copyright J. Schilling neu + +Thu May 20 13:33:59 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.29 + Keine Ausgabe der Bootmethode bei mkisofs -quiet + +Sat May 15 22:25:17 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.151 + Version -> 2.01a29 + Hinweis auf unerwuenschte SILO Optionen + +Sat May 15 21:48:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.82 + Neuer Kommentar damit SuSE keine sinnlosen Patches anbringt + +Sat May 15 21:05:49 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.41 + Version -> 2.01a29 + +Sat May 15 19:59:40 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.66 + * mkisofs.c 1.150 + * isoinfo.c 1.40 + GCC shadowed Variblen beseitigt + +Thu Apr 15 16:33:41 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.149 + Version -> 2.01a28 + +Thu Apr 15 16:30:40 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * hash.c 1.17 + isoname_endsok() neu zum besseren Vergleich von ISO-9660 namen + +Thu Apr 15 14:51:22 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * hash.c 1.16 + * udf.c 1.14 + Cstyle + +Wed Apr 14 12:55:56 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.81 + Schreibfehler beseitigt (Initial Padbock) + +Tue Apr 6 12:30:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.79 + Fix fuer doppeltes Free von Juergen Keil + Absturz durch: + echo bar >/tmp/bar + echo foo/bar=/tmp/bar > /tmp/pathlist + env LD_PRELOAD=libumem.so.1 UMEM_DEBUG=default UMEM_LOGGING=transaction mkisofs -hfs -graft-points -o /tmp/foo.raw -path-list=/tmp/pathlist + +Tue Apr 6 11:57:30 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.78 + beruecksichtigung des Null Bytes beim malloc() fuer die Datei TRANS_TBL + +Sun Apr 4 20:24:38 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.65 + Bessere Fehlermeldung bei multi Session mit volset size > 1 + +Mon Mar 15 15:43:58 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * defaults.h 1.17 + "SCO-OPENSERVER"/"SCO-UNIXWARE", Default ist nun "UNIX" statt "LINUX" + +Fri Mar 5 00:22:28 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.148 + Version -> 2.01a27 + +Fri Mar 5 00:12:50 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mac_label.c 1.9 + * match.c 1.17 + * name.c 1.28 + * scsi.c 1.19 + * stream.c 1.3 + * files.c 1.12 + * exclude.c 1.9 + * dvd_reader.c 1.3 + * eltorito.c 1.28 + * ifo_read.c 1.5 + * dvd_file.c 1.3 + * desktop.c 1.6 + * apple_driver.c 1.6 + * vms.c 1.9 + * volume.c 1.13 + Cstyle + +Thu Mar 4 22:47:39 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.64 + * mkisofs.h 1.93 + * mkisofs.c 1.147 + * mkisofs.8 1.100 + Neue Optionen -root & -old-root von Patrik Ohly + +Thu Mar 4 22:40:24 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mac_label.c 1.8 + Korrektur fuer PREP/CHRP Erweiterung + +Tue Mar 2 00:54:16 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * fnmatch.h 1.4 + * exclude.h 1.3 + * diskmbr.h 1.2 + * defaults.h 1.16 + * bootinfo.h 1.3 + * apple.h 1.7 + * apple.c 1.19 + * ifo_read.h 1.2 + * ifo_types.h 1.2 + * iso9660.h 1.19 + * mac_label.h 1.3 + * mactypes.h 1.3 + * match.h 1.8 + Cstyle + +Tue Mar 2 00:50:27 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * dvd_reader.h 1.2 + Cstyle + +Mon Mar 1 12:05:40 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * vms.h 1.3 + * udf.h 1.2 + * udf_fs.h 1.2 + Cstyle + +Sun Feb 29 17:53:16 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.39 + Eltorito Boot mit -d anzeigen + Extension Records fuer lange RR Namen korrekt anzeigen + +Sun Feb 29 17:20:47 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mac_label.h 1.2 + * write.c 1.80 + * mkisofs.c 1.146 + * mkisofs.h 1.92 + * mac_label.c 1.7 + CHRP Support von "Leigh Brown" <leigh@solinno.co.uk> + +Sun Feb 29 16:49:18 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.42 + * multi.c 1.63 + }; in Funktionen -> } + +Sun Feb 29 16:43:37 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.62 + Korrekte Behandlung von CE Extension Records fuer RR NM & fue rTime Stamps + +Wed Feb 25 00:16:47 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * udf.c 1.13 + Support fuer rationalize_uid/rationalize_gid + +Sun Feb 22 16:27:28 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.145 + Version -> 2.01a26 + Mb -> MB + +Sun Feb 22 16:26:26 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.41 + gen_xa_attr(mode_t attr) ANSI C Variante wegen aelteren UNIX Versionen mit mode_t == short + +Sun Feb 22 16:25:09 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * boot.c 1.13 + Total extents including sparc boot -> Total extents including %s boot + +Sun Feb 22 16:13:43 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.18 + cdr_defaults() wird nun fuer das SCSI dev= gerufen (/etc/default/cdrecord) + +Wed Jan 7 00:23:46 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.144 + Copyright -> 2004 + +Tue Jan 6 23:53:42 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.143 + Version -> 2.01a24 + +Tue Jan 6 22:37:55 2004 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.77 + Rock Ridge Laengenbehandlung in update_nlink()/increment_nlink() korrigiert (Bugfix) + +Mon Dec 29 14:46:02 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.142 + * boot.c 1.12 + Cstyle Anpassungen + +Mon Dec 29 14:36:10 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * boot.c 1.11 + Neue Optionen -sunx86-boot & -sunx86-label + +Mon Dec 29 14:35:05 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.141 + Version -> 2.01a22 + Neue Optionen -sunx86-boot & -sunx86-label + +Mon Dec 29 14:34:16 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.99 + Neue Optionen -sunx86-boot & -sunx86-label + -sparc-label war vergessen - nun dokumentiert + +Mon Dec 29 13:31:28 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.98 + Kommentar zu SILO in den NOTES + Fehlende backslashes for diversen - Zeichen eingefuegt + +Sun Dec 28 14:46:10 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * sunlabel.h 1.5 + Cstyle Aenderungen + +Sun Dec 28 14:44:50 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * sunlabel.h 1.4 + Erweiterungen fuer Solaris x86 Disk Label und fdisk + +Sun Dec 28 14:38:51 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.91 + Cstyle Anpassungen + +Sun Dec 28 14:37:09 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.90 + make_sunx86_label()/scan_sunx86_boot()/sunx86_boot_label() neu + +Sat Nov 29 23:58:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.140 + #include <io.h> fuer setmode(fileno, OBINARY) + #include <io.h> auch fuer DJGPP + +Sat Nov 29 23:11:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.139 + Version -> 2.01a20 + setmode(fileno, O_BINARY) auch fuer DJGPP + +Sun Jul 13 15:42:15 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.79 + * mkisofs.h 1.89 + * mkisofs.c 1.138 + secsize -> osecsize, Version -> 2.01a17 + +Fri Jul 11 11:42:32 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.97 + Schreibfehler + +Thu Jul 10 01:26:47 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.76 + Bessere Meldung bei Stat Buffer Overflow + +Sat Jun 21 14:28:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.137 + Eltorito PVD muss vor direkt nach dem Primaeren PVD kommen -> also vor Enhanced PVD + +Sat Jun 21 14:16:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * match.c 1.16 + Wenn ein TAB nach einem Space im Sort File kommt, dann wird dieses genommen + +Sat Jun 21 14:11:05 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.96 + Schreibfehler und Formulierungen korrigiert + +Sat Jun 21 14:10:13 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.27 + Schreibfehler bei 'is not the an allowable size' beseitigt + +Tue May 6 19:04:03 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.40 + Fix fuer defekte CE Signaturen bei ../../../ in Symlinks + +Wed Apr 30 01:19:33 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.136 + no_rr nur dann automatisch setzen wenn keine XA Signaturen gefunden wurden + +Wed Apr 30 01:18:10 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.61 + find_rr() nun mit XA Flag + +Wed Apr 30 01:15:59 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.88 + Rock Ridge Defines neu + +Tue Apr 29 21:22:52 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.78 + Variable secsize neu, struct xa_subhdr neu + +Tue Apr 29 21:20:40 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.87 + Neue Variable secsize + +Tue Apr 29 21:19:13 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.135 + Neue Option -sectype + +Tue Apr 29 01:39:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.134 + -apple bedeutet nicht mehr -r + +Tue Apr 29 01:17:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.75 + insert_file_entry() erzeugt auch XA oder RockRidge Signaturen fuer rsrc Files + +Tue Apr 29 01:06:32 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.77 + Umbau von xfwrite() fuer XA subheader + +Mon Apr 28 01:44:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.95 + Hinwies, dasz -apple nicht mehr -R beinhaltet + +Mon Apr 28 01:36:07 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.37 + * eltorito.c 1.26 + * boot.c 1.10 + * stream.c 1.2 + * udf.c 1.12 + * mkisofs.h 1.86 + Umbau von xfwrite() fuer XA subheader + +Mon Apr 28 01:06:38 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * iso9660.h 1.18 + XA Sektor Subheader Definitionen neu + +Sun Apr 27 15:46:18 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.74 + * eltorito.c 1.25 + generate_rock_ridge_attributes() -> generate_xa_rr_attributes(), if (use_RockRidge) -> if (use_XA || use_RockRidge) + +Sun Apr 27 15:38:59 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.39 + generate_rock_ridge_attributes() -> generate_xa_rr_attributes(), if (!use_RockRidge) goto xa_only; + +Sun Apr 27 15:36:45 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.85 + generate_rock_ridge_attributes() -> generate_xa_rr_attributes() + +Sun Apr 27 15:35:49 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.133 + Version -> 2.01a12 + +Sun Apr 27 14:09:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * TODO 1.6 + 13.4.2003 HFS > 2 GB + +Tue Apr 15 18:47:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.76 + CD-XA001 Signatur hinzufuegen + +Sun Apr 13 19:05:06 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.38 + Version -> 2.01a10 + st_size ist unsigned bei ISO-9660, map auf Llong + +Sun Apr 13 01:36:22 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.75 + * tree.c 1.73 + * mkisofs.h 1.84 + Erster Versuch Files bis zu 4 GB zu unterstuetzen + +Sun Apr 13 01:32:15 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * vms.h 1.2 + * vms.c 1.8 + vms_write_one_file() mit off_t size + +Fri Apr 11 19:19:24 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.38 + gen_xa()/gen_xa_attr() neu + +Thu Apr 10 15:38:04 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * iso9660.h 1.17 + Kommentar fuer XA Flags korrigiert + +Thu Apr 10 15:37:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.132 + Version -> 2.01a10, Optionen -XA/-xa neu, Schreibfehler bei -iso-level beseitigt + +Thu Apr 10 15:36:03 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.83 + use_XA neu + +Thu Apr 10 15:34:30 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.74 + Skip XA Record neu + +Sat Apr 5 13:39:51 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.37 + Usage Schreibfehler beseitigt + +Fri Apr 4 23:42:02 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.27 + conv_charset() bei -iso-level 4 fuer 8 Bit Zeichen + +Fri Apr 4 23:41:05 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.37 + statis -> LOCAL, unsigned char -> Uchar + +Fri Apr 4 23:40:06 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * ifo_read.c 1.4 + Umbau um ANSI C Warnungen zu vermeiden + +Sat Mar 29 13:01:43 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * udf.c 1.11 + Hinweis auf VIDEO_TS in joliet.c + +Sat Mar 29 12:59:14 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.36 + * write.c 1.73 + #ifdef __STDC__ -> PROTOTYPES, Eingerueckt nach cstyle + +Sat Mar 29 12:43:35 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.60 + * rock.c 1.36 + #ifdef __STDC__ -> PROTOTYPES + +Thu Mar 27 00:19:50 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.35 + Anpassungen fuer cstyle + +Thu Mar 27 00:05:17 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.34 + Bessere Debug Ausgaben fuer add_CE_entry & Bug Fix fuer Split Symplinks (2 Byte Offsetfehler) + +Tue Mar 25 21:31:29 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * bswap.h 1.2 + * mkisofs.h 1.82 + Eingerueckt nach cstyle + +Tue Mar 25 20:51:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.59 + Eingerückt nach cstyle + +Tue Mar 25 20:48:56 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.131 + Version -> 2.01a07, Eingerueckt nach cstyle + +Sun Mar 9 13:38:18 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * getopt.c 1.6 + FSF Junk Code (#define _NO_PROTO) beseitigt der #include strings.h verhinderte; stattdessen #define getopt __nothing_ + +Thu Mar 6 22:11:16 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * getopt.h 1.3 + * fnmatch.h 1.3 + mconfig.h statt (internem) protoyp.h + +Thu Mar 6 22:03:51 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * getopt.h 1.2 + * fnmatch.h 1.2 + Umbau auf prototyp.h & PROTOTYPES statt __STDC__ damit Prototypen korrekt auch bei SCO Unixware gehen + +Thu Mar 6 22:01:40 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * dvd_reader.c 1.2 + DVDOpenFile() mit Prototype implementierung wegen SCO cc (enum) + +Sun Mar 2 17:33:16 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.72 + strdup() -> libport + +Sat Mar 1 21:19:56 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * match.c 1.15 + #include match.h nach #include libport.h wegen MAX define in param.h bei Linux + +Sat Mar 1 19:25:08 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * match.c 1.14 + #includ <libport.h> fuer strdup() + +Sat Mar 1 18:56:35 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.58 + *nent -> *nentp & nent + +Sat Mar 1 18:41:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.57 + pnt->assoc schon direkt nach dem Einlesen der direcory zuweisen damit es zuverlaessig funktioniert + +Sat Mar 1 13:00:37 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.36 + Ausgabe der ISO-9660 directory flags + +Sat Mar 1 12:54:45 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * iso9660.h 1.16 + Definitionen fuer XA attributes neu + +Fri Feb 28 01:32:10 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.72 + * vms.c 1.7 + * mkisofs.c 1.130 + * mkisofs.h 1.81 + strdup() -> libport.h + +Fri Feb 28 01:23:34 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isodump.c 1.20 + * dump.c 1.17 + Umbau auf ttydefs.h und Portabilitaet fuer alte UNIX Versionen ohne termio* + +Sun Feb 23 19:34:23 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.71 + LOCAL statt static & Umbau wegen cstyle + +Sun Feb 23 14:25:55 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.56 + * mkisofs.h 1.80 + Einige Funktionen in multi.c -> LOCAL, Eingerueckt nach cstyle + +Sat Feb 22 21:57:34 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.35 + sort_goof -> jsort_goof + +Sun Feb 16 01:17:25 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple_driver.c 1.5 + Unsinniger Parameter aus comerr() Aufruf beseitigt + +Sat Feb 15 22:05:58 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.35 + Bei -debug wird nun auch der root directory extent ausgegeben + +Sat Feb 15 22:03:43 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.94 + Padding neu beschrieben (150 Sektoren) + +Sat Feb 15 22:00:28 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.71 + Interpad rundet nur noch auf ein Vielfaches von 16 Sektoren auf + +Sat Feb 15 21:50:27 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * stream.c 1.1 + date and time created 03/02/15 21:50:27 by joerg + +Sat Feb 15 21:01:49 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.79 + * mkisofs.c 1.129 + * udf.c 1.10 + * write.c 1.70 + Umbau auf 150 Sektoren Padding am Ende des FS Images + +Sat Feb 15 13:59:11 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.93 + * mkisofs.c 1.128 + Neue Option -stream-media-size + +Thu Feb 13 09:37:52 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.69 + time_t begun -> EXTERN Freigeben fuer UDF & Stream.c + +Thu Feb 13 09:34:41 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.78 + Definitionen fuer stream.c + +Thu Feb 13 09:33:19 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * udf.c 1.9 + Externe time_t begun aus write.c uebernehmen fuer: PDV, LVDESC, File Set Desc, Main Seq + +Mon Feb 10 01:47:19 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.34 + Eingerueckt nach cstyle + +Sun Feb 9 21:49:45 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * udf.c 1.8 + Umformatier fuer cstyle + +Fri Feb 7 11:15:06 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.127 + Version -> 2.01a03, Graft-point nodename ist nun [2*PATH_MAX + 1 + 1] grosz + +Tue Jan 28 01:28:37 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * isoinfo.c 1.33 + Erkennung von ISO-9660:1999 + +Tue Jan 28 01:27:23 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.126 + Version -> 2.01a02 + +Tue Jan 28 01:25:58 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.125 + ISO-9660:1998 -> ISO-9660:1999, Schreibfehler bei -pad help beseitigt + +Tue Jan 28 01:25:04 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.68 + Bei ISO-9660:1999 ist der 2. VD ein ISO_VD_SUPPLEMENTARY (war vorher wie PVD) + +Tue Jan 28 01:24:09 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.92 + * iso9660.h 1.15 + ISO-9660:1998 -> ISO-9660:1999 + +Sun Jan 19 20:18:08 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.91 + Warnung vor Suns Eltorito Patch bei -iso-level 4 + +Sun Jan 19 16:19:29 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.26 + Bei relaxed Filenames wird '/' verboten. + +Sun Jan 19 16:00:57 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.90 + * iso9660.h 1.14 + * mkisofs.h 1.77 + * rock.c 1.33 + * mkisofs.c 1.124 + * multi.c 1.55 + * write.c 1.67 + Version -> 2.01a01, Erweiterungen fuer ISO-9660:1998 + +Sun Jan 19 15:55:18 2003 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.70 + Bessere RR overflow Meldung + +Wed Dec 25 15:16:49 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.25 + * files.c 1.11 + * multi.c 1.54 + ctype.h nach schily.h wegen OpenBSD #define EOF Bug + +Tue Dec 24 16:39:28 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.89 + * isoinfo.8 1.6 + Version -> 2.0 + +Mon Dec 23 18:25:55 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * dvd_file.c 1.2 + Support fuer 0 Byte VIDEO_TS/VTS_xx_0.VOB Files + +Mon Dec 16 22:37:04 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.88 + Umbau auf Berlios & fhg.de + +Sun Dec 15 02:03:20 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.66 + DVD-Video Pad Ausgaben auch ohne DEBUG + +Sat Dec 14 19:03:33 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * ChangeLog 1.22 + -> Version 2.0 + +Sat Dec 14 19:03:09 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * TODO 1.5 + Hints for ISO 9660:1988 + +Thu Dec 12 01:25:27 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.65 + Consistency check for DVD-Video Pad (<0) + +Thu Dec 12 01:25:01 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * ifo_read.c 1.3 + open() with O_BINARY + +Sat Dec 7 21:40:44 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.69 + in #ifdef ABORT_DEEP_ISO_ONLY print a hint for -R/-r and -D + +Sat Dec 7 21:14:50 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * udf.c 1.7 + write_udf_file_entries() now ignores de->de_flags & RELOCATED_DIRECTORY + and does not create a broken FS if RR_MOVED exists + +Sat Dec 7 21:02:08 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.64 + * mkisofs.h 1.76 + * mkisofs.c 1.123 + opnt->of_start_extent new for Constistency Check + +Sat Dec 7 20:41:36 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.87 + Better Documentation for -split-output + +Sat Dec 7 19:37:11 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.122 + Cast to int forr name_end-name (parameter in %.*s) + +Sat Nov 30 17:10:36 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.121 + Version -> 2.0 + +Sun Nov 24 12:54:45 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * TODO 1.4 + Open Problems for time past 2.0 + +Sun Nov 24 01:17:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * udf.c 1.6 + Patch from Wei DING <ding@memory-tech.co.jp> for UDF Files > 1 GB + +Fri Nov 22 17:32:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.68 + Another attempt to fix mkisofs -f + +Fri Nov 22 17:16:43 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.120 + Disable Joliet for -dvd-video (because of Sort in joliet.c) + -s/-S Warning disabled until 2.1alpha + +Fri Nov 22 17:15:34 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.34 + Make VIDEO_TS.IFO 1st dir entry with -dvd-video + +Sun Nov 17 15:42:19 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.119 + Mark -s/-S as reserved options + +Sat Nov 2 21:41:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.118 + Version -> 1.15a40, Tags in ~/.mkisofsrc have '_' in HFS_* + +Thu Oct 24 22:12:30 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.67 + scan_directory_tree() with new Flag DIR_WAS_SCANNED to avoid double scan + scan_directory_tree() more stable by setting errno = 0 before readdir() + no_scandir = 1 commented out to make mkisofs -f not to omit dir content with symlinks to dies + +Thu Oct 24 22:03:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.75 + #define DIR_WAS_SCANNED new + +Mon Oct 21 19:29:14 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.86 + * tree.c 1.66 + Typo removed + +Mon Oct 21 19:28:25 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.117 + Typo efective -> effective uid + +Sat Oct 5 00:38:01 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.63 + * volume.c 1.12 + * mkisofs.8 1.85 + * mkisofs.c 1.116 + * mkisofs.h 1.74 + Version -> 1.15a36, New Option -hfs-parms for better HFS > 4 GB Support from James Pearson + +Sat Oct 5 00:17:22 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.115 + Version -> 1.15a35, Warning for -L/-P/-H Options in POSIX.1-2001 + +Tue Oct 1 01:13:40 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.62 + * volume.c 1.11 + * mkisofs.8 1.84 + * desktop.c 1.5 + Patch from James for HSFS > 4 GB + +Sat Sep 28 16:55:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.83 + * mkisofs.h 1.73 + * write.c 1.61 + * volume.c 1.10 + Fix from James for 4 GB HFS Support + +Tue Sep 24 15:41:27 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.60 + * volume.c 1.9 + Patches from James to aboert on HFS volume size > 2 GB + +Sun Sep 1 23:59:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * udf.c 1.5 + Make sure directories have execute permission in default permissions. + +Sat Aug 10 23:33:36 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.114 + UDF Filenames may be 255 chars if not using Joliet + +Thu Aug 8 23:48:11 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.32 + * tree.c 1.65 + Symlink buffer size -> PATH_MAX to avoid Overflow + +Thu Aug 8 23:25:14 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * ifo_read.c 1.2 + Comment around Tag past #endif + +Thu Aug 8 23:24:37 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.33 + * mkisofs.8 1.82 + * mkisofs.c 1.113 + * mkisofs.h 1.72 + New Option -joliet-long + +Sun Jul 28 01:29:19 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.71 + Tag past #endif now as comment + +Sun Jul 28 01:28:29 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.59 + Defect Debug printf() with newline in String fixed + +Sun Jul 21 17:36:20 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.81 + -dvd-video Option new + +Sun Jul 21 17:00:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.32 + * write.c 1.58 + * mkisofs.h 1.70 + Pathtable now works wth more than 65535 Dires if all Parent indices are <= 65535 + +Sun Jul 21 16:42:36 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * dvd_reader.c 1.1 + date and time created 02/07/21 15:42:36 by joerg + +Sun Jul 21 16:40:43 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * ifo_read.c 1.1 + date and time created 02/07/21 15:40:43 by joerg + +Sun Jul 21 16:23:35 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.c 1.18 + * multi.c 1.53 + malloc() -> e_malloc() + +Sun Jul 21 15:51:54 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * dvd_file.c 1.1 + date and time created 02/07/21 14:51:54 by joerg + +Sun Jul 21 15:18:47 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * dvd_file.h 1.1 + date and time created 02/07/21 14:18:47 by joerg + +Sun Jul 21 15:16:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.57 + Support for DVD-Video -dvd-video + +Sun Jul 21 14:59:31 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.112 + * multi.c 1.52 + * tree.c 1.64 + * files.c 1.10 + 1024 -> PATH_MAX + +Sun Jul 21 14:21:02 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.31 + Hack against wrong GCC warning + +Sat Jul 20 17:57:49 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.c 1.17 + Function perr() now uses comerr() + +Sat Jul 20 17:54:57 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * ifo_types.h 1.1 + * dvd_reader.h 1.1 + date and time created 02/07/20 16:54:57 by joerg + +Sat Jul 20 17:54:56 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * ifo_read.h 1.1 + date and time created 02/07/20 16:54:56 by joerg + +Sat Jul 20 17:37:32 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.69 + Enhancements for DVD-Video -dvd-video + +Sat Jul 20 17:28:10 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * bswap.h 1.1 + date and time created 02/07/20 16:28:10 by joerg + +Sat Jul 20 01:17:52 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * udf.c 1.4 + DVD-Video comment new + +Sat Jul 20 01:15:19 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.111 + Version -> 1.15a27, Option -dvd-video new + +Sat Jul 20 01:13:31 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.63 + Sort Video Files only with -dvd-video + +Tue Jul 16 21:32:42 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.62 + * mkisofs.c 1.110 + * mactypes.h 1.2 + * mkisofs.8 1.80 + * apple.h 1.6 + * apple.c 1.16 + Support for Apple files on MacOS X + +Thu Jul 4 12:31:42 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.109 + Version -> 1.15a25, verbose > 1 writes debug info for output fragments. + +Thu May 30 01:48:28 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * udf.c 1.3 + * write.c 1.56 + * joliet.c 1.31 + * eltorito.c 1.24 + * boot.c 1.9 + * mkisofs.h 1.68 + of_name in struct output_fragment new + +Mon May 20 13:58:11 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mac_label.c 1.6 + ISO_ROUND_UP(mac_boot->size) / SECTOR_SIZE -> ISO_BLOCKS(mac_boot->size) + +Mon May 20 13:55:53 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.55 + Unused Var in graftcp() removed + +Mon May 20 13:51:28 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.67 + HFS_BLOCKS() new + +Tue May 14 21:13:04 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.54 + graftcp() Bug fixed (simple Filenames as Arg not shortened) + +Mon May 13 00:45:28 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * udf.c 1.2 + Now using ISO_ROUND_UP()/ISO_BLOCKS()/SEC_SIZE + +Mon May 13 00:40:04 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.53 + * joliet.c 1.30 + Now using ISO_ROUND_UP()/ISO_BLOCKS() + +Mon May 13 00:24:43 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.51 + Now using ISO_ROUND_UP() + +Mon May 13 00:22:40 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.108 + Version -> 1.15a23, Now using ISO_ROUND_UP()/ISO_BLOCKS() + +Mon May 13 00:08:55 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.23 + Now using ISO_BLOCKS() + +Sun May 12 14:42:18 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.66 + Comment for ISO_ROUND_UP(X)/ISO_BLOCKS(X) + +Sun May 12 14:10:20 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.61 + Function filetype() better + +Sun May 12 00:32:18 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.65 + ISO_BLOCKS() new + +Sat May 4 15:31:00 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.50 + file_addr now based on sectors not on bytes to avoid overflow with DVDs + +Fri May 3 01:17:51 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.24 + * mkisofs.c 1.107 + -no-iso-translate now also using '-' + +Sun Apr 28 14:50:15 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.79 + Remove outdated hint that at least one "pathspec" is needed + (even for File from list List) + +Sun Apr 28 14:48:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.106 + Version -> 1.15a22, susage() Bugfix (program_name missing) + +Tue Apr 16 19:19:41 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.22 + make boot.catalog sortable via -sort + +Sun Apr 14 22:53:26 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.52 + * mkisofs.h 1.64 + * mkisofs.c 1.105 + Avoid to put unwanted information into the version info + +Thu Apr 11 23:53:41 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.104 + Support for xxx/../yyy in graft-points + +Thu Apr 11 19:27:13 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.60 + * mkisofs.c 1.103 + Fix -graft-points /a/b//.///=some_dir bug (doubled / Dir), Version -> 1.15a21 + +Thu Apr 11 18:55:48 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.78 + UTF comment corrected + +Thu Apr 11 18:55:23 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.63 + debug new + +Wed Apr 3 19:47:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.102 + Version -> 1.15a20 + +Wed Apr 3 19:42:41 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.101 + Corrected file type recognition for graft points + +Wed Apr 3 19:00:32 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.30 + * mkisofs.c 1.100 + * mkisofs.8 1.77 + Transparent compression (-z) from H.P. Anvin integrated + +Wed Apr 3 18:12:07 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.99 + escstrcpy() corrected for multiple '//', new option -debug + +Tue Apr 2 00:57:38 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.98 + short usage added + +Fri Mar 8 16:44:37 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.76 + Hint for multisession on MAC -> -part + +Fri Mar 8 16:43:46 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mac_label.c 1.5 + Mac Label mpm[mpc].start = session_start + ... -> mpm[mpc].start = hce->hfs_map_size ... + +Tue Feb 26 22:39:16 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * boot.c 1.8 + Support generic boot for CD-extra (session_start != 0 Dreamcast) + +Sun Feb 10 20:18:32 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * hash.c 1.15 + use Prototyped function definition if we have dev_t arg because it may be < int + +Sun Feb 10 16:13:16 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * fnmatch.c 1.4 + Now using utypes.h, >=/<= compare with Uchar cast + +Sun Feb 10 15:56:51 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.c 1.15 + cast info->nlen to int for comparison + +Sat Feb 9 22:21:33 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.c 1.14 + strcmp() -> memcmp() for sfm_magic/sfm_version + +Fri Jan 18 12:48:35 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.75 + Write correct size info (1440 kB instead of 1.44 meg) for boot floppy sizes, correct .R typo (used instead of .B) at -magic + +Fri Jan 18 12:47:51 2002 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.21 + Write correct size info (1440 kB instead of 1.44 meg) for boot floppy sizes + +Mon Dec 10 01:05:06 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.74 + -udf option documented + +Mon Dec 10 01:04:38 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * getopt.c 1.5 + prototype for my_index() + +Sun Nov 25 12:53:17 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.73 + long unreadable option list removed from sysnopsis line + +Thu Nov 22 22:34:18 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.97 + Version -> 1.15a12 + +Thu Nov 22 22:24:38 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * udf_fs.h 1.1 + * udf.c 1.1 + * udf.h 1.1 + date and time created 01/11/22 22:24:38 by joerg + +Thu Nov 22 16:42:30 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile 1.10 + * Makefile 1.10 + * mkisofs.c 1.96 + * mkisofs.h 1.62 + Enhancements for UDF support + +Thu Nov 22 16:41:13 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.59 + add sort criteria for UDF VIDEO_TS and AUDIO_TS files. + +Thu Nov 22 16:40:47 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.29 + make convert_to_unicode()/joliet_strlen() global if UDF support is compiled in + +Thu Nov 22 15:24:44 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.72 + better documentation for README.sort/README.hide from James Pearson + +Thu Nov 22 00:42:31 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.51 + compare_sort() now behaves correctly if the parameters are exchanged so qsort() may sort correctly + +Tue Nov 20 00:55:44 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.71 + better documentation for -print-size, use \& if '.' is at beginning of line + +Tue Nov 20 00:54:35 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.50 + avoid #if defined(sun) || defined(_AUX_SOURCE), better error messages + +Fri Nov 16 18:15:42 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * desktop.c 1.4 + nitialize the whole struct hfsdirent in make_desktop() + +Sun Nov 11 20:38:20 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.h 1.5 + d_dtoutime() Prototype new + +Sun Nov 11 20:28:56 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.h 1.4 + * apple.c 1.13 + Preserves HFS file dates for AppleDouble, AppleSingle and NetaTalk files + +Sun Nov 11 13:38:45 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.29 + QNX Neutrino has no st_ftime + +Sun Oct 21 01:01:23 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * getopt.c 1.4 + Try to compensate FSF rubish code and supress warnings by always including standard include files + +Sun Oct 21 01:00:30 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.95 + Always use local getopt.h, version -> 1.15a09 + +Tue Oct 9 01:27:16 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.61 + sys/types.h & sys/stat.h -> statdefs.h + +Thu May 31 10:56:32 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.70 + -split-output description new, -hard-disk-boot/-no-emul-boot/-no-boot hint added to -b + +Sun Apr 22 11:34:46 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.94 + Comment for memset() in e_malloc() + +Fri Apr 20 23:53:40 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * ChangeLog 1.21 + Late changes for 1.14 + +Fri Apr 20 18:46:36 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.49 + Initalize more data from struct directory_record + +Fri Apr 20 18:45:47 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.93 + Always clear allocated memory to avoid uninitialized data. + +Tue Apr 17 00:57:30 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.69 + Hint to mailman + +Fri Apr 13 23:31:42 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * ChangeLog 1.20 + updated to release 1.14 + +Fri Apr 13 20:42:30 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.92 + Version -> 1.14 final + +Fri Apr 13 20:12:50 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.68 + New Support mail Adresses + +Thu Apr 12 19:36:39 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.91 + make insert_file_entry() failure non fatal in mkisofs main code + +Sat Apr 7 17:31:44 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.48 + starting to implement associated files in multi-session + +Sat Apr 7 14:47:49 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.58 + * mkisofs.c 1.90 + No exit() for warnings + +Tue Apr 3 23:33:26 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile 1.9 + * defaults.h 1.15 + APPID_DEFAULT now includes Copyright messages + +Mon Apr 2 23:17:05 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.47 + unused vars removed + +Mon Apr 2 20:09:22 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.89 + Fixed -check-session handling for -C0,0 default, Search for SUSP RR record in '.' of root + +Mon Apr 2 20:05:48 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.67 + New option -force-rr + +Mon Apr 2 20:05:25 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.46 + rr_flags()/parse_rrflags()/find_rr() new, get_session_start() handling for -check-session fixed + +Mon Apr 2 20:04:34 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.60 + rr_flags()/parse_rrflags()/find_rr() new + +Sun Apr 1 21:51:43 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.66 + -check-session new + +Sun Apr 1 21:51:11 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.88 + Parameter for -check-session added to usage + +Sun Apr 1 21:49:56 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.59 + -check-session neu + +Sun Apr 1 19:13:37 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.87 + * multi.c 1.45 + Need to handle -C (cdrecord_data) special if -check-session is set + +Sun Apr 1 17:46:59 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.23 + Back up to last '.' found if trying to find a better '.' did not work + +Sun Apr 1 17:45:17 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.86 + New option -check-session + +Tue Mar 20 01:09:27 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * volume.c 1.8 + * mkisofs.h 1.58 + * mkisofs.c 1.85 + * mkisofs.8 1.65 + New options for writable HFS files from James Pearson + +Sun Mar 4 15:13:00 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.64 + Better documentation for -no-cache-inodes + +Sun Mar 4 00:53:59 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.84 + Fix a bug with '-- filename' + +Sun Mar 4 00:52:29 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.63 + * hash.c 1.14 + * mkisofs.h 1.57 + * mkisofs.c 1.83 + new options -no-cache-inodes/-cache-inodes as a workaround for non unique inodes on Cygwin + +Fri Feb 23 21:58:52 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.62 + Einfo for RR_MOVED dir added + +Fri Feb 23 17:33:54 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.c 1.12 + set_Dinfo(hfs_info->finderinfo, hfs_ent); -> set_Finfo(hfs_info->finderinfo, hfs_ent); according to James Pearson to make --xinet option work + +Thu Feb 15 23:04:00 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.49 + output_fraagment now copied to allocated space to allow a desc to be used more than once + +Thu Feb 15 23:02:53 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.82 + version -> 1.14a14 + +Thu Jan 25 23:28:32 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile 1.8 + * eltorito.c 1.20 + * apple.c 1.11 + * mkisofs.h 1.56 + * tree.c 1.57 + * write.c 1.48 + changes to support large files + +Tue Jan 23 13:27:44 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.56 + * mkisofs.c 1.81 + * mkisofs.h 1.55 + * write.c 1.47 + * apple.c 1.10 + * rock.c 1.28 + * eltorito.c 1.19 + * joliet.c 1.28 + Avoid gcc -W warnings (e.g. signed/unsigned) + +Sat Jan 20 23:17:37 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.46 + * mkisofs.8 1.61 + * mkisofs.c 1.80 + -quiet make mkisofs really quiet + +Sat Jan 20 23:03:26 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.79 + Modified to allow EBCDIC + +Sat Jan 20 22:46:10 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.60 + * mkisofs.h 1.54 + * mkisofs.c 1.78 + * rock.c 1.27 + * joliet.c 1.27 + * apple.c 1.9 + Better charset tables for Apple + +Fri Jan 19 19:26:19 2001 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.55 + * mkisofs.c 1.77 + * mkisofs.8 1.59 + * mkisofs.h 1.53 + better rationalized uid/gid/modes + +Sat Dec 9 19:55:17 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.c 1.8 + u_short -> Ushort, u_int -> Uint + +Sat Dec 9 19:36:48 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.26 + u_char -> Uchar + +Tue Dec 5 15:25:02 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * volume.c 1.7 + * write.c 1.45 + * vms.c 1.6 + * tree.c 1.54 + * rock.c 1.26 + * name.c 1.22 + * multi.c 1.44 + * mkisofs.h 1.52 + * mkisofs.c 1.76 + * match.c 1.13 + * match.h 1.7 + * mac_label.c 1.4 + * joliet.c 1.25 + * hash.c 1.13 + * files.c 1.9 + * exclude.c 1.8 + * eltorito.c 1.18 + * desktop.c 1.3 + * apple_driver.c 1.4 + * boot.c 1.7 + * apple.c 1.7 + Completed conversion to Schily SING autoconfiguration + +Mon Dec 4 12:56:49 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.51 + Now first includes mconfig.h then stdio.h (for largefiles), now uses strdefs.h, standard.h for const abstraction, stdxlib.h instead of stdlib.h + +Mon Dec 4 12:53:32 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.43 + * scsi.c 1.17 + lseek now using SEEK_* macros + +Mon Dec 4 12:53:11 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mac_label.c 1.3 + * apple_driver.c 1.3 + * apple.c 1.6 + fseek now using SEEK_* macros + +Fri Dec 1 14:14:23 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.42 + Now working without usal_prbytes() from libusal + +Fri Nov 24 10:49:58 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.75 + -print-size now also prints an easy to parse string to stdout + +Fri Nov 24 10:49:29 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.58 + New -print-size behavior documented + +Sun Nov 19 16:34:56 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.74 + New option -no-pad, -pad now default, support for Cygwin-1.x + +Sun Nov 19 16:33:13 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile 1.7 + Umbau fuer mkhybrid + +Sun Nov 19 16:32:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile.man 1.3 + INSMODE= beseitigt + +Sun Nov 19 13:03:18 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.21 + Special handling for '#' and '~' disabled because the code created infinite dir tree loops + +Sat Nov 4 17:59:36 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.57 + New option -no-pad, -pad now default + +Sat Oct 14 15:33:50 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.56 + hint for CD-Extra usage (-M/-C), note for -graft-points option in examples that need -graft-points + +Fri Sep 8 02:49:31 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.16 + Call to usal_remote() + +Fri Sep 8 02:49:00 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.73 + Warning for using Joliet without Rock Ridge + +Fri Aug 25 15:31:13 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * match.c 1.12 + * mkisofs.c 1.72 + new-line discarded only if really present + +Mon Aug 14 01:36:38 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.71 + Graft-points repariert fuer esacped = + +Sun Jul 30 14:08:38 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.41 + * scsi.c 1.15 + Modified for new libusal with usal_*() + +Thu Jul 20 19:29:19 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.70 + Version -> 1.13 + +Thu Jul 20 19:27:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mac_label.c 1.2 + Size arithmetic fix for HFS vol size + +Thu Jul 20 19:27:12 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.55 + Small typo fixes + +Tue Jun 27 19:12:02 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.69 + * mkisofs.8 1.54 + New option -graft-points + +Tue Jun 27 01:38:35 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.68 + 1.13a02 -> 1.13a03 + +Tue Jun 27 01:31:27 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.67 + allow -path-list option to work without a command line arg, graft pointer escapes haf way ready + +Tue Jun 27 01:20:27 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * match.c 1.11 + better parser for -sort option, avoid buffer overflows by not using fscanf + +Tue Jun 27 01:18:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.53 + Better doc for -sort option + +Mon Jun 26 23:50:33 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple_driver.c 1.2 + Converted for Schily SING makefile system, made portable + +Mon Jun 5 03:19:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.44 + percent output now even works with NO_FLOATINGPOINT + +Sat Jun 3 14:24:26 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.43 + buffer[] -> static in write_one_file() for sake of the silly Metrowerks C found on BeOS/PPC + +Sun May 28 17:41:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.66 + version -> 1.13a02 + +Sun May 28 17:03:48 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.17 + * mkisofs.8 1.52 + * mkisofs.h 1.50 + * mkisofs.c 1.65 + New option -eltorito-alt-boot + +Sun May 28 16:28:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.51 + Integration of mkisofs/mkhybrid to one single application + +Sun May 28 13:21:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.40 + Check for reloc_dir != NULL in match_cl_re_entries() + +Sun May 7 17:23:57 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * match.c 1.10 + * scsi.c 1.14 + * boot.c 1.6 + * eltorito.c 1.16 + * name.c 1.20 + * joliet.c 1.24 + * multi.c 1.39 + * rock.c 1.25 + * hash.c 1.12 + * write.c 1.42 + * tree.c 1.53 + * mkisofs.c 1.64 + #include <schily.h> + +Sun May 7 17:14:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.63 + Release -> 1.13a01, removed comment for associated files as it has been wrong + +Thu Apr 27 14:11:30 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * RELEASE 1.31 + Release 1.12.1 + +Thu Apr 27 14:06:09 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.50 + New Opton -root-info, typo's corrected + +Thu Apr 27 13:54:09 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.c 1.5 + cast for correct char * / unsigned char * handling + +Thu Apr 27 13:36:25 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * volume.c 1.6 + * apple.h 1.3 + * desktop.c 1.2 + * apple.c 1.4 + Major changes to implement new HFS option -root-info and -jcharset mac-roman + +Thu Apr 27 12:47:26 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile 1.6 + New file place sorting option activated with -DSORTING + +Thu Apr 27 12:46:35 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * ChangeLog 1.19 + updated to release 1.12.1 + +**************** Release 1.12.1 ******************* + +Thu Apr 27 12:44:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.52 + * rock.c 1.24 + * mkisofs.h 1.49 + * mkisofs.c 1.62 + New HFS option -root-info + +Fri Apr 21 22:11:17 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.41 + better double conversion for estimation time computation + +Fri Apr 21 22:04:56 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.19 + Name trucation warning removed because it does not work. + +Fri Apr 21 18:37:36 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.18 + * mkisofs.h 1.48 + * mkisofs.c 1.61 + * mkisofs.8 1.49 + -max-iso0660-filenames + +Fri Apr 21 18:09:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.51 + Creating unique filenames now works even if we are creating 37 char names + +Thu Apr 20 22:14:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.50 + Make TRANS.TBL wider to allow 37 char iso names, avoid hard coded values + +Thu Apr 20 21:44:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.38 + Parsing of TRANS.TBL now adaptive instead of using hard coded numbers + +Wed Apr 19 23:59:22 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.49 + * multi.c 1.37 + * iso9660.h 1.13 + MAX_ISONAME fom 38 -> 37 + +Tue Apr 18 16:22:56 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * volume.c 1.5 + Use HFS_FNDR_ISINVISIBLE for dirs too + +Tue Apr 18 16:20:03 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.17 + * tree.c 1.48 + * multi.c 1.36 + * mkisofs.h 1.47 + * mkisofs.c 1.60 + * mkisofs.8 1.48 + Removed Option -all-files, New options -iso-level, -allow-lowercase, -allow-multidot, -relaxed-filenames, -use-fileversion, name.c completely rewritten + +Sun Apr 16 16:30:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.47 + * name.c 1.16 + * mkisofs.h 1.46 + * mkisofs.c 1.59 + New Option -no-iso-translate + +Sun Apr 16 16:26:37 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.46 + New Options -sort & -ucs-level + +Sun Apr 16 15:24:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * defaults.h 1.14 + * mkisofs.h 1.45 + * multi.c 1.35 + Copyright Schilling added + +Sun Apr 16 15:22:32 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * iso9660.h 1.12 + struct iso_ext_attr_record new + +Sun Apr 16 14:47:53 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.23 + * mkisofs.h 1.44 + * mkisofs.c 1.58 + New Option -ucs-level + +Sun Apr 16 14:12:24 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.43 + * mkisofs.c 1.57 + * tree.c 1.47 + * hash.c 1.11 + * write.c 1.40 + New sort code from James Pearson + +Sun Apr 16 13:39:46 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * match.h 1.6 + * match.c 1.9 + Converted to unified match code, new sort match code + +Sat Apr 15 21:59:15 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * volume.c 1.4 + Apply ISO Hidden flag to files on HFS volume too + +Sat Apr 15 20:57:06 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.15 + Handle '.' and '..' entries corretly in iso9660_check() + +Wed Apr 12 23:56:56 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.45 + New option -check-oldnames + +Wed Apr 12 23:44:18 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.c 1.3 + strcasecmp() local implementation + +Wed Apr 12 23:24:10 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile 1.5 + HFILES added to get better ctags + +Wed Apr 12 23:23:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.34 + * name.c 1.14 + * mkisofs.h 1.42 + * mkisofs.c 1.56 + New Option -check-oldnames, new function iso9660_check() to check/repair filenames from old session, better error messages for bad RR attributes, avoid coredump with calling memset with negative count. + +Tue Apr 11 10:50:04 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * iso9660.h 1.11 + * tree.c 1.46 + iso_directory_record now uses MAX_ISONAME (38) old was 34 + +Sun Apr 9 22:04:42 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.33 + Better error messages for bad XA disks. + +Sun Apr 9 17:06:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.55 + Version -> 1.12.1a06, corrected help for -l (30 chars!) + +Sun Apr 9 17:05:47 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.45 + Put number to make names unique before the dot to retain the suffix + +Sun Apr 9 14:28:01 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.44 + some more curly brackets.... + +Sat Apr 8 23:51:20 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.54 + removed duplicate OPTION_H_LIST + +Sat Apr 8 23:44:43 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.44 + * tree.c 1.43 + * mkisofs.c 1.53 + * match.c 1.8 + * mkisofs.h 1.41 + * match.h 1.5 + New option -hidden & -hidden-list to implement hidden (ISO existence flag) files + +Sat Apr 8 23:32:45 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.43 + better padding documentation (-pad) + +Sat Apr 8 20:55:49 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.42 + added description for mkhybrid + +Sat Apr 8 20:50:47 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.41 + add \ before some - signs and mark some mkisofs places with \& to prevent repleacement with sed script + +Sat Apr 8 19:40:05 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.40 + typo correction and preparation towards unified manual (mkisofs/mkhybrid) + +Sat Apr 8 16:05:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * volume.c 1.3 + * write.c 1.39 + * tree.c 1.42 + * multi.c 1.32 + * joliet.c 1.22 + * eltorito.c 1.15 + * iso9660.h 1.10 + * mkisofs.h 1.40 + Now using iso directory flag definition from iso9660.h + +Mon Apr 3 23:59:05 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.31 + Minor clean up, Message about XA records + +Mon Apr 3 23:40:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.39 + * match.c 1.7 + * exclude.c 1.7 + indented + +Mon Apr 3 21:06:04 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.14 + insert_boot_cat() prototype + +Mon Apr 3 02:22:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.41 + * write.c 1.38 + * mkisofs.c 1.52 + * rock.c 1.23 + * name.c 1.13 + * joliet.c 1.21 + * hash.c 1.10 + * files.c 1.8 + * eltorito.c 1.13 + * vms.c 1.4 + indented + +Mon Apr 3 00:38:28 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.40 + * multi.c 1.30 + parse_xa() new to skip XA extended directory attributes + +Sun Apr 2 22:24:43 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.38 + * write.c 1.37 + version_desc new + +Sun Apr 2 21:15:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.51 + version desc new + +Sun Apr 2 20:28:06 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * vms.c 1.5 + eric -> joerg + +Sun Apr 2 19:10:28 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * iso9660.h 1.9 + struct iso_xa_dir_record new + +Sun Apr 2 19:01:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.20 + stdlib.h -> stdxlib.h, rtmp, ltmp (short -> char[2]) for correct byteorder handling + +Sun Apr 2 18:14:35 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * files.c 1.7 + Typo correction + +Sat Apr 1 22:29:29 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * iso9660.h 1.8 + Indented + +Fri Mar 31 18:50:41 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * volume.c 1.2 + New function set_cusstom_icon() + +Fri Mar 31 18:48:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.h 1.2 + * apple.c 1.2 + sys/param.h removed, MAXPATHLEN -> PATH_MAX for portability + +Fri Mar 31 18:44:31 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.19 + Now sort joliet tree according to Unicode order + +Fri Mar 31 18:38:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.39 + * write.c 1.36 + * mkisofs.h 1.37 + * mkisofs.c 1.50 + New option -pad + +Fri Mar 31 12:59:06 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.38 + -jcharset implies -J + +Fri Mar 31 12:55:30 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.49 + hfs_ct var new, -hfs-creator typo in option parsing fixed + +Thu Mar 30 02:47:14 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.48 + 1.8.1a04 -> 1.8.1a05, -icon-position option needs no argument, -jcharset now implies -J + +Thu Mar 30 02:43:18 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.36 + #include limits.h for NAME_MAX, PATH_MAX definition new + +Wed Mar 29 10:33:45 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.c.bak 1.1 + date and time created 00/03/29 09:33:45 by joerg + +Sun Mar 26 18:44:46 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.37 + Better doc for -jcharset + +Sun Mar 26 18:40:23 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.47 + Unicode mapping now defaults to iso8859-1 resp. cp437 + +Sun Mar 26 18:31:24 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.46 + * defaults.h 1.13 + defined(__CYGWIN__) added for Cygwin recognition + +Sat Mar 25 17:10:43 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.36 + * joliet.c 1.18 + * Makefile 1.4 + * mkisofs.c 1.45 + Joliet character translation using different character sets (-jcharset) + +Sun Mar 19 20:08:24 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * boot.c 1.5 + -B ... zum Duplizieren der letzten Partition bis zum Ende der Partitions Map + +Sun Mar 19 20:02:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.35 + New usage for -B option: ... means replicate previous boot partition + +Sun Mar 19 19:19:46 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * defaults.h 1.12 + Mac OS X definition new + +Sun Mar 19 16:46:31 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.39 + * multi.c 1.29 + * mkisofs.c 1.44 + * mkisofs.h 1.35 + RR deep directory relocation fixes for multi-session from: "Artem Hodyush" <artem@duma.gov.ru> + +Sun Mar 19 16:15:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.28 + made conform to schily programming rules + +Sun Mar 19 16:02:46 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.27 + indented + +Sat Mar 18 23:59:42 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * README.eltorito 1.2 + typo corrected + +Sat Mar 18 22:43:10 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.43 + * tree.c 1.38 + added code for APPLE_HYBRID + +Sat Mar 18 19:39:14 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.34 + removed superfluous spaces + +Sat Mar 18 19:24:34 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.h 1.1 + date and time created 00/03/18 19:24:34 by joerg + +Sat Mar 18 19:24:13 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mac_label.h 1.1 + date and time created 00/03/18 19:24:13 by joerg + +Sat Mar 18 19:23:54 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mactypes.h 1.1 + date and time created 00/03/18 19:23:54 by joerg + +Sat Mar 18 19:18:36 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * desktop.c 1.1 + date and time created 00/03/18 19:18:36 by joerg + +Sat Mar 18 19:18:09 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mac_label.c 1.1 + date and time created 00/03/18 19:18:09 by joerg + +Sat Mar 18 19:16:33 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * volume.c 1.1 + date and time created 00/03/18 19:16:33 by joerg + +Sat Mar 18 17:56:59 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * apple.c 1.1 + date and time created 00/03/18 17:56:59 by joerg + +Sat Mar 18 13:52:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.35 + * mkisofs.h 1.34 + added code for APPLE_HYBRID, ROUND_UP() -> ISO_ROUND_UP() + +Sat Mar 18 13:44:25 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * defaults.h 1.11 + Use better recognition code for Rhapsody + +Sat Mar 18 13:41:24 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.17 + ROUND_UP() -> ISO_ROUND_UP() + +Sat Mar 18 13:02:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * boot.c 1.4 + 2048 -> SECTOR_SIZE + +Sat Mar 18 13:00:02 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.12 + csum_buffer[2048] -> csum_buffer[SECTOR_SIZE] + +Sun Mar 12 20:50:51 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.16 + * rock.c 1.22 + added code for APPLE_HYBRID + +Sat Mar 11 14:00:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * match.c 1.6 + added match code for APPLE_HYBRID, better error messages + +Sat Mar 11 13:38:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * hash.c 1.9 + New function flush_hash() for APPLE_HYBRID + +Sat Mar 11 13:21:13 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * match.h 1.4 + Added definitions for APPLE_HYBRID + +Sat Mar 11 13:19:07 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * defaults.h 1.10 + Defaults for HFS (mkhybrid), SYSTEM_ID_DEAULT for Rhapsody + +Sun Mar 5 18:08:30 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.15 + Always sort root dir to be first in path table + +Sun Mar 5 14:28:41 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.33 + correction for boot.catalog description, -table-name documented + +Sun Mar 5 14:27:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.12 + replace forgotten but illegal chars by '_' + +Sat Mar 4 16:33:38 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.42 + close_merge_image() call from multi.c, do not close merge image a second time + +Sat Mar 4 16:32:32 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.33 + * multi.c 1.26 + new function clode_merge_image(), close_merge_image() -> mkisofs.c + +Thu Feb 17 00:10:46 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * sunlabel.h 1.3 + * boot.c 1.3 + splitted into boot.c and sunlabel.h + +Wed Feb 16 17:55:06 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * getopt.c 1.3 + Prototypes for exchange() & _getopt_initialize() + +Wed Feb 16 17:08:57 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.32 + prototype for scsidev_close() + +Wed Feb 16 17:08:36 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.25 + merge_previous_session() now calls scsidev_close() to allow mkisofs | cdrecord with multi session + +Mon Feb 14 15:58:26 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * bootinfo.h 1.2 + comment added + +Thu Feb 10 01:10:21 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.13 + scsidev_close() neu + +**************** Release 1.12 ******************* + +Mon Jan 17 23:53:16 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * RELEASE 1.30 + * mkisofs.c 1.41 + * mkisofs.8 1.32 + Release 1.12 + +Fri Jan 14 02:26:40 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.31 + -no-rr new, Bugs section + +Wed Jan 12 16:19:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * README.graft_dirs 1.1 + date and time created 00/01/12 16:19:55 by joerg + +Tue Jan 11 13:17:32 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.14 + allow odd to buffer sizes when converting to unicode + +Mon Jan 10 23:17:25 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.37 + * rock.c 1.21 + now using device.h + +Mon Jan 10 02:26:07 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.40 + -no-rr new + +Mon Jan 10 01:45:07 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.24 + * mkisofs.h 1.31 + no_rr new + +Sat Jan 8 23:42:24 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.12 + scsi_read() beachtet nun is_atapi damit mkisofs auch mit ATAPI multi-session kann + +Fri Jan 7 20:51:10 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.36 + print file typee, better error messages, no_scandir added + +Fri Jan 7 20:42:00 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.20 + * exclude.c 1.6 + better error messages + +Fri Jan 7 20:41:04 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.39 + new -U flag, -F flag removed, new list match code + +Fri Jan 7 20:32:22 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * match.c 1.5 + new list match code + +Fri Jan 7 19:26:08 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.30 + new hide options, -F removed -U new + +Fri Jan 7 18:58:12 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.34 + make TRANS.TBL a variable, gui code gives faster verbose message + +Fri Jan 7 18:55:19 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.23 + make TRANS.TML name a variable + +Fri Jan 7 18:52:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.30 + -U new, new match list code + +Fri Jan 7 18:07:38 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * match.h 1.3 + new match list code + +Wed Jan 5 20:06:55 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.11 + -U flag new + +Sun Jan 2 00:37:28 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.38 + Version js-a38 + +Sat Jan 1 23:05:28 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.33 + using offsetof() to get around odd structure length, better error messages + +Sat Jan 1 23:03:42 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.13 + * multi.c 1.22 + * tree.c 1.35 + using offsetof() to get around odd structure length + +Sat Jan 1 20:31:59 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * iso9660.h 1.7 + Note for odd length added + +Sat Jan 1 20:31:53 2000 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.29 + offsetof() macro new + +Wed Dec 29 14:38:31 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.29 + * mkisofs.h 1.28 + * mkisofs.c 1.37 + New options -hide-rr-moved & -hide-joliet-trans-tbl + +Wed Dec 29 14:21:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.34 + New options -hide-rr-moved & -hide-joliet-trans-tbl, better error messages + +Tue Dec 28 18:23:43 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.21 + better error messages, free more structures, check for bad RR Version, fix direactory handling code for graft pointers + +Tue Dec 28 16:32:00 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * getopt.c 1.2 + fixed uninitialized variable + +Tue Dec 28 15:12:05 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * hash.c 1.8 + * files.c 1.6 + * write.c 1.32 + better error messages + +Tue Dec 28 15:07:29 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.11 + better error messages, make boot file/ boot catalog hidable + +Tue Dec 28 14:21:26 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.12 + Error message made different from others + +Mon Dec 27 15:34:43 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * iso9660.h 1.6 + indented + +Mon Dec 20 00:14:20 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.33 + config.h must be first, boot catalog becomes MEMORY FILE + +Sun Dec 19 22:31:42 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.36 + hard disk boot, no emulation boot + +Sun Dec 19 21:29:59 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.10 + better autoconf, hd boot, no emulation boot, boot catalog as memory file + +Sun Dec 19 21:06:46 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.10 + fix with file priority + +Sun Dec 19 21:01:37 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.27 + hard disk boot/ no emulation boot new, MEMORY FILE new + +Sun Dec 19 20:58:32 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.31 + config.h must be first get_731()/get_732() new + +Sun Dec 19 20:57:02 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.19 + * multi.c 1.20 + config.h must be first + +Sun Dec 19 20:55:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * hash.c 1.7 + include stdlib.h past config.h + +Sun Dec 19 20:33:49 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * diskmbr.h 1.1 + date and time created 99/12/19 20:33:49 by joerg + +Sun Dec 19 19:54:43 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * iso9660.h 1.5 + changes for NOEMUL BOOT + +Sun Dec 19 18:16:10 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * bootinfo.h 1.1 + date and time created 99/12/19 18:16:10 by joerg + +Sun Dec 19 16:38:04 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.28 + hard disk boot and no emulation boot + +Sun Dec 19 16:13:21 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * sunlabel.h 1.2 + * boot.c 1.2 + Ueberfluessige Variablen beseitigt, Prototypen fuer geboot_*() + +Sat Dec 18 01:11:43 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile.in 1.16 + Erics final changes + +Wed Dec 15 01:24:58 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.35 + sparc boot new, -nomak new, suid mode now safe + +Sun Dec 12 22:01:32 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * README.sparcboot 1.1 + date and time created 99/12/12 22:01:32 by joerg + +Sun Dec 12 19:26:57 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.30 + * mkisofs.8 1.27 + * mkisofs.h 1.26 + sparc boot new + +Sun Dec 12 18:28:09 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile 1.3 + boot.c new + +Sun Dec 12 18:03:39 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * sunlabel.h 1.1 + * boot.c 1.1 + date and time created 99/12/12 18:03:39 by joerg + +Sat Dec 11 16:26:54 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.32 + rstr() new to check for .bak files + +Fri Dec 10 01:58:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.19 + Check first if -M file exists before trying to use scsidev_open() + +Tue Dec 7 00:33:13 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.29 + new sort_dir code checks for is_rr_dir + +Tue Dec 7 00:21:00 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.31 + Do not make directory loop fatal, new sort_directory code + +Tue Dec 7 00:19:32 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.25 + sort directory prototyp modified + +Mon Dec 6 23:40:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.11 + use comerr() + +Mon Dec 6 22:46:07 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.34 + Version js-a34 + +Sat Dec 4 20:56:21 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.18 + Allow RR Version 2 for Mac, memcmp() returns != null for misscompare of date!!! + +Sat Dec 4 20:48:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.28 + Allow the same name in rr_moved + +Tue Nov 30 17:16:47 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.10 + strncmp() for max of 64 chars in Joliet dirs + +Sat Nov 27 22:05:15 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.30 + Force graft dirs to be at least SECTOR_SIZE, dup missing whole_name + +Thu Nov 25 10:44:05 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * defaults.h 1.9 + Various new system definitions + +Thu Nov 25 00:25:08 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.33 + -version new + +Tue Nov 23 00:11:24 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.26 + Hint to new maintainer Joerg Schilling + +Tue Nov 23 00:05:30 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.32 + Version js-a32, -cdwrite-params -> -cdrecord-params + +Tue Nov 23 00:03:15 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * README 1.7 + cdwrite hint removed + +Tue Nov 23 00:01:13 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.17 + TRANS.TBL handling corrected + +Mon Nov 22 23:47:21 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.11 + Abbruch bei Lesefehlern in readsecs() + +Mon Nov 22 21:41:38 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.18 + #ifdef corrected for BLK/CHR devices + +Fri Nov 19 23:01:59 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.29 + S_IFBLK checked for OS/2 + +Fri Nov 12 11:55:44 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * eltorito.c 1.9 + clean castings + +Fri Nov 12 11:53:07 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.27 + clean casting + +Fri Nov 12 11:45:03 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.24 + #include statdefs.h + +Wed Nov 3 23:56:49 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.31 + Release js-a31 + +Mon Nov 1 22:29:15 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile.man 1.2 + INSMODE new + +Sat Oct 16 18:52:16 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.30 + Release 1.12b5-js-a30, removed & before array + +Fri Oct 15 22:01:18 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.16 + Removed & before array + +Fri Oct 8 19:54:24 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * match.c 1.4 + make it work correctly on 64 bit systems + +Mon Sep 13 12:10:13 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.29 + Version to 1.12b5-js-28 + +Tue Sep 7 16:45:13 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.10 + Umbau auf neues open_scsi(), commerr() statt fprintf(stderr) + +Tue Sep 7 14:52:25 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * rock.c 1.17 + HAVE_READLINK test, use comerr() + +Tue Sep 7 14:50:50 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.9 + * hash.c 1.6 + * files.c 1.5 + * eltorito.c 1.8 + * multi.c 1.15 + * write.c 1.26 + use comerr() + +Tue Sep 7 14:32:27 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.28 + use comerr(), HAVE_READLINK test + +Tue Sep 7 14:13:12 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.28 + use comerr()/save_args() + +Tue Sep 7 14:10:48 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile 1.2 + USE_LIBSCHILY new + +Sun Aug 29 01:59:22 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.23 + HAVE_LSTAT test new + +Sun Aug 1 22:50:12 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * defaults.h 1.8 + SYSTEM ID DEFAULT for OS/2 + +Sun Jul 11 19:32:42 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * multi.c 1.14 + <translation table> -> TRTANS.TBL for Joliet, round up to SECSIZE for reading TRANS.TBL + +Sun Jul 11 19:30:08 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * tree.c 1.27 + <translation table> -> TRTANS.TBL for Joliet, ignore-loops new + +Mon Jun 21 11:46:40 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * write.c 1.25 + Check for Rock Ridge files with same name + +Thu Jun 17 16:31:43 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.9 + cleaned up + +Thu Jun 17 16:30:18 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.8 1.25 + Better words, -F option new + +Thu Jun 17 16:17:18 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.27 + wildcard for EMX, ignore loops, no-split-symlink-fields/no-split-symlink-components now work + +Tue May 25 21:09:44 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.h 1.22 + ignore-loops new + +Wed May 19 16:41:02 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * joliet.c 1.8 + debug print for joliet files wirh same name + +Wed Apr 28 16:58:37 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * name.c 1.8 + Better handling for chars > 128 + +Sat Apr 24 18:39:19 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.9 + Wegen OS/2 wird nun scsi_getbuf() aufgerufen, wait_inut_ready() neu, read_capacity() neu, Schleife ueber read_scsi, falls der transfer groeszer als der SCSI Puffer ist. + +Sat Apr 24 18:25:00 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * mkisofs.c 1.26 + #ifdef for EMX (OS/2) + +**************** Release 1.12b5 ******************* + +Mon Mar 8 01:32:05 1999 Eric Youngdale <eric@andante.org> + * RELEASE 1.29 + Release1.12b5 + +Mon Mar 8 01:31:05 1999 Eric Youngdale <eric@andante.org> + * mkisofs.8 1.24 + many new options from Joerg Schilling, Release 1.12b5 + +Sun Mar 7 22:48:49 1999 Eric Youngdale <eric@andante.org> + * mkisofs.c 1.25 + several new options, binary open for Win32 + +Sun Mar 7 18:41:19 1999 Eric Youngdale <eric@andante.org> + * write.c 1.24 + split-output new, binary open for Win32, avoid incorrect sorting for ./.. with -L, ISO hide code + +Sun Mar 7 18:41:19 1999 Eric Youngdale <eric@andante.org> + * tree.c 1.26 + Inhibit code, sprintf() now correct, varoius other fixes + +Sun Mar 7 18:41:19 1999 Eric Youngdale <eric@andante.org> + * joliet.c 1.7 + Let all iso8859-1 chars be unicode, Joliet hide code + +Tue Mar 2 05:16:41 1999 Eric Youngdale <eric@andante.org> + * multi.c 1.13 + Prototypes and other various bug fixes + +Tue Mar 2 05:16:41 1999 Eric Youngdale <eric@andante.org> + * mkisofs.h 1.21 + better prototypes, INHIBIT_ISO9660_entry new, volume_set_size/volume_sequence_number + +Tue Mar 2 05:16:40 1999 Eric Youngdale <eric@andante.org> + * Makefile.in 1.15 + Release 1.12b5 + +Tue Mar 2 05:16:40 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * README.session 1.3 + Modified for cdrecord + +Tue Mar 2 04:41:26 1999 Eric Youngdale <eric@andante.org> + * rock.c 1.16 + Binary open for Win32, some other fixes + +Tue Mar 2 04:41:26 1999 Eric Youngdale <eric@andante.org> + * name.c 1.7 + casts for unsigned char * + +Tue Mar 2 04:41:25 1999 Eric Youngdale <eric@andante.org> + * match.h 1.2 + * match.c 1.3 + Joliet/ISO hide code new + +Tue Mar 2 04:41:25 1999 Eric Youngdale <eric@andante.org> + * defaults.h 1.7 + APPID_DEFAULT new + +Tue Mar 2 04:41:25 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * exclude.h 1.2 + __PR() macros + +Tue Mar 2 04:41:25 1999 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * fnmatch.c 1.3 + some casts for unsigned char * + +Tue Mar 2 04:41:25 1999 Eric Youngdale <eric@andante.org> + * eltorito.c 1.7 + small bug fixes + +Sun Nov 29 19:13:43 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.8 + usalio.h -> usalcmd.h/usalio.h, usalio.h usalcmd.h scsidefs.h scsireg.h scsitransp.h -> include/usal + +Sun Nov 29 18:30:41 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile 1.1 + date and time created 98/11/29 18:30:41 by joerg + +Sat Nov 14 04:20:05 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * Makefile.man 1.1 + date and time created 98/11/14 04:20:05 by joerg + +Fri Oct 30 02:06:35 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.7 + open_scsi() returniert nun SCSI *usalp, wird auch fuer read_scsi() verwendet + +Sat Oct 24 01:29:24 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.6 + open_scsi(dev, timeout, verboseopen) -> open_scsi(dev, debug, verboseopen) + +**************** Release 1.12b4 ******************* + +Tue Jun 2 06:44:45 1998 Eric Youngdale <eric@andante.org> + * RELEASE 1.28 + Release 1.12b4 + +Tue Jun 2 06:43:45 1998 Eric Youngdale <eric@andante.org> + * mkisofs.c 1.24 + New options -print-size & -split-output, put Joliet & ElTorite PVD in right order + +Tue Jun 2 06:43:44 1998 Eric Youngdale <eric@andante.org> + * mkisofs.8 1.23 + -print-size/-split-output new, Release 1.12b4 + +Tue Jun 2 06:14:58 1998 Eric Youngdale <eric@andante.org> + * tree.c 1.25 + Win32 changes, do not use sprintf result, some other fixes + +Tue Jun 2 05:40:39 1998 Eric Youngdale <eric@andante.org> + * write.c 1.23 + -split-output, several fixes + +Tue Jun 2 05:40:38 1998 Eric Youngdale <eric@andante.org> + * multi.c 1.12 + Some fixes with DOT/DODOT, create whole_name by strdup + +Tue Jun 2 05:40:38 1998 Eric Youngdale <eric@andante.org> + * mkisofs.h 1.20 + Win32, -print-size, -split-output + +Tue Jun 2 05:40:38 1998 Eric Youngdale <eric@andante.org> + * name.c 1.6 + No version number if it is part of the filename + +Tue Jun 2 05:40:37 1998 Eric Youngdale <eric@andante.org> + * eltorito.c 1.6 + O_BINARY for Win32 + +Tue Jun 2 05:40:37 1998 Eric Youngdale <eric@andante.org> + * joliet.c 1.6 + bug fix for ce_bytes and chars > 128 + +Tue Jun 2 05:40:37 1998 Eric Youngdale <eric@andante.org> + * defaults.h 1.6 + Defaults for Win32 + +Tue Jun 2 05:40:36 1998 Eric Youngdale <eric@andante.org> + * Makefile.in 1.14 + CFLAGS new + +Fri Apr 17 12:39:39 1998 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.5 + Prototypen entfernt fuer K&R C + +**************** Release 1.12b3 ******************* + +Wed Feb 18 05:51:47 1998 Eric Youngdale <eric@andante.org> + * RELEASE 1.27 + * mkisofs.c 1.23 + * mkisofs.8 1.22 + Release 1.12b3 + +Wed Feb 18 05:48:24 1998 Eric Youngdale <eric@andante.org> + * tree.c 1.24 + check for relocated dirs + +Wed Feb 18 05:48:23 1998 Eric Youngdale <eric@andante.org> + * rock.c 1.15 + check strlen of symlink buffer + +**************** Release 1.12b2 ******************* + +Mon Feb 16 18:57:56 1998 Eric Youngdale <eric@andante.org> + * RELEASE 1.26 + * mkisofs.c 1.22 + * mkisofs.8 1.21 + Release 1.12b2 + +Mon Feb 16 18:56:56 1998 Eric Youngdale <eric@andante.org> + * tree.c 1.23 + small bug fixes, Ingoring file message + +Mon Feb 16 18:56:56 1998 Eric Youngdale <eric@andante.org> + * write.c 1.22 + bug fix.... + +Mon Feb 16 18:56:55 1998 Eric Youngdale <eric@andante.org> + * mkisofs.h 1.19 + better autoconf, better prototypes + +Mon Feb 16 18:56:55 1998 Eric Youngdale <eric@andante.org> + * joliet.c 1.5 + several casts to unsigned char * + +**************** Release 1.12b1 ******************* + +Mon Dec 15 13:48:59 1997 Eric Youngdale <eric@andante.org> + * RELEASE 1.25 + * mkisofs.c 1.21 + * mkisofs.8 1.20 + Release 1.12b1 + +Mon Dec 15 13:47:59 1997 Eric Youngdale <eric@andante.org> + * rock.c 1.14 + mkdev() autoconf corrected + +Mon Dec 15 13:47:59 1997 Eric Youngdale <eric@andante.org> + * mkisofs.h 1.18 + string.h/strings.h autoconf + +Mon Dec 15 13:47:59 1997 Eric Youngdale <eric@andante.org> + * tree.c 1.22 + set isorec.size later + +Mon Dec 15 13:47:58 1997 Eric Youngdale <eric@andante.org> + * eltorito.c 1.5 + some printf's moved to stderr to avoid problems + +Mon Dec 15 13:47:57 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * configure.in 1.4 + several new tests + +**************** Release 120697 ******************* + +Sat Dec 6 22:06:07 1997 Eric Youngdale <eric@andante.org> + * RELEASE 1.24 + * ChangeLog 1.18 + Release 120697 + +Sat Dec 6 22:05:07 1997 Eric Youngdale <eric@andante.org> + * write.c 1.21 + * tree.c 1.21 + * rock.c 1.13 + Fix uninitialized memory usage that screwed up lots of stupid things. Add support for non-split symlinks. + +Sat Dec 6 22:05:05 1997 Eric Youngdale <eric@andante.org> + * multi.c 1.11 + init struct directory to null + +Sat Dec 6 22:05:05 1997 Eric Youngdale <eric@andante.org> + * mkisofs.h 1.17 + readdir include handling new, *split_SL* new + +Sat Dec 6 22:05:05 1997 Eric Youngdale <eric@andante.org> + * mkisofs.c 1.20 + * mkisofs.8 1.19 + new option -no-split-symlink-fields/-no-split-symlink-components + +Sat Dec 6 22:05:03 1997 Eric Youngdale <eric@andante.org> + * defaults.h 1.5 + SunOS/Solaris switch + +**************** Release 112597 ******************* + +Tue Nov 25 14:09:37 1997 Eric Youngdale <eric@andante.org> + * RELEASE 1.23 + Release 112597 + +Tue Nov 25 14:08:37 1997 Eric Youngdale <eric@andante.org> + * mkisofs.8 1.18 + Release 112597, -quiet option new + +Tue Nov 25 14:08:37 1997 Eric Youngdale <eric@andante.org> + * mkisofs.c 1.19 + verbose levels, -quiet + +Tue Nov 25 14:06:43 1997 Eric Youngdale <eric@andante.org> + * write.c 1.20 + vervose levels + +Tue Nov 25 14:06:42 1997 Eric Youngdale <eric@andante.org> + * joliet.c 1.4 + some bug fixes, handling of reloc dir + +Tue Nov 25 14:06:42 1997 Eric Youngdale <eric@andante.org> + * tree.c 1.20 + * hash.c 1.5 + verbose levels + +**************** Release 112397 ******************* + +Mon Nov 24 03:52:49 1997 Eric Youngdale <eric@andante.org> + * RELEASE 1.22 + Release 112397 + +Mon Nov 24 03:51:49 1997 Eric Youngdale <eric@andante.org> + * multi.c 1.10 + print error messages to stderr + +Mon Nov 24 03:51:49 1997 Eric Youngdale <eric@andante.org> + * joliet.c 1.3 + fixed some bugs that prevented images working on NT, convert to unicode new + +Mon Nov 24 03:51:49 1997 Eric Youngdale <eric@andante.org> + * tree.c 1.19 + put error/debug messages to stderr, INHIBIT_JOLIET_ENTRY new + +Thu Nov 13 06:01:42 1997 Eric Youngdale <eric@andante.org> + * name.c 1.5 + typo fix + +Mon Nov 10 04:27:17 1997 Eric Youngdale <eric@andante.org> + * write.c 1.19 + casting to unsigned char * + +**************** Release 110997 ******************* + +Sun Nov 9 19:56:51 1997 Eric Youngdale <eric@andante.org> + * RELEASE 1.21 + 110997 + +Sun Nov 9 19:55:51 1997 Eric Youngdale <eric@andante.org> + * mkisofs.c 1.18 + getopt_long() codem, graft pointers, struct output_fragment new + +Sun Nov 9 19:55:44 1997 Eric Youngdale <eric@andante.org> + * mkisofs.8 1.17 + Joliet new, Graft pointers new + +Sun Nov 9 19:54:58 1997 Eric Youngdale <eric@andante.org> + * tree.c 1.18 + Joliet handling and graft pointer handling + +Sun Nov 9 19:54:45 1997 Eric Youngdale <eric@andante.org> + * write.c 1.18 + struct output_fragment new, sort goof check new, free unused space, better statistics + +Sun Nov 9 19:54:27 1997 Eric Youngdale <eric@andante.org> + * multi.c 1.9 + correct line length for TRANS.TBL, graft pointer merging code new + +Sun Nov 9 19:43:36 1997 Eric Youngdale <eric@andante.org> + * mkisofs.h 1.16 + struct output_fragment new, some defines for the tree + +Sun Nov 9 19:43:36 1997 Eric Youngdale <eric@andante.org> + * iso9660.h 1.4 + defines for unicode level, PVD ID for Joliet + +Sun Nov 9 19:43:36 1997 Eric Youngdale <eric@andante.org> + * joliet.c 1.2 + first code added + +Sun Nov 9 19:43:36 1997 Eric Youngdale <eric@andante.org> + * Makefile.in 1.13 + joliet.c, getopt*.c new + +Sun Nov 9 19:43:36 1997 Eric Youngdale <eric@andante.org> + * name.c 1.4 + mapping chars > 128 + +Sun Nov 9 19:43:36 1997 Eric Youngdale <eric@andante.org> + * eltorito.c 1.4 + error messages to stderr, struct output_fragement new + +Sun Nov 9 19:43:36 1997 Eric Youngdale <eric@andante.org> + * README 1.6 + Notes for Release 1.12 added + +Thu Nov 6 20:19:25 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.4 + #include <mconfig.h> fuer AIX + +Tue Nov 4 03:27:44 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * getopt.h 1.1 + date and time created 97/11/04 03:27:44 by joerg + +Tue Nov 4 03:27:39 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * getopt1.c 1.1 + date and time created 97/11/04 03:27:39 by joerg + +Tue Nov 4 03:27:32 1997 Eric Youngdale <eric@andante.org> + * getopt.c 1.1 + date and time created 97/11/04 03:27:32 by eric + +Sat Oct 18 19:14:05 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.3 + stdlib.h -> stdxlib.h, unistd.h -> unixstd.h + +Wed Oct 15 07:25:15 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * TODO 1.3 + New list for 1.12 + +**************** Release 1.11.1 ******************* + +Mon Oct 13 05:56:49 1997 Eric Youngdale <eric@andante.org> + * RELEASE 1.20 + * mkisofs.8 1.16 + Release 1.11.1 + +Mon Oct 13 05:55:49 1997 Eric Youngdale <eric@andante.org> + * mkisofs.c 1.17 + Release 1.11.1, let path_table start on correct sector # depending on El Torito or not + +Mon Oct 13 05:46:46 1997 Eric Youngdale <eric@andante.org> + * multi.c 1.8 + better checking for null pointers, USE_SCG code included, type casts for unsigned char * + +Mon Oct 13 05:46:01 1997 Eric Youngdale <eric@andante.org> + * write.c 1.17 + Make local time a structure rahte than a pointer so data will not overwritten, add Joliet support + +Mon Oct 13 05:41:16 1997 Eric Youngdale <eric@andante.org> + * tree.c 1.17 + file renaming code corrected, iso9660_file_length() called correctly (not dir!) for TRANS.TBL + +Mon Oct 13 05:32:57 1997 Eric Youngdale <eric@andante.org> + * mkisofs.h 1.15 + prototypes for readsecs() and scsidev_open() + +Mon Oct 13 05:30:51 1997 Eric Youngdale <eric@andante.org> + * name.c 1.3 + seen_dot new, include '%' to illegal characters + +Mon Oct 13 05:30:21 1997 Eric Youngdale <eric@andante.org> + * rock.c 1.12 + major() autoconf changed + +Mon Oct 13 05:29:40 1997 Eric Youngdale <eric@andante.org> + * eltorito.c 1.3 + Limit publisher ID to 23 chars + +Wed May 21 18:11:25 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * scsi.c 1.2 + scsireg.h Include + +Sat May 17 18:49:03 1997 Eric Youngdale <eric@andante.org> + * joliet.c 1.1 + date and time created 97/05/17 17:49:03 by eric + +Fri May 16 15:46:48 1997 Joerg Schilling <joerg@schily.isdn.cs.tu-berlin.de> + * config.h 1.1 + * scsi.c 1.1 + date and time created 97/05/16 14:46:48 by joerg + +**************** Release 1.11 ******************* + +Thu Apr 10 06:46:21 1997 Eric Youngdale <eric@andante.org> + * RELEASE 1.19 + * RELEASE 1.18 + * mkisofs.8 1.15 + Release 1.11 + +Thu Apr 10 06:43:02 1997 Eric Youngdale <eric@andante.org> + * write.c 1.16 + Check for . and .. entries in dir + +Thu Apr 10 06:41:49 1997 Eric Youngdale <eric@andante.org> + * tree.c 1.16 + Strip off non-significant part of filename + +/*--------------------------------------------------------------------------*/ +The text below is not autogenerated from SCCS comments: + +Wed Nov 5 10:46:29 1997 Andreas Buschmann US/EC4 60/1F/110 #40409 <buschman@lts.sel.alcatel.de> + + Circumvent a bug in the SunOS / Solaris CD-ROM driver (and maybe HP/UX, too). + + * mkisofs.8 (-S): Document switch. + * mkisofs.c (split_SL_field): new Variable, new switch -S. + * mkisofs.h (split_SL_field): new Variable. + * rock.c (generate_rock_ridge_attributes): only split SL field, + when split_SL_field is set. + +Tue Jun 3 15:32:21 1997 Andreas Buschmann <buschman@lts.sel.alcatel.de> + + Circumvent a bug in the SunOS CD-ROM driver (and maybee HP/UX, too). + + * mkisofs.8 (-s): Document switch. + * mkisofs.c (split_SL_component): new Variable, new switch -s. + * mkisofs.h (split_SL_component): new Variable. + * rock.c (generate_rock_ridge_attributes): only split SL + components, when split_SL_component is set. + + * defaults.h: Added SunOS string. + + +Wed Mar 19 16:50:17 1997 Fred Fish <fnf@ninemoons.com> + + * Makefile.in (CFLAGS): Let configure set basic flags. Move + compilation option -c to actual CC commands. + (LDFLAGS): Let configure set basic flags. + (Makefile): Depends upon config.status, not configure. + Regenerate if necessary from Makefile.in using config.status. + (configure): Cd to srcdir before running autoconf. + * acconfig.h: New file to hold nonstandard entries used in + config.h.in. Used by autoheader to generate config.h.in. + * config.h.in: Regenerated with autoheader. + * configure.in: Check for existance of sbrk() function. + * configure: Regenerated with autoconf 2.12. + * fnmatch.c (FMN_FILE_NAME): Define if not already defined. + (FNM_LEADING_DIR): Ditto. + (FNM_CASEFOLD): Ditto. + * mkisofs.c (main): Only use sbrk() if system supports it. + +Fri Mar 14 21:54:37 1997 Eric Youngdale <eric@andante.jic.com> + + * Bump version number to 1.10, public release. + + * Put entire thing under RCS. History is buried there now. + + * Fix bug involving empty directories, translation tables and + malloc(0). + +Mon Feb 17 12:44:03 1997 Eric Youngdale <eric@andante.jic.com> + + * Bump version number to 1.10b7. + + * Makefile.in, configure.in, config.in: Change to use GNU autoconf. + + * Configure: Delete old configuration script. + + * tree.c: Fix bug where we had a rename limit of 1000 files + instead of 0x1000. + + * mkisofs.c: Fix sign of timezone offset. Linux iso filesystem + also need to be fixed, unfortunately. + +Tue Dec 3 22:21:21 1996 Eric Youngdale <eric@sub2317.jic.com> + + Fixed a couple of multi-session bugs. Discs now seem to + work on both Solaris and Windows-NT. + + * Bump version number to 1.10b6. + +Tue Dec 3 22:21:21 1996 Eric Youngdale <eric@sub2317.jic.com> + + Multi-session stuff *almost* there. Discs seem to work + under Linux without any problem, but under DOS only + the first session is seen. The patch to write.c + inspired by disc written by Windows generated multi-session + disc, which will hopefully make the discs usable under + DOS as well. + + * Bump version number to 1.10b5. + + * write.c: use size of new session, not total of all sessions + in volume_space_size field. + + * mkisofs.8: Update with current location of cdwrite. + +Mon Nov 4 23:45:01 1996 Eric Youngdale <eric@sub2317.jic.com> + + * Bump version number to 1.10b4. + + * Add cdwrite.c.diff file, which provides a very crude, minimal + interface between mkisofs and cdwrite. It should be enough to + generate a multi-session disc, but it hasn't been tested yet. + +Thu Oct 17 00:39:52 1996 Eric Youngdale <eric@sub2317.jic.com> + + * Bump version number to 1.10b3. + +Wed Oct 16 23:40:44 1996 Michael Fulbright <msf@redhat.com> + + Add support for 'El Torito' specification which allows for bootable + cdroms. + + * Makefile.in: Add eltorito.[c,o]. + + * defaults.h: Add default settings for El Torito related things. + + * iso9660.h: Add structure definitions for El Torito. + + * mkisofs.8: Document new options. + + * mkisofs.c: Add support for new options related to El Torito. + + * mkisofs.h: Add definitions, prototypes as required. + + * tree.c: Add search_tree_file function to search for a specified + file. + + * write.c: Add support for writing special records for El Torito. + + * eltorito.c: New file. + + +Wed Oct 16 23:40:44 1996 Eric Youngdale <eric@sub2317.jic.com> + + * rock.c: Fix bug whereby we made assumptions about how + dev_t was split into major/minor. Use major() and minor() + macros to do this for us, since each system should + do this correctly. + + * write.c: Fix bug whereby abstract, copyright and appid + strings were not properly filled if application ID weren't + in use. + +Sun Sep 29 10:05:10 1996 Eric Youngdale <eric@sub2317.jic.com> + + * Bump version number to 1.10b2. Minor bug fixes here + and there. + +Sun Sep 15 18:54:05 1996 Eric Youngdale <eric@sub2317.jic.com> + + * Bump version number to 1.10b1. Major new functionality is + support for multi-session. Still a bit preliminary, but + most of the pieces are there now. + +Wed Dec 20 16:44:44 1995 Eric Youngdale (eric@andante.aib.com) + + * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.05. + + * rock.c: Bugfix for cases where sizeof(int) == 4 and + sizeof(dev_t) > 4. + + * rock.c: Bugfix for long symbolic links ('/' characters were + being dropped). + + Patches from Peter Miller <pmiller@agso.gov.au>: + + * mkisofs.8: Documentation fix (some versions of nroff don't + like '.' in column 1 if it is not a nroff command). + + * mkisofs.c: Add support for 'rationalize' option. + Similar to rock ridge, except echos of development environment + are removed. + + * write.c Status indicator now indicates percent finished, and + estimated time of completion. + +Sun Feb 26 01:52:06 1995 Eric Youngdale (eric@largo) + + * Add patches from Ross Biro to allow you to merge arbitrary + trees into the image. This is not compiled in by default but + you need to add -DADD_FILES when compiling. + +Fri Feb 17 02:29:03 1995 Paul Eggert <eggert@twinsun.com> + + * tree.c: Port to Solaris 2.4. Prefer <sys/mkdev.h> if + HASMKDEV. Cast unknown integer types to unsigned long and + print them with %lu or %lx. + +Thu Jan 26 15:25:00 1995 H. Peter Anvin (hpa@yggdrasil.com) + + * mkisofs.c: Substitute underscore for leading dot in non-Rock + Ridge filenames, since MS-DOS cannot read files whose names + begin with a period. + +Mon Jan 16 18:31:41 1995 Eric Youngdale (eric@aib.com) + + * rock.c (generate_rock_ridge_attributes): Only use ROOT + record for symlinks if we are at the start of the symlink. + Otherwise just generate an empty entry. + +Mon Jan 16 16:19:50 1995 Eric Youngdale (eric@aib.com) + + * diag/isodump.c: Use isonum_733 instead of trying to dereference + pointers when trying to decode 733 numbers in the iso9660 image. + + * diag/isovfy.c: Likewise. + + * write.c: Always assign an extent number, even for zero length + files. A zero length file with a NULL extent is apparently dropped + by many readers. + +Wed Jan 11 13:46:50 1995 Eric Youngdale (eric@aib.com) + + * mkisofs.c: Modify extension record to conform to IEEE P1282 + specifications. This is commented out right now, but a trivial + change to a #define enables this. I need to see the specs + to see whether anything else changed before this becomes final. + + * write.c (FDECL4): Fix so that we properly determine error + conditions. + + * mkisofs.h: Change rr_attributes to unsigned. + + * tree.c(increment_nlink): Change pnt since rr_attributes is now + unsigned. + + Ultrix patches from petav@argon.e20.physik.tu-muenchen.de (Peter Averkamp) + + * rock.c: Fix for ultrix systems, we have 64 bit device numbers. + Type cast when generating file size. Change rr_attributes to + unsigned. + + * mkisofs.c: For ultrix systems, define our own function + for strdup. + + * mkisofs.c: Fix usage() since some compilers do not concatenate + strings properly (i.e. ultrix). + + Bugs found with Sentinel II: + + * write.c: Fix a couple of memory leaks. + + * mkisofs.c: Bugfix - always put a zero byte at end of name + for ".." entry. + + * tree.c: Set isorec.date from fstatbuf.st_ctime, not current_time, + since current_time might not be set. + +Sat Dec 3 14:55:42 1994 Eric Youngdale (eric@andante) + + * mkisofs.c: When returning entry for ".." file, set second byte + to 0. + + * write.c: Free name and rr_attributes fields when writing. + +Mon Nov 28 13:36:27 1994 Eric Youngdale (eric@andante) + + * mkisofs.h: Change rr_attributes to unsigned. + + * rock.c: Ditto. Work around >>32 bug in ultrix for 64 bit data types. + + * mkisofs.c (usage): Fix for ultrix - use continuation lines + instead of assuming that strings are catenated by the compiler. + +Mon Jun 20 20:25:26 1994 Eric Youngdale (eric@esp22) + + * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to pre-1.02. + + * mkisofs.h: Fix declaration of e_malloc to use DECL macros. + + * tree.c: Fix bug in previous change. + + * diag/*.c: Add appropriate copyright notices. + +Sat Apr 9 13:30:46 1994 Eric Youngdale (ericy@cais.com) + + * Configure: New file - shell script that determines a bunch of + things to properly build mkisofs. + + * Makefile.in: New file - copy of Makefile, but Configure sets a + few things up for it. + + * tree.c: Do not depend upon opendir to return NULL if we cannot + open a directory - actually try and read the first entry. The + foibles of NFS seem to require this. + + * write.c: Fix definition of xfwrite (Use FDECL4) + + Add some changes to allow more configurability of some of the + volume header fields: + + * mkisofs.8: Document new configuration options. + + * mkisofs.c: Add variables to hold new fields. Add function to + read .mkisofsrc files. + + * defaults.h: Another way of configuring the same things. + + Add some changes from Leo Weppelman leo@ahwau.ahold.nl. + + * mkisofs.c: Allow -A to specify application ID. Fix usage(), + getopt and add case switch. + + * rock.c: Fix handling of device numbers (dev_t high should only + be used when sizeof(dev_t) > 32 bits). + + Add a bunch of changes from Manuel Bouyer. + + * diag/Makefile: New file. + + * diag/dump.c, diag/isodump.c: Use termios if system supports it. + + * (throughout): Replace all occurences of "malloc" with e_malloc. + + * mkisofs.c: For NetBSD, attempt to increase the rlimit for + the size of the data segment to about 33 Mb. + + * mkisofs.c (e_malloc): New function. Calls malloc, and prints + nice error message and exits if NULL is returned. + +Sun Jan 23 19:23:57 1994 Eric Youngdale (eric@esp22) + + * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.01. + + Add a bunch of stuff so that mkisofs will work on a VMS system. + + * (ALL): Change any direct use of the "st_ino" field from + the statbuf to use a macro. + + * mkisofs.h: Define appropriate macros for both VMS and unix. + + * (ALL): Add type casts whenever we use the UNCACHED_DEV macro. + + * rock.c: Wrap a #ifndef VMS around block and character device + stuff. + + * write.c: Add prototype for strdup if VMS is defined. + + * make.com: Script for building mkisofs on a VMS system. + + * Makefile: Include make.com in the distribution. + + * mkisofs.c: Include <sys/type.h> on VMS systems. + + * tree.c: Include <sys/file.h> and "vms.h" on VMS systems. + + * mkisofs.h (PATH_SEPARATOR, SPATH_SEPARATOR): New macros + that define the ascii character that separates the last directory + component from the filename. + + * tree.c, mkisofs.c: Use them. + + * vms.c: New file. Contains version of getopt, strdup, opendir, + readdir and closedir. + + * vms.h: New file. Defines S_IS* macros. Define gmtime as + localtime, since gmtime under VMS returns NULL. + +Sat Jan 15 13:57:42 1994 Eric Youngdale (eric@esp22) + + * mkisofs.h (transparent_compression): New prototype. + + * mkisofs.c (transparent_compression): Declare, use + '-z' option to turn on. + + * tree.c: Change TRANS.TBL;1 to TRANS.TBL (version gets + added later, if required). + + * rock.c: If transparent compression requested, verify + file is really suitable (check magic numbers), and extract + correct file length to store in SUSP record. + +Sat Jan 15 01:57:42 1994 Eric Youngdale (eric@esp22) + + * write.c (compare_dirs): Bugfix for patch from Jan 6. + + * mkisofs.h (struct directory_entry): Add element total_rr_attr_size. + (struct file_hash): Add element ce_bytes. + + * write.c (iso_write): Update last_extent_written, as required, + and check it against last_extent as a sanity check. + (generate_one_directory): If ce_bytes is non-zero, allocate + a buffer and fill it with the CE records. Also, update + the extent and offset entries in the CE SUSP field and + output after directory is written. + (assign_directory_addresses): Allow for CE sectors after each + directory. + + * tree.c (sort_n_finish): Set field ce_bytes by summing + the sizes of all CE blocks in each files RR attributes. + Do not count these bytes for main directory. + + * rock.c (generate_rock_ridge_attributes): Generate + CE entries to break up large records into manageable sizes. + Allow long names to be split, and allow long symlinks to be split. + Allow splitting before each SUSP field as well, to make + sure we do not screw outselves. + +Thu Jan 6 21:47:43 1994 Eric Youngdale (eric@esp22) + + Bugfix. + + * write.c (compare_dirs): Only compare directory names up to + the ';' for the version number. + + Add four new options: (1) Full 31 character filenames, + (2) Omit version number, (3) Omit trailing period from filenames, + (4) Skip deep directory relocation. + + * iso9660.h: Allow 34 characters for filename. + + * mkisofs.8: Update for new options. + + * mkisofs.c: Add flag variables for new options. + Mention new options in usage(), tell getopt about + new options, and set appropriate flags when + new options are specified. + + * mkisofs.c (iso9660_file_length): Implement new options. + + * mkisofs.h: Declare flag variables for new options. + + * tree.c (sort_n_finish): Increase declaration of newname and + rootname to 34 characters. If full_iso9660_filenames in effect, + use different rules for making unique names. + + * tree.c (scan_directory_tree): Use RR_relocation_depth instead of + constant for threshold for starting deep directory relocation. + +Wed Jan 5 01:32:34 1994 John Brezak (brezak@ch.hp.com) + + * Makefile.bsd: New file. For NetBSD. + + * rock.c, tree.c: Do not include sys/sysmacros.h for NetBSD. + +Fri Dec 31 13:22:52 1993 Eric Youngdale (eric@esp22) + + * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.00. + + * tree.c (scan_directory_tree): Handle case where we do not + have permissions to open a directory. + + * write.c (xfwrite): New function - wrapper for fwrite, + except that we print message and punt if write fails. + + * write.c: Move include of mkisofs.h and iso9660.h until after + string.h and stdlib.h is included. + + * write.c: Do not attempt to use strerror on sun systems. + +Thu Dec 9 13:17:28 1993 R.-D. Marzusch (marzusch@odiehh.hanse.de) + + * exclude.c, exclude.h: New files. Contains list of files to + exclude from consideration. + + * Makefile: Compile exclude.c, add dependencies to other files. + + * mkisofs.8: Describe -x option. + + * mkisofs.c: Include exclude.h, handle -x option. + + +Fri Dec 10 01:07:43 1993 Peter van der Veen (peterv@qnx.com) + + * mkisofs.c, mkisofs.h: Moved declaration of root_record. + + * mkisofs.h: Added prototype for get_733(). + + * write.c(iso_write), tree.c, rock.c(generate_rock_ridge_attributes): + Added defines for QNX operation system + + * rock.c(generate_rock_ridge_attributes): symbolic links should + not have CONTINUE component flag set unless there are multiple + component records, and mkisofs does not generate these. + st_ctime was stored as the creation time, changed to attribute time. + QNX has a creation time, so that is stored as well under QNX. + +Thu Oct 28 19:54:38 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.99. + + * write.c(iso_write): Put hour, minute, second into date fields in + volume descriptor. + + * write.c (iso_write): Set file_structure_version to 1, instead of + ' ' (Seems to screw up Macs). + +Sun Oct 17 01:13:36 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.98. + + Increment nlink in root directory when rr_moved directory is present. + + * tree.c (increment_nlink): New function. + + * tree.c (finish_cl_pl_entries): Call increment_nlink for all + references to the root directory. + + * tree.c (root_statbuf): New variable. + + * tree.c (scan_directory_tree): Initialize root_statbuf when we + stat the root directory. + + * tree.c (generate_reloc_directory): Use root_statbuf when + generating the Rock Ridge stuff for the ".." entry in the + reloc_dir. + + * tree.c (scan_directory_tree): Use root_statbuf when generating + the ".." entry in the root directory. + +Sat Oct 16 10:28:30 1993 Eric Youngdale (eric@kafka) + + Fix path tables so that they are sorted. + + * tree.c (assign_directory_addresses): Move to write.c + + * write.c (generate_path_tables): Create an array of pointers to + the individual directories, and sort it based upon the name and + the parent path table index. Then update all of the indexes and + repeat the sort until the path table indexes no longer need to be + changed, and then write the path table. + + Fix problem where hard links were throwing off the total extent count. + + * write.c (iso_write): Call assign_file_addresses, and then + use last_extent to determine how big the volume is. + + * write.c (generate_one_directory): Decrement n_data_extents + for hard links to non-directories so that the expected number + of extents is written correctly. + + * write.c(assign_file_addresses): New function. + +Fri Oct 15 22:35:43 1993 Eric Youngdale (eric@kafka) + + The standard says we should do these things: + + * tree.c (generate_reloc_directory): Add RR attributes to + the rr_moved directory. + + * mkisofs.c(main): Change ER text strings back to recommended + values. + +Tue Oct 12 21:07:38 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.97. + + * tree.c (scan_directory_tree): Do not insert PL entry into + root directory record (i.e. !parent) + + * tree.c (finish_cl_pl_entries): Do not rely upon name + comparison to locate parent - use d_entry->self instead, + which is guaranteed to be correct. + + * mkisofs.h: New variable n_data_extents. + + * tree.c: Declare and initialize n_data_extents to 0. + (scan_directory_tree) for non-directories, add + ROUND_UP(statbuf.st_size) to n_data_extents. + (sort_n_finish): Increment n_data_extents for translation tables, + as appropriate. + + * write.c(iso_write): Add n_data_extents to the + volume_space_size field. + + * hash.c(add_hash): If size != 0 and extent == 0, or + if size == 0 and extent != 0, then complain about + inserting this into the hash table. Kind of a sanity check. + +Sat Oct 9 16:39:15 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.96. + + Numerous bugfixes, thanks to a one-off disc from rab@cdrom.com. + + * write.c(generate_one_directory): Wait until after we have + filled in the starting_extent field to s_entry before calling + add_hash. This fixes a problem where the hash table gets an + extent of 0 for all regular files, and this turns up when you have + hard links on the disc. (The hash table allows us to have each + hard link point to the same extent on the cdrom, thereby saving + some space). + + * tree.c(scan_directory_tree): Set statbuf.st_dev and + statbuf.st_ino to the UNCACHED numbers for symlinks that we + are not following. This prevents the function find_hash from + returning an inode that cooresponds to the file the symlink points + to, which in turn prevents generate_one_directory from filling in + a bogus file length (should be zero for symlinks). + + * tree.c(scan_directory_tree): Always call lstat for the file + so that non-RockRidge discs get correct treatment of symlinks. + Improve error message when we ignore a symlink on a non-RR disc. + + * write.c(generate_one_directory): Set fields for starting_extent + and size in the "." and ".." entries before we add them to the + file hash. Fixes problems with incorrect backlinks for second + level directories. + +Wed Oct 6 19:53:40 1993 Eric Youngdale (eric@kafka) + + * write.c (write_one_file): Print message and punt if we are + unable to open the file. + + * tree.c(scan_directory_tree): For regular files, use the access + function to verify that the file is readable in the first place. + If not, issue a warning and skip it. For directories, it probably + does not matter, since we would not be able to descend into them + in the first place. + +Wed Sep 29 00:02:47 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.95. + + * write.c, tree.c: Cosmetic changes to printed information. + + * tree.c(scan_directory_tree): Set size to zero for + special stub entries that correspond to the + relocated directories. Hopefully last big bug. + + * mkisofs.h: Change TABLE_INODE, UNCACHED_* macros + to be 0x7fff... to be compatible with signed datatypes. + +Mon Sep 27 20:14:49 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.94. + + * write.c (write_path_tables): Actually search the + directory for the matching entry in case we renamed + the directory because of a name conflict. + + * tree.c(scan_directory_tree): Take directory_entry pointer + as second argument so that we can create a backpointer + in the directory structure that points back to the original + dir. + + * mkisofs.c: Fix call to scan_directory_tree to use new calling + sequence. + + * write.c(generate_one_directory): Punt if the last_extent counter + ever exceeds 700Mb/2048. Print name of responsible file, + extent counter, and starting extent. Perhaps we can catch it in + the act. + +Sun Sep 26 20:58:05 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.93. + + * tree.c(scan_directory_tree): Handle symlinks better. Either + leave them as symlinks, or erase any trace that they were a + symlink but do not do it 1/2 way as before. Also, watch for + directory loops created with symlinks. + + * mkisofs.h: Add new flag follow_links. + + * mkisofs.c: Add command line switch "-f" to toggle follow_links. + + * mkisofs.8: Document new switch. + + * tree.c: Add code to handle symlinks using new flag. + + * hash.c: Add add_directory_hash, find_directory_hash functions. + + * mkisofs.h: Add prototypes. + +Sat Sep 25 14:26:31 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.92. + + * mkisofs.c: Make sure path is an actual directory before trying + to scan it. + + * mkisofs.h: Add DECL and FDECL? macros for sparc like systems. + Do proper define of optind and optarg under SVr4. + + * tree.c: Change translation table name from YMTRANS.TBL to TRANS.TBL. + + * mkisofs.c: Neaten up message in extension record when RRIP is + in use. + + * Throughout - change all function declarations so that + traditional C compilers (i.e. sparc) will work. + + * Makefile: Change to use system default C compiler. + + * mkisofs.c: Add some stuff so that this will compile under VMS. + Many things missing for VMS still. + + * iso9660.h: Do not use zero length array in struct definition. + + * tree.c (sort_n_finish): Account for this. + + * Change copyright notice. + + +Wed Aug 25 08:06:51 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.91. + + * mkisofs.h: Only include sys/dir.h for linux. Other systems + will need other things. + + * mkisofs.c, tree.c: Include unistd.h. + + * Makefile: Use OBJS to define list of object files. + +Sun Aug 22 20:55:17 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.9. + + * write.c (iso_7*): Fix so that they work properly on Motorola + systems. + +Fri Aug 20 00:14:36 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.8. + + * rock.c: Do not mask off write permissions from posix file modes. + +Wed Aug 18 09:02:12 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.7. + + * rock.c: Do not write NM field for . and .. (redundant and a + waste of space). + + * mkisofs.c: Take -P and -p options for publisher and preparer id + fields. + + * write.c: Store publisher and preparer id in volume + descriptor. + + * rock.c: Write optional SP field to identify SUSP. Write + optional CE field to point to the extension header. + + * tree.c: Request SP and CE fields be added to root directory. + + * tree.c: Fix bug in name conflict resolution. + + * write.c: Fill in date fields in the colume descriptor. + + * write.c (write_one_file): If the file is large enough, write in + chunks of 16 sectors to improve performance. + + * hash.c (add_hash, find_hash, etc): Do not hash s_entry, instead + store relevant info in hash structure (we free s_entry structs as + we write files, and we need to have access to the hash table the + whole way through. + + * write.c: Add a few statistics about directory sizes, RR sizes, + translation table sizes, etc. + + * tree.c: Use major, not MAJOR. Same for minor. Define S_ISSOCK + and S_ISLNK if not defined. + + * rock.c: Define S_ISLNK if not defined. + + * mkisofs.c: Print out max memory usage. Fix bug in call to getopt. + + * mkisofs.c, Makefile (version_string): Bump to 0.6. + + * tree.c: Simplify the calculation of isorec.len, isorec.name_len + and the calculation of the path table sizes by doing it all at + one point after conflict resolution is done. + + * tree.c: scan_directory_tree is now responsible for generating + the line that goes into the YMTRANS.TBL file. These lines are + collected later on into something that will be dumped to the + file. Correctly handle all of the special file types. + +Mon Aug 16 21:59:47 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.5. + + * mkisofs.c: Add -a option (to force all files to be + transferred). Remove find_file_hash stuff. + + * write.c: Pad length even if Rock Ridge is not in use. + + * hash.c: Rewrite hash_file_* stuff so that it can be used to + easily detect (and look up) filenames that have been accepted + for use in this directory. Used for name collision detection. + + * tree.c (sort_n_finish): If two names collide, generate a unique + one (verified with the hash routines). Change the lower priority + name if there is a difference. + + + +Sat Aug 14 13:18:21 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.4. + + * tree.c (load_translation_table): New function - read + YMTRANS.TBL. (scan_directory_tree) Call it. + + * mkisofs.c (iso9660_file_length): Call find_file_hash to see + if translated name is specified. If so, use it. + + * hash.c (name_hash, add_file_hash, find_file_hash, + flush_file_hash): New functions for hashing stuff from + YMTRANS.TBL. + + * mkisofs.h: Add a bunch of prototypes for the new functions. + + * mkisofs.8: Update. + + * mkisofs.c, Makefile (version_string): Bump to 0.3. + + * Makefile: Add version number to tar file in dist target. + + * mkisofs.c: Call finish_cl_pl_entries() after directories have + been generated, and extent numbers assigned. + + * write.c (generate_one_directory): Update s_entry->size for + directories (as well as isorec.size). + + * rock.c: Add code to generate CL, PL, and RE entries. The + extent numbers for the CL and PL entries are NULL, and these + are filled in later once we know where they actually belong. + + * mkisofs.h: Add parent_rec to directory_entry. Used to fix CL/PL + stuff. + + * tree.c (scan_directory_tree): Set flag to generate CL/PL/RE + entries as required, update sizes as well. + +Fri Aug 13 19:49:30 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c (version_string): Bump to 0.2. + + * hash.c: Do not use entries with inode == 0xffffffff or dev == + 0xffff. + + * write.c (write_path_tables): Strip leading directory specifications. + + * mkisofs.h: Add definition for reloc_dir symbol. Add prototype + for sort_n_finish, add third parameter to scan_directory_tree + (for true parent, when directories are relocated). + + * mkisofs.c (main): Modify call to scan_directory_tree. Call + sort_n_finish for reloc_dir. + + * tree.c (sort_n_finish): New function - moved code from + scan_directory_tree. + + * tree.c (generate_reloc_directory): New function. Generate + directory to hold relocated directories. + + * tree.c (scan_directory_tree): Strip leading directories when + generating this_dir->name. If depth is too great, then move + directory to reloc_dir (creating if it does not exist, and leave + a dummy (non-directory) entry in the regular directory so that + we can eventually add the required Rock Ridge record. + + * tree.c (scan_directory_tree): Use s_entry instead of sort_dir, + assign to this_dir->contents sooner. + +Thu Aug 12 22:38:17 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c (usage): Fix syntax. + + * mkisofs.c (main): Add new argument to scan_directory_tree + + * tree.c (scan_directory_tree): If directory is at depth 8 or + more, create rr_moved directory in main directory. + +Mon Jul 26 19:45:47 1993 Eric Youngdale (eric@kafka) + + * mkisofs v 0.1 released. + diff --git a/genisoimage/ChangeLog.mkhybrid b/genisoimage/ChangeLog.mkhybrid new file mode 100644 index 0000000..e641d96 --- /dev/null +++ b/genisoimage/ChangeLog.mkhybrid @@ -0,0 +1,482 @@ +Mon May 1 14:51:00 BST 2000 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.13a01 + + mkhybrid has now been merged with, and is now part of mkisofs + +Wed Apr 26 10:18:44 BST 2000 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12.1a10 + + The -icon-position will now attempt to preserve folder window + positions, scroll bars, views etc. for Apple/Unix file formats + that support this information (currently CAP, EtherShare, Netatalk) + + Added -root-info option - which works with the -icon-position + option to preserve the root folder window characteristics. + See README.rootinfo for more about this option. + + Added 'mac-roman' to the -jcharset option. Converts Macintosh + Roman file name characters to the correct Joliet characters. + +Tue Apr 18 14:06:00 BST 2000 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12.1a07 + + HFS files/directories are made invisible (HFS_FNDR_ISINVISIBLE + flag set) if the ISO file/directory is hidden. + +Mon Apr 3 22:04:00 BST 2000 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12.1a05 + + Custom HFS volume or folder icons are now recoginised + +Sun Mar 19 19:12:00 GMT 2000 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12.1a03 + + New options -hfs-type & -hfs-creator + +Wed Mar 8 11:26:00 GMT 2000 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12 + + Final release of mkhybrid v1.12 + + mkhybrid will now be integrated with the cdrecord package (see: + ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/alpha) + + +Wed Feb 23 14:35:20 GMT 2000 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12b6.0 + + Now based on mkisofs v1.12 available as part of the cdrecord + package from ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ + + Will now create an HFS volume of at least 800k in size. + + Added option to preserve the HFS icon position (if it exists) + from a Apple/Unix file. Use -icon-position (Alpha) + +Thu Nov 25 19:59:27 GMT 1999 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12b5.4 + + Added partial support for Microsoft's "Services for Macintosh" + format files. See the man page for details. + + mkhybrid no longer tries to work out the "disk cluster size" + for use with Apple File Exchange. The disk cluster size now needs + to be given on the command line (-cluster-size). The code involved + was not portable across various operating systems. + + Added minor changes for Rhapsody and BeOS. + + Cleaned up the code in apple.c (thanks to Ed Randall + <ed_randall@yahoo.com>). + + mkhybrid will now create a valid HFS partition as the last session + on a multisession CD. (Alpha) + +Sun Aug 8 10:36:15 BST 1999 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12b5.3 + + Changed the nature of the -hfs and -apple command line options - + see README.mkhybrid for details + + Added PReP boot option from Troy Benjegerdes - see README.prep_boot + + Added support for AppleDouble/Single file names as "Pascal Strings" + + Added checks for Joliet and Rock Ridge filename clashes. + + Fixed minor install bug in Makefile.in + +Tue Apr 30 21:33:39 BST 1999 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12b5.2 + + Fixed bug where CREATOR/TYPE not padded with spaces if less + than 4 characters + + Added support for "DAVE" format files (and AppleDouble v2) + use --dave + + Fixed a small signed char bug in name.c + + Fixed bug in diag/isoinfo.c - didn't support UCS level 1 + filenames that mkisofs/mkhybrid now creates with the -J option. + + +Thu Apr 7 20:29:04 BST 1999 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12b5.1 + + Fixed bugs with MacBinary names and symbolic links to HFS files + when using the -f option + + Re-introduced some minor changes "lost" from v1.12b4.8 + + Forgot to add -hide-hfs-list option in previous version ... + +Tue Mar 30 08:31:13 BST 1999 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12b5.0 + + Now based on mkisofs v1.12b5 + + Option -mac-name now only uses the HFS name if the file is one + of the known HFS file types + + Added -hide-list, -hide-joliet-list, -hide-hfs-list, -exclude-list + and -path-list options. Allows a list of filenames to be excluded or + hidden to be given in a file instead of on the command line. + + Added option -hfs-volid to give the HFS volume its own name (not + using the ISO9660 volume name). + + +Tue Jan 5 15:44:24 GMT 1999 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12b4.8 + + Fixed an AppleDouble bug and added better support for more Unix + flavours. + + Fixed -hide-hfs bug that corrupted some HFS hidden files + + Made the verbose output less verbose. + + Added initial support for the AutoStart feature. + + HFS partition maps can now be added without having to create + a bootable HFS CD (as pre-v1.12a4.7). + + Added option to specify the PC Exchange "cluster size". + +Mon Aug 24 23:18:38 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a4.7 + + Fixed SGI/XINET and PC Exchange bugs + + By default, the output image no longer has an HFS partition map + (as pre-v1.12a3.4). Partition maps are only added if making a + bootable HFS CD + + Fixed possible bug with odd-length structure alignment with gcc on + some architectures + +Tue Aug 4 23:09:17 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a4.6 + + Made a couple of Netatalk changes + + Altered way Apple/Unix associated files are excluded - e.g. + if just --cap is selected, then files associated with the other + Apple/Unix encodings are processed as normal files. Previously they + would have been ignored + + Added option (-no-desktop) to prevent the (empty) HFS desktop files + being created. These will be created when the CD is used on a + Macintosh (and stored in the System Folder). + +Sun Jul 26 09:44:50 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a4.5 + + Fixed serious bug that could cause corrupt output when used with + the -J option + +Tue Jul 21 14:33:20 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a4.4 + + HFS file/directory names that share the first 31 characters have + '_N' (N == decimal number) substituted for the last few characters + to generate unique names. + + 1 year since the first release ... + +Sat Jul 11 12:57:04 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a4.3 + + Added options to "hide" (options -hide and -hide-joliet) files + or directories from the ISO9660/RockRidge and/or Joliet directory + trees. + + Renamed the -hfs-exclude option to -hide-hfs to be compatible + with the above options. + + Fixed a bug with the -hide-hfs option (very rare case ...) + +Thu Jun 25 20:02:20 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a4.2 + + Fixed an HFS bug introduced with v1.12a3.4 that created some + corrupt HFS volumes over about 400Mb + + Tighten up checking for MacBinary files to prevent false matches + +Sun Jun 21 11:55:09 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a4.1 + + Default TYPE and CREATOR can now be set via the .mkisofsrc file + + Order of magic and mapping file on the command line is now + important. This defines the order in which TYPE and CREATOR are set. + + Apple/Unix file types found are logged as part of the verbose output + (need to give -v twice) + + Added option (-log-file) to redirect stderr messages + + Added option (-hfs-exclude) to exclude files/directories from + the HFS part of the CD. + + Fixed a couple of MacBinary/AppleSingle bugs. + +Thu Jun 8 23:40:56 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a4.0 + + Resource fork file names not added to TRANS.TBL + + Re-enabled support of non-regular Win32 files. GNU-Win32 can + create symbolic links etc. These are now recognised. + + mkhybrid man page added. + + Based on mkisofs v1.12b4 + +Wed May 20 12:54:36 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a3.5 + + Added support for using a "magic" file to set CREATOR/TYPE for + a file - see README.hfs_magic for details. + +Mon May 18 16:22:32 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a3.4 + + Added possible support for bootable Mac CDs - see README.hfs_boot + or details. + + Fixed -x bug (mkisofs v1.12 bug) + +Mon May 4 14:23:46 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a3.3 + + Added support for UShare Mac/Unix files + + Individual Mac/Unix file types can now be selected instead + of searching for all possible types. See README.mkhybrid for + details. + +Fri May 1 10:34:29 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a3.2 + + Various bug fixes to Mac file names + +Tue Mar 10 14:42:03 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a3.1 + + Added -no-hfs-files option that assumes there are no Unix/Mac + files (CAP, Netatalk, etc) - speeds up processing in these cases + + Case insensitive HFS file/folder names that are the same are now + allowed - one or more '_' characters are added to one or more of + the filenames. + + (Changed -macname option to -mac-name option) + +Mon Feb 23 16:09:27 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a3.0 + + Based on mkisofs v1.12b3 + + Fixed serious HFS bug that crept in from v1.11 -> v1.12 + +Tue Feb 17 16:20:12 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a2.0 + + Based on mkisofs v1.12b2 + + Improved Win32 support: using -r now makes all files executable + when run under Win95/NT4 + +Tue Feb 3 10:30:18 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a1.2 + + Fixed memory bug when used without any HFS options + + Improved PC Exchange support (although still needs testing) + +Tue Jan 27 10:32:26 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a1.1 + + Can now handle multiple hard linked source files with the -hfs option + (multiple hard linked source files are handled as separate files) + + configure script changed to check for ranlib + + Fixed a couple of AppleSingle bugs. + + Added option to use Mac names as starting point for ISO9660, Joliet + and RockRidge names + +Wed Jan 21 14:00:56 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.12a1 + + See README.mkhybrid for details + +Fri Jan 16 17:09:48 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 1.11 + + Changed version numbering to be the same as mkisofs + + Code no longer considered beta level + + Minor changes to allow the code to be complied and run + on Win95/NT using Cygnus' GNU-Win32 (available from + http://www.cygnus.com/misc/gnu-win32/) + +Thu Dec 4 17:17:45 GMT 1997 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 0.49b + + Fixed an HFS bug that caused a failure with directory names that + had special AUFS characters + + Fixed mkisofs bug in eltorito.c that wrote warning messages + to stdout not stderr + + Code no longer considered alpha level + +Thu Nov 27 19:00:02 GMT 1997 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 0.48a + + Added Apple's extensions to ISO9660 that can be used instead of + the HFS options (see README.mkhybrid for more details). + + Added more verbose HFS error messages. + + Changed the Joliet option flag to -J (-j still works) to be + compatible the with next release of mkisofs (v1.12) + +Wed Oct 15 11:16:21 BST 1997 James Pearson <j.pearson@ge.ucl.ac.uk> + + Version 0.47a + + Fixed bug that prevented volume_space_size not being set in the + PVD (or SVD) + +Mon Oct 6 15:46:24 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk> + + Version 0.46a + + Small Joliet bug fix - source directories that are not readable + are set to empty ordinary files in the ISO9660 filesystem - this + is now true for the Joliet directory (partially responsible + for NT4 having problems with CDs where this happened) + + Minor documentation updates. + +Mon Sep 15 14:15:11 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk> + + Version 0.45a + + Attempt to prevent the HFS Catalog file growing (see + "Implementation" in README.mkhybrid for more details) + This is only likely to be a problem where folders have lots + of small files. + +Mon Aug 18 12:00:24 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk> + + Version 0.44a + + If the directories were deeper than 8 and the -D flag was not + used, then the "rr_moved" directory was not added to the Joliet + directory tree. This has now been fixed - but one day, the deep + Joliet directories may not have to be relocated ... + + Fixed memcmp problem with possible uninitialised memory in + j_compare_paths(), which *might* cause incorrect Joliet directory + sort order + +Wed Aug 13 14:58:56 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk> + + Version 0.43a + + Fixed bug for incorrect Joliet path table size + + Fixed some old minor mkisofs bugs (TRANS.TBL not having a + version number by default and incorrect date in the PVD). + +Mon Aug 11 17:17:07 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk> + + Version 0.42a + + Now will not try to create the HFS "Desktop DB" and "Desktop DF" + if they already exist when used with the HFS options. + + Fixed a serious bug in the hfs code that truncated some files. + + "TRANS.TBL" was missed out of the Joliet directory if the -T + option was given (previously an empty file with no name was used + which could cause problems on NT 4) + +Fri Aug 8 10:19:46 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk> + + Version 0.41a + + Fixed bug which created invalid HFS/ISO9660 volumes if the -j (Joliet) + option was not used + +Mon Aug 4 15:08:43 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk> + + Version 0.4a + + Added (partial?) Joliet support. + + Now based on mkisofs v1.11 + +Tue Jul 29 11:57:14 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk> + + Version 0.32a + + Allocation sizes improved to cut down on wasted space. Now uses + the HFS "allocation" size rounded up to the nearest 2048 bytes. + Savings can be significant with a large volume containing lots + of smallish files. + +Wed Jul 23 15:36:08 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk> + + Version 0.31a + + Deep directories (greater than RR_relocation_depth) cause core + dump in "copy_to_mac_volume" as the relocated directory was not + marked as an HFS folder. Fixed by putting deep HFS folders in + their correct location. + +Mon Jul 21 15:50:05 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk> + + Version 0.3a, first public release. diff --git a/genisoimage/RELEASE b/genisoimage/RELEASE new file mode 100644 index 0000000..c547f6e --- /dev/null +++ b/genisoimage/RELEASE @@ -0,0 +1,3 @@ +# @(#)RELEASE 1.35 04/09/09 joerg + +Release 2.01 diff --git a/genisoimage/TODO b/genisoimage/TODO new file mode 100644 index 0000000..cce3b24 --- /dev/null +++ b/genisoimage/TODO @@ -0,0 +1,57 @@ +/* @(#)TODO 1.6 03/04/27 joerg */ + 1) Finish multiple paths. Update nlink count on directories if it is + different than what stat returned. Save the nlink count that we store in + the rock ridge attributes so know when we don't have to adjust it. + + +Andy Polyakov <appro@fy.chalmers.se> +Well, it was rather hard to get it wrong... But the answer is "yes" if +you have to hear this very word. + +And while we're discussing this code. A *cosmetic* *suggestion*. +Consider modifying two lines above the "if(is_directory)" as following: + + set32(&fe->uid,0); + set32(&fe->gid,0); + +or to any other small number. Problem is that with -1 as now 'ls -l' +results in wider output which is rather annoying (it has to print +4294967295 twice while it formats for 8 chars). + +Cheers. A. + +/*--------------------------------------------------------------------------*/ + +Option to modify Volume id, ... in PVD after the image has been +created? + +/*--------------------------------------------------------------------------*/ +http://www.y-adagio.com/public/standards/iso_cdromr/tocont.htm + +Annex B has: + +Changes from ISO 9660:1988 to this International Standard: + +a) The Volume Descriptor Version is changed to indicate the new structure; + Version number 2 indicated the new specification. +b) The File Structure Version is changed to indicate the new structure; + Version number 2 indicated the new specification. +c) The limitation in the Depth of Hierarchy is lifted; + The levels in the hierarchy can exceed eight. +d) The File Identifier is not separated to components; + The SEPARATORS are not specified. + A complex file name can be expressed. +e) The File Identifier does not have File Version Numbers; + File with and without Version Numbers should not exist in the same directory. +f) The character used for filling byte positions which are specified to be characters is subject to agreement +between the originator and the recipient of the volume; +g) The length of File Identifier is limited to 207; + Long file name can be expressed. +h) The length of a Directory Identifier is limited to 207; + Long directory name can be expressed. +/*--------------------------------------------------------------------------*/ + +Extent # auch als off_t statt int + +Wenn HFS, dann max File size == 2 GB? + diff --git a/genisoimage/apple.c b/genisoimage/apple.c new file mode 100644 index 0000000..3939504 --- /dev/null +++ b/genisoimage/apple.c @@ -0,0 +1,2688 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)apple.c 1.19 04/03/02 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */ +/* + * Copyright (c) 1997, 1998, 1999, 2000 James Pearson + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Unix-HFS file interface including maping file extensions to TYPE/CREATOR + * + * Adapted from mkhfs routines for mkhybrid + * + * James Pearson 1/5/97 + * Bug fix JCP 4/12/97 + * Updated for 1.12 and added more Unix HFS filetypes. JCP 21/1/98 + * Tidy up to use Finfo and Dinfo for all formats where + * possible JCP 25/4/2000 + * + * Things still to de done: + * + * Check file size = finder + rsrc [+ data] is needed + */ + +#ifdef APPLE_HYB + +#include <mconfig.h> +#include "genisoimage.h" +#include <errno.h> +#include <fctldefs.h> +#include <utypes.h> +#include <ctype.h> +#include <netinet/in.h> +#include "apple.h" +#include <schily.h> + +#ifdef USE_MAGIC +#include <magic.h> +magic_t magic_state = NULL; +#ifndef MAGIC_ERROR +/* workaround for older ´API */ +#define MAGIC_ERROR 0 +#endif +#endif /* USE_MAGIC */ + +/* tidy up genisoimage definition ... */ +typedef struct directory_entry dir_ent; + +/* routines for getting HFS names and info */ +#ifndef HAVE_STRCASECMP +static int strcasecmp(const char *s1, const char *s2); +#endif +static int get_none_dir(char *, char *, dir_ent *, int); +static int get_none_info(char *, char *, dir_ent *, int); +static int get_cap_dir(char *, char *, dir_ent *, int); +static int get_cap_info(char *, char *, dir_ent *, int); +static int get_es_dir(char *, char *, dir_ent *, int); +static int get_es_info(char *, char *, dir_ent *, int); +static int get_dbl_dir(char *, char *, dir_ent *, int); +static int get_dbl_info(char *, char *, dir_ent *, int); +static int get_mb_info(char *, char *, dir_ent *, int); +static int get_sgl_info(char *, char *, dir_ent *, int); +static int get_fe_dir(char *, char *, dir_ent *, int); +static int get_fe_info(char *, char *, dir_ent *, int); +static int get_sgi_dir(char *, char *, dir_ent *, int); +static int get_sgi_info(char *, char *, dir_ent *, int); +static int get_sfm_info(char *, char *, dir_ent *, int); + +#ifdef IS_MACOS_X +static int get_xhfs_dir(char *, char *, dir_ent *, int); +static int get_xhfs_info(char *, char *, dir_ent *, int); +#else +#define get_xhfs_dir get_none_dir +#define get_xhfs_info get_none_info +#endif /* IS_MACOS_X */ + +static void set_ct(hfsdirent *, char *, char *); +static void set_Dinfo(byte *, hfsdirent *); +static void set_Finfo(byte *, hfsdirent *); +static void cstrncpy(char *, char *, int); +static unsigned char dehex(char); +static unsigned char hex2char(char *); +static void hstrncpy(unsigned char *, char *, int); +static int read_info_file(char *, void *, int); + +/*static unsigned short calc_mb_crc __PR((unsigned char *, long, unsigned short));*/ +static struct hfs_info *get_hfs_fe_info(struct hfs_info *, char *); +static struct hfs_info *get_hfs_sgi_info(struct hfs_info *, char *); +static struct hfs_info *match_key(struct hfs_info *, char *); + +static int get_hfs_itype(char *, char *, char *); +static void map_ext(char *, char **, char **, short *, char *); + +static afpmap **map; /* list of mappings */ +static afpmap *defmap; /* the default mapping */ +static int last_ent; /* previous mapped entry */ +static int map_num; /* number of mappings */ +static int mlen; /* min extension length */ +static char tmp[PATH_MAX]; /* tmp working buffer */ +static int hfs_num; /* number of file types */ +static char p_buf[PATH_MAX]; /* info working buffer */ +static FILE *p_fp = NULL; /* probe File pointer */ +static int p_num = 0; /* probe bytes read */ +static unsigned int hselect; /* type of HFS file selected */ + +struct hfs_type { /* Types of various HFS Unix files */ + int type; /* type of file */ + int flags; /* special flags */ + char *info; /* finderinfo name */ + char *rsrc; /* resource fork name */ + int (*get_info)(char *, char *, dir_ent *, int); /* finderinfo */ + /* function */ + int (*get_dir)(char *, char *, dir_ent *, int); /* directory */ + /* name */ + /* function */ + char *desc; /* description */ +}; + +/* Above filled in */ +static struct hfs_type hfs_types[] = { + {TYPE_NONE, INSERT, "", "", get_none_info, get_none_dir, "None"}, + {TYPE_CAP, INSERT, ".finderinfo/", ".resource/", + get_cap_info, get_cap_dir, "CAP"}, + {TYPE_NETA, INSERT, ".AppleDouble/", ".AppleDouble/", + get_dbl_info, get_dbl_dir, "Netatalk"}, + {TYPE_DBL, INSERT, "%", "%", get_dbl_info, get_dbl_dir, "AppleDouble"}, + {TYPE_ESH, INSERT, ".rsrc/", ".rsrc/", + get_es_info, get_es_dir, "EtherShare/UShare"}, + {TYPE_FEU, NOPEND, "FINDER.DAT", "RESOURCE.FRK/", + get_fe_info, get_fe_dir, "Exchange"}, + {TYPE_FEL, NOPEND, "finder.dat", "resource.frk/", + get_fe_info, get_fe_dir, "Exchange"}, + {TYPE_SGI, NOPEND, ".HSancillary", ".HSResource/", + get_sgi_info, get_sgi_dir, "XINET/SGI"}, + {TYPE_MBIN, PROBE, "", "", get_mb_info, get_none_dir, "MacBinary"}, + {TYPE_SGL, PROBE, "", "", get_sgl_info, get_none_dir, "AppleSingle"}, + {TYPE_DAVE, INSERT, "resource.frk/", "resource.frk/", + get_dbl_info, get_dbl_dir, "DAVE"}, + {TYPE_SFM, APPEND | NORSRC, ":Afp_AfpInfo", ":Afp_Resource", + get_sfm_info, get_none_dir, "SFM"}, + {TYPE_XDBL, INSERT, "._", "._", get_dbl_info, get_dbl_dir, + "MacOS X AppleDouble"}, + {TYPE_XHFS, APPEND | NOINFO, "/rsrc", "/rsrc", get_xhfs_info, get_xhfs_dir, + "MacOS X HFS"} +}; + +/* used by get_magic_match() return */ +static char tmp_type[CT_SIZE + 1], + tmp_creator[CT_SIZE + 1]; + +#ifdef __used__ +/* + * An array useful for CRC calculations that use 0x1021 as the "seed" + * taken from mcvert.c modified by Jim Van Verth. + */ + +static unsigned short mb_magic[] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +#endif /* __used__ */ + +#ifndef HAVE_STRCASECMP +static int +strcasecmp(const char *s1, const char *s2) +{ + while (tolower(*s1) == tolower(*s2)) { + if (*s1 == 0) + return (0); + s1++; + s2++; + } + return (tolower(*s1) - tolower(*s2)); +} +#endif + +/* + * set_ct: set CREATOR and TYPE in hfs_ent + * + * CREATOR and TYPE are padded with spaces if not CT_SIZE long + */ + +static void +set_ct(hfsdirent *hfs_ent, char *c, char *t) +{ + memset(hfs_ent->u.file.type, ' ', CT_SIZE); + memset(hfs_ent->u.file.creator, ' ', CT_SIZE); + + strncpy(hfs_ent->u.file.type, t, MIN(CT_SIZE, strlen(t))); + strncpy(hfs_ent->u.file.creator, c, MIN(CT_SIZE, strlen(c))); + + hfs_ent->u.file.type[CT_SIZE] = '\0'; + hfs_ent->u.file.creator[CT_SIZE] = '\0'; +} + +/* + * cstrncopy: Cap Unix name to HFS name + * + * ':' is replaced by '%' and string is terminated with '\0' + */ +static void +cstrncpy(char *t, char *f, int c) +{ + while (c-- && *f) { + switch (*f) { + case ':': + *t = '%'; + break; + default: + *t = *f; + break; + } + t++; + f++; + } + + *t = '\0'; +} + +/* + * dehex() + * + * Given a hexadecimal digit in ASCII, return the integer representation. + * + * Taken from linux/fs/hfs/trans.c by Paul H. Hargrove + */ +static unsigned char +dehex(char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } + if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } +/* return (0xff); */ + return (0); +} + +static unsigned char +hex2char(char *s) +{ + unsigned char i1; + unsigned char i2; + unsigned char o; + + if (strlen(++s) < 2) + return (0); + + i1 = (unsigned char) s[0]; + i2 = (unsigned char) s[1]; + + if (!isxdigit(i1) || !isxdigit(i2)) + return (0); + + o = (dehex(i1) << 4) & 0xf0; + o |= (dehex(i2) & 0xf); + + return (o); +} + + +/* + * hstrncpy: Unix name to HFS name with special character + * translation. + * + * "%xx" or ":xx" is assumed to be a "special" character and + * replaced by character code given by the hex characters "xx" + * + * if "xx" is not a hex number, then it is left alone - except + * that ":" is replaced by "%" + * + */ +static void +hstrncpy(unsigned char *t, char *f, int c) +{ + unsigned char o; + + while (c-- && *f) { + switch (*f) { + case ':': + case '%': + if ((o = hex2char(f)) == 0) { + *t = conv_charset('%', in_nls, hfs_onls); + } else { + *t = o; + f += 2; + } + break; + default: + *t = conv_charset(*f, in_nls, hfs_onls); + break; + } + t++; + f++; + } + + *t = '\0'; +} + +/* + * basename: find just the filename with any directory component + */ +/* + not used at the moment ... +static char +basename(a) + char *a; +{ + char *b; + + if ((b = strchr(a, '/'))) + return (++b); + else + return (a); +} +*/ + +/* + * set_Dinfo: set directory info + */ +static void +set_Dinfo(byte *ptr, hfsdirent *ent) +{ + Dinfo *dinfo = (Dinfo *)ptr; + + /* finder flags */ + ent->fdflags = d_getw((unsigned char *) dinfo->frFlags); + + if (icon_pos) { + ent->u.dir.rect.top = + d_getw((unsigned char *) dinfo->frRect[0]); + ent->u.dir.rect.left = + d_getw((unsigned char *) dinfo->frRect[1]); + ent->u.dir.rect.bottom = + d_getw((unsigned char *) dinfo->frRect[2]); + ent->u.dir.rect.right = + d_getw((unsigned char *) dinfo->frRect[3]); + + ent->fdlocation.v = + d_getw((unsigned char *) dinfo->frLocation[0]); + ent->fdlocation.h = + d_getw((unsigned char *) dinfo->frLocation[1]); + + ent->u.dir.view = + d_getw((unsigned char *) dinfo->frView); + + ent->u.dir.frscroll.v = + d_getw((unsigned char *) dinfo->frScroll[0]); + ent->u.dir.frscroll.h = + d_getw((unsigned char *) dinfo->frScroll[1]); + + } else { + /* + * clear HFS_FNDR_HASBEENINITED to have tidy desktop ?? + */ + ent->fdflags &= 0xfeff; + } +} + +/* + * set_Finfo: set file info + */ +static void +set_Finfo(byte *ptr, hfsdirent *ent) +{ + Finfo *finfo = (Finfo *)ptr; + + /* type and creator from finder info */ + set_ct(ent, finfo->fdCreator, finfo->fdType); + + /* finder flags */ + ent->fdflags = d_getw((unsigned char *) finfo->fdFlags); + + if (icon_pos) { + ent->fdlocation.v = + d_getw((unsigned char *) finfo->fdLocation[0]); + ent->fdlocation.h = + d_getw((unsigned char *) finfo->fdLocation[1]); + } else { + /* + * clear HFS_FNDR_HASBEENINITED to have tidy desktop ?? + */ + ent->fdflags &= 0xfeff; + } +} + +/* + * get_none_dir: ordinary Unix directory + */ +static int +get_none_dir(char *hname, char *dname, dir_ent *s_entry, int ret) +{ + /* just copy the given name */ + hstrncpy((unsigned char *) (s_entry->hfs_ent->name), + dname, HFS_MAX_FLEN); + + return (ret); +} + +/* + * get_none_info: ordinary Unix file - try to map extension + */ +static int +get_none_info(char *hname, char *dname, dir_ent *s_entry, int ret) +{ + char *t, + *c; + hfsdirent *hfs_ent = s_entry->hfs_ent; + + map_ext(dname, &t, &c, &s_entry->hfs_ent->fdflags, s_entry->whole_name); + + /* just copy the given name */ + hstrncpy((unsigned char *) (hfs_ent->name), dname, HFS_MAX_FLEN); + + set_ct(hfs_ent, c, t); + + return (ret); +} + +/* + * read_info_file: open and read a finderinfo file for an HFS file + * or directory + */ +static int +read_info_file(char *name, /* finderinfo filename */ + void *info, /* info buffer */ + int len /* length of above */) +{ + FILE *fp; + int num; + + /* clear out any old finderinfo stuf */ + memset(info, 0, len); + + if ((fp = fopen(name, "rb")) == NULL) + return (-1); + + /* read and ignore if the file is short - checked later */ + num = fread(info, 1, len, fp); + + fclose(fp); + + return (num); +} + +/* + * get_cap_dir: get the CAP name for a directory + */ +static int +get_cap_dir(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + FileInfo info; /* finderinfo struct */ + int num = -1; /* bytes read */ + hfsdirent *hfs_ent = s_entry->hfs_ent; + + num = read_info_file(hname, &info, sizeof (FileInfo)); + + /* check finder info is OK */ + if (num > 0 && + info.fi_magic1 == FI_MAGIC1 && + info.fi_magic == FI_MAGIC && + info.fi_bitmap & FI_BM_MACINTOSHFILENAME) { + /* use the finderinfo name if it exists */ + cstrncpy((char *) (hfs_ent->name), + (char *) (info.fi_macfilename), HFS_MAX_FLEN); + + set_Dinfo(info.finderinfo, hfs_ent); + + return (ret); + } else { + /* otherwise give it it's Unix name */ + hstrncpy((unsigned char *) (s_entry->hfs_ent->name), + dname, HFS_MAX_FLEN); + return (TYPE_NONE); + } +} + +/* +** get_cap_info: get CAP finderinfo for a file +*/ +static int +get_cap_info(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + FileInfo info; /* finderinfo struct */ + int num = -1; /* bytes read */ + hfsdirent *hfs_ent = s_entry->hfs_ent; + + num = read_info_file(hname, &info, sizeof (info)); + + /* check finder info is OK */ + if (num > 0 && + info.fi_magic1 == FI_MAGIC1 && + info.fi_magic == FI_MAGIC) { + + if (info.fi_bitmap & FI_BM_MACINTOSHFILENAME) { + /* use the finderinfo name if it exists */ + cstrncpy((char *) (hfs_ent->name), + (char *) (info.fi_macfilename), HFS_MAX_FLEN); + } else { + /* use Unix name */ + hstrncpy((unsigned char *) (hfs_ent->name), dname, + HFS_MAX_FLEN); + } + + set_Finfo(info.finderinfo, hfs_ent); +#ifdef USE_MAC_DATES + /* + * set created/modified dates - these date should have already + * been set from the Unix data fork dates. The finderinfo dates + * are in Mac format - but we have to convert them back to Unix + * for the time being + */ + if ((info.fi_datemagic & FI_CDATE)) { + /* use libhfs routines to get correct byte order */ + hfs_ent->crdate = d_toutime(d_getl(info.fi_ctime)); + } + if (info.fi_datemagic & FI_MDATE) { + hfs_ent->mddate = d_toutime(d_getl(info.fi_mtime)); + } +#endif /* USE_MAC_DATES */ + } else { + /* failed to open/read finderinfo - so try afpfile mapping */ + if (verbose > 2) { + fprintf(stderr, + "warning: %s doesn't appear to be a %s file\n", + s_entry->whole_name, hfs_types[ret].desc); + } + ret = get_none_info(hname, dname, s_entry, TYPE_NONE); + } + + return (ret); +} + +/* + * get_es_dir: get EtherShare/UShare finderinfo for a directory + * + * based on code from Jens-Uwe Mager (jum@helios.de) and Phil Sylvester + * <psylvstr@interaccess.com> + */ +static int +get_es_dir(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + es_FileInfo *einfo; /* EtherShare info struct */ + us_FileInfo *uinfo; /* UShare info struct */ + char info[ES_INFO_SIZE]; /* finderinfo buffer */ + int num = -1; /* bytes read */ + hfsdirent *hfs_ent = s_entry->hfs_ent; + + /* + * the EtherShare and UShare file layout is the same, but they store + * finderinfo differently + */ + einfo = (es_FileInfo *) info; + uinfo = (us_FileInfo *) info; + + num = read_info_file(hname, info, sizeof (info)); + + /* check finder info for EtherShare finderinfo */ + if (num >= (int)sizeof (es_FileInfo) && + d_getl(einfo->magic) == ES_MAGIC && + d_getw(einfo->version) == ES_VERSION) { + + set_Dinfo(einfo->finderinfo, hfs_ent); + + } else if (num >= (int)sizeof (us_FileInfo)) { + /* + * UShare has no magic number, so we assume that this is a valid + * info/resource file ... + */ + + set_Dinfo(uinfo->finderinfo, hfs_ent); + + } else { + /* failed to open/read finderinfo - so try afpfile mapping */ + if (verbose > 2) { + fprintf(stderr, + "warning: %s doesn't appear to be a %s file\n", + s_entry->whole_name, hfs_types[ret].desc); + } + ret = get_none_dir(hname, dname, s_entry, TYPE_NONE); + return (ret); + } + + /* set name */ + hstrncpy((unsigned char *) (hfs_ent->name), dname, HFS_MAX_FLEN); + + return (ret); +} + +/* + * get_es_info: get EtherShare/UShare finderinfo for a file + * + * based on code from Jens-Uwe Mager (jum@helios.de) and Phil Sylvester + * <psylvstr@interaccess.com> + */ +static int +get_es_info(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + es_FileInfo *einfo; /* EtherShare info struct */ + us_FileInfo *uinfo; /* UShare info struct */ + char info[ES_INFO_SIZE]; /* finderinfo buffer */ + int num = -1; /* bytes read */ + hfsdirent *hfs_ent = s_entry->hfs_ent; + dir_ent *s_entry1; + + /* + * the EtherShare and UShare file layout is the same, but they store + * finderinfo differently + */ + einfo = (es_FileInfo *) info; + uinfo = (us_FileInfo *) info; + + num = read_info_file(hname, info, sizeof (info)); + + /* check finder info for EtherShare finderinfo */ + if (num >= (int)sizeof (es_FileInfo) && + d_getl(einfo->magic) == ES_MAGIC && + d_getw(einfo->version) == ES_VERSION) { + + set_Finfo(einfo->finderinfo, hfs_ent); + + /* + * set create date - modified date set from the Unix + * data fork date + */ + + hfs_ent->crdate = d_getl(einfo->createTime); + + } else if (num >= (int)sizeof (us_FileInfo)) { + /* + * UShare has no magic number, so we assume that this is a valid + * info/resource file ... + */ + + set_Finfo(uinfo->finderinfo, hfs_ent); + + /* set create and modified date - if they exist */ + if (uinfo->ctime) + hfs_ent->crdate = + d_getl(uinfo->ctime); + + if (uinfo->mtime) + hfs_ent->mddate = + d_getl(uinfo->mtime); + } else { + /* failed to open/read finderinfo - so try afpfile mapping */ + if (verbose > 2) { + fprintf(stderr, + "warning: %s doesn't appear to be a %s file\n", + s_entry->whole_name, hfs_types[ret].desc); + } + ret = get_none_info(hname, dname, s_entry, TYPE_NONE); + return (ret); + } + + /* this should exist ... */ + if ((s_entry1 = s_entry->assoc) == NULL) + perr("TYPE_ESH error - shouldn't happen!"); + + /* set name */ + hstrncpy((unsigned char *) (hfs_ent->name), dname, HFS_MAX_FLEN); + + /* real rsrc file starts ES_INFO_SIZE bytes into the file */ + if (s_entry1->size <= ES_INFO_SIZE) { + s_entry1->size = 0; + hfs_ent->u.file.rsize = 0; + } else { + s_entry1->size -= ES_INFO_SIZE; + hfs_ent->u.file.rsize = s_entry1->size; + s_entry1->hfs_off = ES_INFO_SIZE; + } + + set_733((char *) s_entry1->isorec.size, s_entry1->size); + + return (ret); +} + +/* + * calc_crc() -- + * Compute the MacBinary II-style CRC for the data pointed to by p, with the + * crc seeded to seed. + * + * Modified by Jim Van Verth to use the magic array for efficiency. + */ +#ifdef __used__ +static unsigned short +calc_mb_crc(unsigned char *p, long len, unsigned short seed) +{ + unsigned short hold; /* crc computed so far */ + long i; /* index into data */ + + hold = seed; /* start with seed */ + for (i = 0; i < len; i++, p++) { + hold ^= (*p << 8); + hold = (hold << 8) ^ mb_magic[(unsigned char) (hold >> 8)]; + } + + return (hold); +}/* calc_mb_crc() */ + +#endif /* __used__ */ + +static int +get_mb_info(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + mb_info *info; /* finderinfo struct */ + char *c; + char *t; + hfsdirent *hfs_ent; + dir_ent *s_entry1; + int i; + +#ifdef TEST_CODE + unsigned short crc_file, + crc_calc; + +#endif + + info = (mb_info *) p_buf; + + /* + * routine called twice for each file - first to check that it is a + * valid MacBinary file, second to fill in the HFS info. p_buf holds + * the required raw data and it *should* remain the same between the + * two calls + */ + if (s_entry == 0) { + /* + * test that the CRC is OK - not set for MacBinary I files (and + * incorrect in some MacBinary II files!). If this fails, then + * perform some other checks + */ + +#ifdef TEST_CODE + /* leave this out for the time being ... */ + if (p_num >= MB_SIZE && info->version == 0 && info->zero1 == 0) { + crc_calc = calc_mb_crc((unsigned char *) info, 124, 0); + crc_file = d_getw(info->crc); +#ifdef DEBUG + fprintf(stderr, "%s: file %d, calc %d\n", hname, + crc_file, crc_calc); +#endif /* DEBUG */ + if (crc_file == crc_calc) + return (ret); + } +#endif /* TEST_CODE */ + + /* + * check some of the fields for a valid MacBinary file not + * zero1 and zero2 SHOULD be zero - but some files incorrect + */ + +/* if (p_num < MB_SIZE || info->nlen > 63 || info->zero2 || */ + if (p_num < MB_SIZE || info->zero1 || + info->zero2 || info->nlen > 63 || + info->version || info->nlen == 0 || *info->name == 0) + return (TYPE_NONE); + + /* check that the filename is OKish */ + for (i = 0; i < (int)info->nlen; i++) + if (info->name[i] == 0) + return (TYPE_NONE); + + /* check CREATOR and TYPE are valid */ + for (i = 0; i < 4; i++) + if (info->type[i] == 0 || info->auth[i] == 0) + return (TYPE_NONE); + } else { + /* we have a vaild MacBinary file, so fill in the bits */ + + /* this should exist ... */ + if ((s_entry1 = s_entry->assoc) == NULL) + perr("TYPE_MBIN error - shouldn't happen!"); + + hfs_ent = s_entry->hfs_ent; + + /* type and creator from finder info */ + t = (char *) (info->type); + c = (char *) (info->auth); + + set_ct(hfs_ent, c, t); + + /* finder flags */ + hfs_ent->fdflags = ((info->flags << 8) & 0xff00) | info->flags2; + + if (icon_pos) { + hfs_ent->fdlocation.v = + d_getw((unsigned char *) info->icon_vert); + hfs_ent->fdlocation.h = + d_getw((unsigned char *) info->icon_horiz); + } else { + /* + * clear HFS_FNDR_HASBEENINITED to have tidy desktop ?? + */ + hfs_ent->fdflags &= 0xfeff; + } + + /* + * set created/modified dates - these date should have already + * been set from the Unix data fork dates. The finderinfo dates + * are in Mac format - but we have to convert them back to Unix + * for the time being + */ + hfs_ent->crdate = d_toutime(d_getl(info->cdate)); + hfs_ent->mddate = d_toutime(d_getl(info->mdate)); + + /* set name */ + hstrncpy((unsigned char *) (hfs_ent->name), + (char *) (info->name), MIN(HFS_MAX_FLEN, info->nlen)); + + /* set correct fork sizes */ + hfs_ent->u.file.dsize = d_getl(info->dflen); + hfs_ent->u.file.rsize = d_getl(info->rflen); + + /* update directory entries for data fork */ + s_entry->size = hfs_ent->u.file.dsize; + s_entry->hfs_off = MB_SIZE; + set_733((char *) s_entry->isorec.size, s_entry->size); + + /* + * real rsrc file starts after data fork (must be a multiple of + * MB_SIZE) + */ + s_entry1->size = hfs_ent->u.file.rsize; + s_entry1->hfs_off = MB_SIZE + ROUND_UP(hfs_ent->u.file.dsize, MB_SIZE); + set_733((char *) s_entry1->isorec.size, s_entry1->size); + } + + return (ret); +} + +/* + * get_dbl_dir: get Apple double finderinfo for a directory + * + * Based on code from cvt2cap.c (c) May 1988, Paul Campbell + */ +static int +get_dbl_dir(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + FileInfo info; /* finderinfo struct */ + a_hdr *hp; + a_entry *ep; + int num = -1; /* bytes read */ + int nentries; + FILE *fp; + hfsdirent *hfs_ent = s_entry->hfs_ent; + char name[64]; + int i; + int fail = 0; + int len = 0; + + hp = (a_hdr *) p_buf; + memset(hp, 0, A_HDR_SIZE); + + memset(name, 0, sizeof (name)); + + /* open and read the info/rsrc file (it's the same file) */ + if ((fp = fopen(hname, "rb")) != NULL) + num = fread(hp, 1, A_HDR_SIZE, fp); + + /* + * check finder info is OK - some Netatalk files don't have magic + * or version set - ignore if it's a netatalk file + */ + if (num == A_HDR_SIZE && ((ret == TYPE_NETA) || + (d_getl(hp->magic) == APPLE_DOUBLE && + (d_getl(hp->version) == A_VERSION1 || + d_getl(hp->version) == A_VERSION2)))) { + + /* read TOC of the AppleDouble file */ + nentries = (int) d_getw(hp->nentries); + if (fread(hp->entries, A_ENTRY_SIZE, nentries, fp) < 1) { + fail = 1; + nentries = 0; + } + /* extract what is needed */ + for (i = 0, ep = hp->entries; i < nentries; i++, ep++) { + switch ((int)d_getl(ep->id)) { + case ID_FINDER: + /* get the finder info */ + fseek(fp, (off_t)d_getl(ep->offset), SEEK_SET); + if (fread(&info, d_getl(ep->length), 1, fp) < 1) { + fail = 1; + } + break; + case ID_NAME: + /* get Mac file name */ + fseek(fp, (off_t)d_getl(ep->offset), SEEK_SET); + if (fread(name, d_getl(ep->length), 1, fp) < 1) + *name = '\0'; + len = d_getl(ep->length); + break; + default: + break; + } + } + + fclose(fp); + + /* skip this if we had a problem */ + if (!fail) { + + set_Dinfo(info.finderinfo, hfs_ent); + + /* use stored name if it exists */ + if (*name) { + /* + * In some cases the name is stored in the + * Pascal string format - first char is the + * length, the rest is the actual string. + * The following *should* be OK + */ + if (len == 32 && (int) name[0] < 32) { + cstrncpy(hfs_ent->name, &name[1], + MIN(name[0], HFS_MAX_FLEN)); + } else { + cstrncpy(hfs_ent->name, name, + HFS_MAX_FLEN); + } + } else { + hstrncpy((unsigned char *) (hfs_ent->name), + dname, HFS_MAX_FLEN); + } + } + } else { + /* failed to open/read finderinfo */ + fail = 1; + if (fp) + fclose(fp); + } + + if (fail) { + /* problem with the file - try mapping/magic */ + if (verbose > 2) { + fprintf(stderr, + "warning: %s doesn't appear to be a %s file\n", + s_entry->whole_name, hfs_types[ret].desc); + } + ret = get_none_dir(hname, dname, s_entry, TYPE_NONE); + } + return (ret); +} + +/* + * Depending on the version, AppleDouble/Single stores dates + * relative to 1st Jan 1904 (v1) or 1st Jan 2000 (v2) + * + * The d_toutime() function uses 1st Jan 1904 to convert to + * Unix time (1st Jan 1970). + * + * The d_dtoutime() function uses 1st Jan 2000 to convert to + * Unix time (1st Jan 1970). + * + * However, NetaTalk files seem to do their own thing - older + * Netatalk files don't have a magic number of version and + * store dates in ID=7 (don't know how). Newer Netatalk files + * claim to be version 1, but store dates in ID=7 as if they + * were version 2 files. + */ + +/* + * get_dbl_info: get Apple double finderinfo for a file + * + * Based on code from cvt2cap.c (c) May 1988, Paul Campbell + */ +static int +get_dbl_info(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + FileInfo info; /* finderinfo struct */ + a_hdr *hp; + a_entry *ep; + int num = -1; /* bytes read */ + int nentries; + FILE *fp; + hfsdirent *hfs_ent = s_entry->hfs_ent; + dir_ent *s_entry1; + char name[64]; + int i; + int fail = 0; + int len = 0; + unsigned char dates[A_DATE]; + int ver = 0, dlen; + + hp = (a_hdr *) p_buf; + memset(hp, 0, A_HDR_SIZE); + + memset(name, 0, sizeof (name)); + memset(dates, 0, sizeof (dates)); + + /* get the rsrc file info - should exist ... */ + if ((s_entry1 = s_entry->assoc) == NULL) + perr("TYPE_DBL error - shouldn't happen!"); + + /* open and read the info/rsrc file (it's the same file) */ + if ((fp = fopen(hname, "rb")) != NULL) + num = fread(hp, 1, A_HDR_SIZE, fp); + + /* + * check finder info is OK - some Netatalk files don't have magic + * or version set - ignore if it's a netatalk file + */ + + ver = d_getl(hp->version); + if (num == A_HDR_SIZE && ((ret == TYPE_NETA) || + (d_getl(hp->magic) == APPLE_DOUBLE && + (ver == A_VERSION1 || ver == A_VERSION2)))) { + + /* read TOC of the AppleDouble file */ + nentries = (int) d_getw(hp->nentries); + if (fread(hp->entries, A_ENTRY_SIZE, nentries, fp) < 1) { + fail = 1; + nentries = 0; + } + /* extract what is needed */ + for (i = 0, ep = hp->entries; i < nentries; i++, ep++) { + switch ((int)d_getl(ep->id)) { + case ID_FINDER: + /* get the finder info */ + fseek(fp, (off_t)d_getl(ep->offset), SEEK_SET); + if (fread(&info, d_getl(ep->length), 1, fp) < 1) { + fail = 1; + } + break; + case ID_RESOURCE: + /* set the offset and correct rsrc fork size */ + s_entry1->size = d_getl(ep->length); + hfs_ent->u.file.rsize = s_entry1->size; + /* offset to start of real rsrc fork */ + s_entry1->hfs_off = d_getl(ep->offset); + set_733((char *) s_entry1->isorec.size, + s_entry1->size); + break; + case ID_NAME: + /* get Mac file name */ + fseek(fp, (off_t)d_getl(ep->offset), SEEK_SET); + if (fread(name, d_getl(ep->length), 1, fp) < 1) + *name = '\0'; + len = d_getl(ep->length); + break; + case ID_FILEI: + /* Workround for NetaTalk files ... */ + if (ret == TYPE_NETA && ver == A_VERSION1) + ver = A_VERSION2; + /* fall through */ + case ID_FILEDATESI: + /* get file info */ + fseek(fp, d_getl(ep->offset), 0); + dlen = MIN(d_getl(ep->length), A_DATE); + if (fread(dates, dlen, 1, fp) < 1) { + fail = 1; + } else { + /* get the correct Unix time */ + switch (ver) { + + case (A_VERSION1): + hfs_ent->crdate = + d_toutime(d_getl(dates)); + hfs_ent->mddate = + d_toutime(d_getl(dates+4)); + break; + case (A_VERSION2): + hfs_ent->crdate = + d_dtoutime(d_getl(dates)); + hfs_ent->mddate = + d_dtoutime(d_getl(dates+4)); + break; + default: + /* Use Unix dates */ + break; + } + } + break; + default: + break; + } + } + + fclose(fp); + + /* skip this if we had a problem */ + if (!fail) { + set_Finfo(info.finderinfo, hfs_ent); + + /* use stored name if it exists */ + if (*name) { + /* + * In some cases the name is stored in the + * Pascal string format - first char is the + * length, the rest is the actual string. + * The following *should* be OK + */ + if (len == 32 && (int) name[0] < 32) { + cstrncpy(hfs_ent->name, &name[1], + MIN(name[0], HFS_MAX_FLEN)); + } else { + cstrncpy(hfs_ent->name, name, + HFS_MAX_FLEN); + } + } else { + hstrncpy((unsigned char *) (hfs_ent->name), + dname, HFS_MAX_FLEN); + } + } + } else { + /* failed to open/read finderinfo */ + fail = 1; + if (fp) + fclose(fp); + } + + if (fail) { + /* problem with the file - try mapping/magic */ + if (verbose > 2) { + fprintf(stderr, + "warning: %s doesn't appear to be a %s file\n", + s_entry->whole_name, hfs_types[ret].desc); + } + ret = get_none_info(hname, dname, s_entry, TYPE_NONE); + } + return (ret); +} + +/* + * get_sgl_info: get Apple single finderinfo for a file + * + * Based on code from cvt2cap.c (c) May 1988, Paul Campbell + */ +static int +get_sgl_info(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + FileInfo *info = 0; /* finderinfo struct */ + a_hdr *hp; + static a_entry *entries; + a_entry *ep; + int nentries; + hfsdirent *hfs_ent; + dir_ent *s_entry1; + char name[64]; + int i; + int len = 0; + unsigned char *dates; + int ver = 0; + + /* + * routine called twice for each file + * - first to check that it is a valid + * AppleSingle file, second to fill in the HFS info. + * p_buf holds the required + * raw data and it *should* remain the same between the two calls + */ + hp = (a_hdr *) p_buf; + + if (s_entry == 0) { + if (p_num < A_HDR_SIZE || + d_getl(hp->magic) != APPLE_SINGLE || + (d_getl(hp->version) != A_VERSION1 && + d_getl(hp->version) != A_VERSION2)) + return (TYPE_NONE); + + /* check we have TOC for the AppleSingle file */ + nentries = (int) d_getw(hp->nentries); + if (p_num < (int)(A_HDR_SIZE + nentries * A_ENTRY_SIZE)) + return (TYPE_NONE); + + /* save the TOC */ + entries = (a_entry *) e_malloc(nentries * A_ENTRY_SIZE); + + memcpy(entries, (p_buf + A_HDR_SIZE), nentries * A_ENTRY_SIZE); + } else { + /* have a vaild AppleSingle File */ + memset(name, 0, sizeof (name)); + + /* get the rsrc file info - should exist ... */ + if ((s_entry1 = s_entry->assoc) == NULL) + perr("TYPE_SGL error - shouldn't happen!"); + + hfs_ent = s_entry->hfs_ent; + + nentries = (int) d_getw(hp->nentries); + ver = d_getl(hp->version); + + /* extract what is needed */ + for (i = 0, ep = entries; i < nentries; i++, ep++) { + switch ((int)d_getl(ep->id)) { + case ID_FINDER: + /* get the finder info */ + info = (FileInfo *) (p_buf + d_getl(ep->offset)); + break; + case ID_DATA: + /* set the offset and correct data fork size */ + hfs_ent->u.file.dsize = s_entry->size = + d_getl(ep->length); + /* offset to start of real data fork */ + s_entry->hfs_off = d_getl(ep->offset); + set_733((char *) s_entry->isorec.size, + s_entry->size); + break; + case ID_RESOURCE: + /* set the offset and correct rsrc fork size */ + hfs_ent->u.file.rsize = s_entry1->size = + d_getl(ep->length); + /* offset to start of real rsrc fork */ + s_entry1->hfs_off = d_getl(ep->offset); + set_733((char *) s_entry1->isorec.size, + s_entry1->size); + break; + case ID_NAME: + /* get Mac file name */ + strncpy(name, (p_buf + d_getl(ep->offset)), + d_getl(ep->length)); + len = d_getl(ep->length); + break; + case ID_FILEI: + /* get file info - ignore at the moment*/ + break; + case ID_FILEDATESI: + /* get file info */ + dates = (unsigned char *)p_buf + d_getl(ep->offset); + /* get the correct Unix time */ + if (ver == A_VERSION1) { + hfs_ent->crdate = + d_toutime(d_getl(dates)); + hfs_ent->mddate = + d_toutime(d_getl(dates+4)); + } else { + hfs_ent->crdate = + d_dtoutime(d_getl(dates)); + hfs_ent->mddate = + d_dtoutime(d_getl(dates+4)); + } + break; + default: + break; + } + } + + free(entries); + + if (info == NULL) { + /* + * failed to open/read finderinfo + * - so try afpfile mapping + */ + if (verbose > 2) { + fprintf(stderr, + "warning: %s doesn't appear to be a %s file\n", + s_entry->whole_name, + hfs_types[ret].desc); + } + ret = get_none_info(hname, dname, s_entry, TYPE_NONE); + return (ret); + } + + set_Finfo(info->finderinfo, hfs_ent); + + /* use stored name if it exists */ + if (*name) { + /* + * In some cases the name is stored in the Pascal string + * format - first char is the length, the rest is the + * actual string. The following *should* be OK + */ + if (len == 32 && (int) name[0] < 32) { + cstrncpy(hfs_ent->name, &name[1], MIN(name[0], + HFS_MAX_FLEN)); + } else { + cstrncpy(hfs_ent->name, name, HFS_MAX_FLEN); + } + } else { + hstrncpy((unsigned char *) (hfs_ent->name), dname, + HFS_MAX_FLEN); + } + } + + return (ret); +} + +/* + * get_hfs_fe_info: read in the whole finderinfo for a PC Exchange + * directory - saves on reading this many times for each file. + * + * Based of information provided by Mark Weinstein <mrwesq@earthlink.net> + * + * Note: the FINDER.DAT file layout depends on the FAT cluster size + * therefore, files should only be read directly from the FAT media + * + * Only tested with PC Exchange v2.1 - don't know if it will work + * with v2.2 and above. + */ +static struct hfs_info * +get_hfs_fe_info(struct hfs_info *hfs_info, char *name) +{ + FILE *fp; + int fe_num, + fe_pad; + fe_info info; + int c = 0; + struct hfs_info *hfs_info1 = NULL; + char keyname[12]; + char *s, + *e, + *k; + int i; + + if ((fp = fopen(name, "rb")) == NULL) + return (NULL); + + /* + * no longer attempt to find out FAT cluster + * - rely on command line parameter + */ + if (afe_size <= 0) + return (NULL); + + fe_num = afe_size / FE_SIZE; + fe_pad = afe_size % FE_SIZE; + + while (fread(&info, 1, FE_SIZE, fp) != 0) { + + /* the Mac name may be NULL - so ignore this entry */ + if (info.nlen != 0) { + + hfs_info1 = + (struct hfs_info *)e_malloc(sizeof (struct hfs_info)); + /* add this entry to the list */ + hfs_info1->next = hfs_info; + hfs_info = hfs_info1; + + /* + * get the bits we need + * - ignore [cm]time for the moment + */ + cstrncpy(hfs_info->name, (char *) (info.name), + info.nlen); + + memcpy(hfs_info->finderinfo, info.finderinfo, INFOLEN); + + s = (char *) (info.sname); + e = (char *) (info.ext); + k = keyname; + + /* + * short (Unix) name is stored in PC format, + * so needs to be mangled a bit + */ + + /* name part */ + for (i = 0; i < 8; i++, s++, k++) { + if (*s == ' ') + break; + else + *k = *s; + } + + /* extension - if it exists */ + if (strncmp((const char *) (info.ext), " ", 3)) { + *k = '.'; + k++; + for (i = 0; i < 3; i++, e++, k++) { + if (*e == ' ') + break; + else + *k = *e; + } + } + *k = '\0'; + + hfs_info1->keyname = strdup(keyname); + } + /* + * each record is FE_SIZE long, and there are FE_NUM + * per each "cluster size", so we may need to skip the padding + */ + if (++c == fe_num) { + c = 0; + fseek(fp, (off_t)fe_pad, SEEK_CUR); + } + } + fclose(fp); + + return (hfs_info); +} + +/* + * get_hfs_sgi_info: read in the whole finderinfo for a SGI (XINET) + * directory - saves on reading this many times for each + * file. + */ +static struct hfs_info * +get_hfs_sgi_info(struct hfs_info *hfs_info, char *name) +{ + FILE *fp; + sgi_info info; + struct hfs_info *hfs_info1 = NULL; + + if ((fp = fopen(name, "rb")) == NULL) + return (NULL); + + while (fread(&info, 1, SGI_SIZE, fp) != 0) { + + hfs_info1 = (struct hfs_info *)e_malloc(sizeof (struct hfs_info)); + /* add this entry to the list */ + hfs_info1->next = hfs_info; + hfs_info = hfs_info1; + + /* get the bits we need - ignore [cm]time for the moment */ + cstrncpy(hfs_info->name, (char *)info.name, HFS_MAX_FLEN); + + memcpy(hfs_info->finderinfo, info.finderinfo, INFOLEN); + + /* use the HFS name as the key */ + hfs_info1->keyname = hfs_info->name; + + } + fclose(fp); + + return (hfs_info); +} + +/* + * del_hfs_info: delete the info list and recover memory + */ +void +del_hfs_info(struct hfs_info *hfs_info) +{ + struct hfs_info *hfs_info1; + + while (hfs_info) { + hfs_info1 = hfs_info; + hfs_info = hfs_info->next; + + /* key may be the same as the HFS name - so don't free it */ + *hfs_info1->name = '\0'; + if (*hfs_info1->keyname) + free(hfs_info1->keyname); + free(hfs_info1); + } +} + +/* + * match_key: find the correct hfs_ent using the Unix filename + * as the key + */ +static struct hfs_info * +match_key(struct hfs_info *hfs_info, char *key) +{ + while (hfs_info) { + if (strcasecmp(key, hfs_info->keyname) == 0) + return (hfs_info); + hfs_info = hfs_info->next; + } + + return (NULL); +} + +/* + * get_fe_dir: get PC Exchange directory name + * + * base on probing with od ... + */ +static int +get_fe_dir(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + struct hfs_info *hfs_info; + hfsdirent *hfs_ent = s_entry->hfs_ent; + + /* cached finderinfo stored with parent directory */ + hfs_info = s_entry->filedir->hfs_info; + + /* if we have no cache, then make one and store it */ + if (hfs_info == NULL) { + if ((hfs_info = get_hfs_fe_info(hfs_info, hname)) == NULL) + ret = TYPE_NONE; + else + s_entry->filedir->hfs_info = hfs_info; + } + if (ret != TYPE_NONE) { + /* see if we can find the details of this file */ + if ((hfs_info = match_key(hfs_info, dname)) != NULL) { + strcpy(hfs_ent->name, hfs_info->name); + + set_Dinfo(hfs_info->finderinfo, hfs_ent); + + return (ret); + } + } + /* can't find the entry, so use the Unix name */ + hstrncpy((unsigned char *)(hfs_ent->name), dname, HFS_MAX_FLEN); + + return (TYPE_NONE); +} + +/* + * get_fe_info: get PC Exchange file details. + * + * base on probing with od and details from Mark Weinstein + * <mrwesq@earthlink.net> + */ +static int +get_fe_info(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + struct hfs_info *hfs_info; + hfsdirent *hfs_ent = s_entry->hfs_ent; + + /* cached finderinfo stored with parent directory */ + hfs_info = s_entry->filedir->hfs_info; + + /* if we have no cache, then make one and store it */ + if (hfs_info == NULL) { + if ((hfs_info = get_hfs_fe_info(hfs_info, hname)) == NULL) + ret = TYPE_NONE; + else + s_entry->filedir->hfs_info = hfs_info; + } + if (ret != TYPE_NONE) { + char *dn = dname; + +#ifdef _WIN32_TEST + /* + * may have a problem here - v2.2 has long filenames, + * but we need to key on the short filename, + * so we need do go a bit of win32 stuff + * ... + */ + char sname[1024]; + char lname[1024]; + + cygwin32_conv_to_full_win32_path(s_entry->whole_name, lname); + + if (GetShortPathName(lname, sname, sizeof (sname))) { + if (dn = strrchr(sname, '\\')) + dn++; + else + dn = sname; + } +#endif /* _WIN32 */ + + /* see if we can find the details of this file */ + if ((hfs_info = match_key(hfs_info, dn)) != NULL) { + + strcpy(hfs_ent->name, hfs_info->name); + + set_Finfo(hfs_info->finderinfo, hfs_ent); + + return (ret); + } + } + /* no entry found - use extension mapping */ + if (verbose > 2) { + fprintf(stderr, "warning: %s doesn't appear to be a %s file\n", + s_entry->whole_name, hfs_types[ret].desc); + } + ret = get_none_info(hname, dname, s_entry, TYPE_NONE); + + return (TYPE_NONE); +} + +/* + * get_sgi_dir: get SGI (XINET) HFS directory name + * + * base on probing with od ... + */ +static int +get_sgi_dir(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + struct hfs_info *hfs_info; + hfsdirent *hfs_ent = s_entry->hfs_ent; + + /* cached finderinfo stored with parent directory */ + hfs_info = s_entry->filedir->hfs_info; + + /* if we haven't got a cache, then make one */ + if (hfs_info == NULL) { + if ((hfs_info = get_hfs_sgi_info(hfs_info, hname)) == NULL) + ret = TYPE_NONE; + else + s_entry->filedir->hfs_info = hfs_info; + } + /* find the matching entry in the cache */ + if (ret != TYPE_NONE) { + /* key is (hopefully) the real Mac name */ + cstrncpy(tmp, dname, strlen(dname)); + if ((hfs_info = match_key(hfs_info, tmp)) != NULL) { + strcpy(hfs_ent->name, hfs_info->name); + + set_Dinfo(hfs_info->finderinfo, hfs_ent); + + return (ret); + } + } + /* no entry found - use Unix name */ + hstrncpy((unsigned char *)(hfs_ent->name), dname, HFS_MAX_FLEN); + + return (TYPE_NONE); +} + +/* + * get_sgi_info: get SGI (XINET) HFS finder info + * + * base on probing with od ... + */ +static int +get_sgi_info(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + struct hfs_info *hfs_info; + hfsdirent *hfs_ent = s_entry->hfs_ent; + + /* cached finderinfo stored with parent directory */ + hfs_info = s_entry->filedir->hfs_info; + + /* if we haven't got a cache, then make one */ + if (hfs_info == NULL) { + if ((hfs_info = get_hfs_sgi_info(hfs_info, hname)) == NULL) + ret = TYPE_NONE; + else + s_entry->filedir->hfs_info = hfs_info; + } + if (ret != TYPE_NONE) { + /* + * tmp is the same as hname here, but we don't need hname + * anymore in this function ... see if we can find the + * details of this file using the Unix name as the key + */ + cstrncpy(tmp, dname, strlen(dname)); + if ((hfs_info = match_key(hfs_info, tmp)) != NULL) { + + strcpy(hfs_ent->name, hfs_info->name); + + set_Finfo(hfs_info->finderinfo, hfs_ent); + + return (ret); + } + } + /* no entry found, so try file extension */ + if (verbose > 2) { + fprintf(stderr, "warning: %s doesn't appear to be a %s file\n", + s_entry->whole_name, hfs_types[ret].desc); + } + ret = get_none_info(hname, dname, s_entry, TYPE_NONE); + + return (TYPE_NONE); +} + +/* + * get_sfm_info: get SFM finderinfo for a file + */ + +static byte sfm_magic[4] = {0x41, 0x46, 0x50, 0x00}; +static byte sfm_version[4] = {0x00, 0x00, 0x01, 0x00}; + +static int +get_sfm_info(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + sfm_info info; /* finderinfo struct */ + int num = -1; /* bytes read */ + hfsdirent *hfs_ent = s_entry->hfs_ent; + + num = read_info_file(hname, &info, sizeof (info)); + + /* check finder info is OK */ + if (num == sizeof (info) && + !memcmp((char *)info.afpi_Signature, (char *)sfm_magic, 4) && + !memcmp((char *)info.afpi_Version, (char *)sfm_version, 4)) { + /* use Unix name */ + hstrncpy((unsigned char *)(hfs_ent->name), dname, HFS_MAX_FLEN); + + set_Finfo(info.finderinfo, hfs_ent); + + } else { + /* failed to open/read finderinfo - so try afpfile mapping */ + if (verbose > 2) { + fprintf(stderr, + "warning: %s doesn't appear to be a %s file\n", + s_entry->whole_name, hfs_types[ret].desc); + } + ret = get_none_info(hname, dname, s_entry, TYPE_NONE); + } + + return (ret); +} + +#ifdef IS_MACOS_X +/* + * get_xhfs_dir: get MacOS X HFS finderinfo for a directory + * + * Code ideas from 'hfstar' by Marcel Weiher marcel@metaobject.com + * and another GNU hfstar by Torres Vedras paulotex@yahoo.com + * + * Here we are dealing with actual HFS files - not some encoding + * we have to use a system call to get the finderinfo + * + * The file name here is the pseudo name for the resource fork + */ +static int +get_xhfs_dir(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + int err; + hfsdirent *hfs_ent = s_entry->hfs_ent; + attrinfo ainfo; + struct attrlist attrs; + int i; + + memset(&attrs, 0, sizeof (attrs)); + + /* set flags we need to get info from getattrlist() */ + attrs.bitmapcount = ATTR_BIT_MAP_COUNT; + attrs.commonattr = ATTR_CMN_CRTIME | ATTR_CMN_MODTIME | + ATTR_CMN_FNDRINFO; + + /* get the info */ + err = getattrlist(hname, &attrs, &ainfo, sizeof (ainfo), 0); + + if (err == 0) { + /* + * If the Finfo is blank then we assume it's not a + * 'true' HFS directory ... + */ + err = 1; + for (i = 0; i < sizeof (ainfo.info); i++) { + if (ainfo.info[i] != 0) { + err = 0; + break; + } + } + } + + /* check finder info is OK */ + if (err == 0) { + + hstrncpy((unsigned char *) (s_entry->hfs_ent->name), + dname, HFS_MAX_FLEN); + + set_Dinfo(ainfo.info, hfs_ent); + + return (ret); + } else { + /* otherwise give it it's Unix name */ + hstrncpy((unsigned char *) (s_entry->hfs_ent->name), + dname, HFS_MAX_FLEN); + return (TYPE_NONE); + } +} + +/* + * get_xhfs_info: get MacOS X HFS finderinfo for a file + * + * Code ideas from 'hfstar' by Marcel Weiher marcel@metaobject.com, + * another GNU hfstar by Torres Vedras paulotex@yahoo.com and + * hfspax by Howard Oakley howard@quercus.demon.co.uk + * + * Here we are dealing with actual HFS files - not some encoding + * we have to use a system call to get the finderinfo + * + * The file name here is the pseudo name for the resource fork + */ +static int +get_xhfs_info(char *hname, /* whole path */ + char *dname, /* this dir name */ + dir_ent *s_entry, /* directory entry */ + int ret) +{ + int err; + hfsdirent *hfs_ent = s_entry->hfs_ent; + attrinfo ainfo; + struct attrlist attrs; + int i; + int size; + + memset(&attrs, 0, sizeof (attrs)); + + /* set flags we need to get info from getattrlist() */ + attrs.bitmapcount = ATTR_BIT_MAP_COUNT; + attrs.commonattr = ATTR_CMN_CRTIME | ATTR_CMN_MODTIME | + ATTR_CMN_FNDRINFO; + + /* get the info */ + err = getattrlist(hname, &attrs, &ainfo, sizeof (ainfo), 0); + + /* check finder info is OK */ + if (err == 0) { + + /* + * If the Finfo is blank and the resource file is empty, + * then we assume it's not a 'true' HFS file ... + * There will be not associated file if the resource fork + * is empty + */ + + if (s_entry->assoc == NULL) { + err = 1; + for (i = 0; i < sizeof (ainfo.info); i++) { + if (ainfo.info[i] != 0) { + err = 0; + break; + } + } + } + + if (err == 0) { + + /* use Unix name */ + hstrncpy((unsigned char *) (hfs_ent->name), dname, + HFS_MAX_FLEN); + + set_Finfo(ainfo.info, hfs_ent); + + /* + * dates have already been set - but we will + * set them here as well from the HFS info + * shouldn't need to check for byte order, as + * the source is HFS ... but we will just in case + */ + hfs_ent->crdate = d_getl((byte *)&ainfo.ctime.tv_sec); + + hfs_ent->mddate = d_getl((byte *)&ainfo.mtime.tv_sec); + } + + } + + if (err) { + /* not a 'true' HFS file - so try afpfile mapping */ +#if 0 + /* + * don't print a warning as we will get lots on HFS + * file systems ... + */ + if (verbose > 2) { + fprintf(stderr, + "warning: %s doesn't appear to be a %s file\n", + s_entry->whole_name, hfs_types[ret].desc); + } +#endif + ret = get_none_info(hname, dname, s_entry, TYPE_NONE); + } + + return (ret); +} +#endif /* IS_MACOS_X */ + +/* + * get_hfs_itype: get the type of HFS info for a file + */ +static int +get_hfs_itype(char *wname, char *dname, char *htmp) +{ + int wlen, + i; + int no_type = TYPE_NONE; + + wlen = strlen(wname) - strlen(dname); + + /* search through the known types looking for matches */ + for (i = 1; i < hfs_num; i++) { + /* skip the ones that we don't care about */ + if ((hfs_types[i].flags & PROBE) || + *(hfs_types[i].info) == TYPE_NONE) { + continue; + } + + strcpy(htmp, wname); + + /* + * special case - if the info file doesn't exist + * for a requested type, then remember the type - + * we don't return here, as we _may_ find another type + * so we save the type here in case - we will have + * problems if more than one of this type ever exists ... + */ + if (hfs_types[i].flags & NOINFO) { + no_type = i; + } else { + + /* append or insert finderinfo filename part */ + if (hfs_types[i].flags & APPEND) + strcat(htmp, hfs_types[i].info); + else + sprintf(htmp + wlen, "%s%s", hfs_types[i].info, + (hfs_types[i].flags & NOPEND) ? "" : dname); + + /* hack time ... Netatalk is a special case ... */ + if (i == TYPE_NETA) { + strcpy(htmp, wname); + strcat(htmp, "/.AppleDouble/.Parent"); + } + + if (!access(htmp, R_OK)) + return (hfs_types[i].type); + } + } + + return (no_type); +} + +/* + * set_root_info: set the root folder hfs_ent from given file + */ +void +set_root_info(char *name) +{ + dir_ent *s_entry; + hfsdirent *hfs_ent; + int i; + + s_entry = root->self; + + hfs_ent = (hfsdirent *) e_malloc(sizeof (hfsdirent)); + memset(hfs_ent, 0, sizeof (hfsdirent)); + + /* make sure root has a valid hfs_ent */ + s_entry->hfs_ent = root->hfs_ent = hfs_ent; + + /* search for correct type of root info data */ + for (i = 1; i < hfs_num; i++) { + if ((hfs_types[i].flags & PROBE) || + (hfs_types[i].get_info == get_none_info)) + continue; + + if ((*(hfs_types[i].get_dir))(name, "", s_entry, i) == i) + return; + } +} + + +/* + * get_hfs_dir: set the HFS directory name + */ +int +get_hfs_dir(char *wname, char *dname, dir_ent *s_entry) +{ + int type; + + /* get the HFS file type from the info file (if it exists) */ + type = get_hfs_itype(wname, dname, tmp); + + /* try to get the required info */ + type = (*(hfs_types[type].get_dir)) (tmp, dname, s_entry, type); + + return (type); +} + +/* + * get_hfs_info: set the HFS info for a file + */ +int +get_hfs_info(char *wname, char *dname, dir_ent *s_entry) +{ + int type, + wlen, + i; + + wlen = strlen(wname) - strlen(dname); + + /* we may already know the type of Unix/HFS file - so process */ + if (s_entry->hfs_type != TYPE_NONE) { + + type = s_entry->hfs_type; + + strcpy(tmp, wname); + + /* append or insert finderinfo filename part */ + if (hfs_types[type].flags & APPEND) + strcat(tmp, hfs_types[type].info); + else + sprintf(tmp + wlen, "%s%s", hfs_types[type].info, + (hfs_types[type].flags & NOPEND) ? "" : dname); + + type = (*(hfs_types[type].get_info))(tmp, dname, s_entry, type); + + /* if everything is as expected, then return */ + if (s_entry->hfs_type == type) + return (type); + } + /* we don't know what type we have so, find out */ + for (i = 1; i < hfs_num; i++) { + if ((hfs_types[i].flags & PROBE) || + *(hfs_types[i].info) == TYPE_NONE) { + continue; + } + + strcpy(tmp, wname); + + /* append or insert finderinfo filename part */ + if (hfs_types[i].flags & APPEND) { + strcat(tmp, hfs_types[i].info); + } else { + sprintf(tmp + wlen, "%s%s", hfs_types[i].info, + (hfs_types[i].flags & NOPEND) ? "" : dname); + } + + /* if the file exists - and not a type we've already tried */ + if (!access(tmp, R_OK) && i != s_entry->hfs_type) { + type = (*(hfs_types[i].get_info))(tmp, dname, + s_entry, i); + s_entry->hfs_type = type; + return (type); + } + } + + /* nothing found, so just a Unix file */ + type = (*(hfs_types[TYPE_NONE].get_info))(wname, dname, + s_entry, TYPE_NONE); + + return (type); +} + +/* + * get_hfs_rname: set the name of the Unix rsrc file for a file + * + * For the time being we ignore the 'NOINFO' flag - the only case + * at the moment is for MacOS X HFS files - for files the resource + * fork exists - so testing the "filename/rsrc" pseudo file as + * the 'info' filename is OK ... + */ +int +get_hfs_rname(char *wname, char *dname, char *rname) +{ + int wlen, + type, + i; + int p_fd = -1; + + wlen = strlen(wname) - strlen(dname); + + /* try to find what sort of Unix HFS file type we have */ + for (i = 1; i < hfs_num; i++) { + /* skip if don't want to probe the files - (default) */ + if (hfs_types[i].flags & PROBE) + continue; + + strcpy(rname, wname); + + /* if we have a different info file, the find out it's type */ + if (*(hfs_types[i].rsrc) && *(hfs_types[i].info)) { + /* first test the Info file */ + + /* append or insert finderinfo filename part */ + if (hfs_types[i].flags & APPEND) { + strcat(rname, hfs_types[i].info); + } else { + sprintf(rname + wlen, "%s%s", hfs_types[i].info, + (hfs_types[i].flags & NOPEND) ? + "" : dname); + } + + /* if it exists, then check the Rsrc file */ + if (!access(rname, R_OK)) { + if (hfs_types[i].flags & APPEND) { + sprintf(rname + wlen, "%s%s", dname, + hfs_types[i].rsrc); + } else { + sprintf(rname + wlen, "%s%s", + hfs_types[i].rsrc, dname); + } + + /* + * for some types, a rsrc fork may not exist, + * so just return the current type + * in these cases + */ + if (hfs_types[i].flags & NORSRC || + !access(rname, R_OK)) + return (hfs_types[i].type); + } + } else { + /* + * if we are probing, + * then have a look at the contents to find type + */ + if (p_fd < 0) { + /* open file, if not already open */ + if ((p_fd = open(wname, + O_RDONLY | O_BINARY)) < 0) { + /* can't open it, then give up */ + return (TYPE_NONE); + } else { + if ((p_num = read(p_fd, p_buf, + sizeof (p_buf))) <= 0) { + /* + * can't read, or zero length + * - give up + */ + close(p_fd); + return (TYPE_NONE); + } + /* get file pointer and close file */ + p_fp = fdopen(p_fd, "rb"); + close(p_fd); + if (p_fp == NULL) + return (TYPE_NONE); + } + } + /* + * call routine to do the work + * - use the given dname as this + * is the name we may use on the CD + */ + type = (*(hfs_types[i].get_info)) (rname, dname, 0, i); + if (type != 0) { + fclose(p_fp); + return (type); + } + if (p_fp) { + /* + * close file + * - just use contents of buffer next time + */ + fclose(p_fp); + p_fp = NULL; + } + } + } + + return (0); +} + +/* + * hfs_exclude: file/directory names that hold finder/resource + * information that we want to exclude from the tree. + * These files/directories are processed later ... + */ +int +hfs_exclude(char *d_name) +{ + /* we don't exclude "." and ".." */ + if (strcmp(d_name, ".") == 0) + return (0); + if (strcmp(d_name, "..") == 0) + return (0); + + /* do not add the following to our list of dir entries */ + if (DO_CAP & hselect) { + /* CAP */ + if (strcmp(d_name, ".finderinfo") == 0) + return (1); + if (strcmp(d_name, ".resource") == 0) + return (1); + if (strcmp(d_name, ".ADeskTop") == 0) + return (1); + if (strcmp(d_name, ".IDeskTop") == 0) + return (1); + if (strcmp(d_name, "Network Trash Folder") == 0) + return (1); + /* + * special case when HFS volume is mounted using Linux's hfs_fs + * Brad Midgley <brad@pht.com> + */ + if (strcmp(d_name, ".rootinfo") == 0) + return (1); + } + if (DO_ESH & hselect) { + /* Helios EtherShare files */ + if (strcmp(d_name, ".rsrc") == 0) + return (1); + if (strcmp(d_name, ".Desktop") == 0) + return (1); + if (strcmp(d_name, ".DeskServer") == 0) + return (1); + if (strcmp(d_name, ".Label") == 0) + return (1); + } + if (DO_DBL & hselect) { + /* Apple Double */ + /* + * special case when HFS volume is mounted using Linux's hfs_fs + */ + if (strcmp(d_name, "%RootInfo") == 0) + return (1); + /* + * have to be careful here - a filename starting with '%' + * may be vaild if the next two letters are a hex character - + * unfortunately '%' 'digit' 'digit' may be a valid resource + * file name ... + */ + if (*d_name == '%') + if (hex2char(d_name) == 0) + return (1); + } + if (DO_NETA & hselect) { + if (strcmp(d_name, ".AppleDouble") == 0) + return (1); + if (strcmp(d_name, ".AppleDesktop") == 0) + return (1); + } + if ((DO_FEU & hselect) || (DO_FEL & hselect)) { + /* PC Exchange */ + if (strcmp(d_name, "RESOURCE.FRK") == 0) + return (1); + if (strcmp(d_name, "FINDER.DAT") == 0) + return (1); + if (strcmp(d_name, "DESKTOP") == 0) + return (1); + if (strcmp(d_name, "FILEID.DAT") == 0) + return (1); + if (strcmp(d_name, "resource.frk") == 0) + return (1); + if (strcmp(d_name, "finder.dat") == 0) + return (1); + if (strcmp(d_name, "desktop") == 0) + return (1); + if (strcmp(d_name, "fileid.dat") == 0) + return (1); + } + if (DO_SGI & hselect) { + /* SGI */ + if (strcmp(d_name, ".HSResource") == 0) + return (1); + if (strcmp(d_name, ".HSancillary") == 0) + return (1); + } + if (DO_DAVE & hselect) { + /* DAVE */ + if (strcmp(d_name, "resource.frk") == 0) + return (1); + if (strcmp(d_name, "DesktopFolderDB") == 0) + return (1); + } +#ifndef _WIN32 + /* + * NTFS streams are not "seen" as files, + * so WinNT will not see these files - + * so ignore - used for testing under Unix + */ + if (DO_SFM & hselect) { + /* SFM */ + char *dn = strrchr(d_name, ':'); + + if (dn) { + if (strcmp(dn, ":Afp_Resource") == 0) + return (1); + if (strcmp(dn, ":Comments") == 0) + return (1); + if (strcmp(dn, ":Afp_AfpInfo") == 0) + return (1); + } + } +#endif /* _WIN32 */ + + if (DO_XDBL & hselect) { + /* XDB */ + if (strncmp(d_name, "._", 2) == 0) + return (1); + } + + return (0); +} + +/* + * print_hfs_info: print info about the HFS files. + * + */ +void +print_hfs_info(dir_ent *s_entry) +{ + fprintf(stderr, "Name: %s\n", s_entry->whole_name); + fprintf(stderr, "\tFile type: %s\n", hfs_types[s_entry->hfs_type].desc); + fprintf(stderr, "\tHFS Name: %s\n", s_entry->hfs_ent->name); + fprintf(stderr, "\tISO Name: %s\n", s_entry->isorec.name); + fprintf(stderr, "\tCREATOR: %s\n", s_entry->hfs_ent->u.file.creator); + fprintf(stderr, "\tTYPE: %s\n", s_entry->hfs_ent->u.file.type); +} + + +/* + * hfs_init: sets up the mapping list from the afpfile as well + * the default mapping (with or without) an afpfile + */ +void +hfs_init(char *name, Ushort fdflags, Uint hfs_select) +{ + FILE *fp; /* File pointer */ + int count = NUMMAP; /* max number of entries */ + char buf[PATH_MAX]; /* working buffer */ + afpmap *amap; /* mapping entry */ + char *c, + *t, + *e; + int i; + + /* setup number of Unix/HFS filetype - we may wish to not bother */ + if (hfs_select) { + hfs_num = sizeof (hfs_types) / sizeof (struct hfs_type); + + /* + * code below needs to be tidied up + * - most can be made redundant + */ + for (i = 0; i < hfs_num; i++) + hfs_types[i].flags &= ~1; /* 0xfffffffe */ + + for (i = 1; i < hfs_num; i++) + if (!((1 << i) & hfs_select)) + hfs_types[i].flags |= PROBE; + + hselect = hfs_select; + } else + hfs_num = hselect = 0; + +#ifdef DEBUG + for (i = 0; i < hfs_num; i++) + fprintf(stderr, "type = %d flags = %d\n", + i, hfs_types[i].flags); +#endif /* DEBUG */ + + /* min length set to max to start with */ + mlen = PATH_MAX; + +#ifdef USE_MAGIC + /* initialise magic state */ + if (magic_filename) { + magic_state = magic_open(MAGIC_ERROR); + if (magic_state == NULL) + perr("failed to initialise libmagic"); + if (magic_load(magic_state, magic_filename) == -1) { + fprintf(stderr, "failed to open magic file: %s\n", + magic_error(magic_state)); + exit(1); + } + } +#endif /* USE_MAGIC */ + + /* set defaults */ + map_num = last_ent = 0; + + /* allocate memory for the default entry */ + defmap = (afpmap *) e_malloc(sizeof (afpmap)); + + /* set default values */ + defmap->extn = DEFMATCH; + + /* make sure creator and type are 4 chars long */ + strcpy(defmap->type, BLANK); + strcpy(defmap->creator, BLANK); + + e = deftype; + t = defmap->type; + + while (*e && (e - deftype) < CT_SIZE) + *t++ = *e++; + + e = defcreator; + c = defmap->creator; + + while (*e && (e - defcreator) < CT_SIZE) + *c++ = *e++; + + /* length is not important here */ + defmap->elen = 0; + + /* no flags */ + defmap->fdflags = fdflags; + + /* no afpfile - no mappings */ + if (*name == '\0') { + map = NULL; + return; + } + if ((fp = fopen(name, "r")) == NULL) + perr("unable to open mapping file"); + + map = (afpmap **) e_malloc(NUMMAP * sizeof (afpmap *)); + + /* read afpfile line by line */ + while (fgets(buf, PATH_MAX, fp) != NULL) { + /* ignore any comment lines */ + c = tmp; + *c = '\0'; + if (sscanf(buf, "%1s", c) == EOF || *c == '#') + continue; + + /* increase list size if needed */ + if (map_num == count) { + count += NUMMAP; + map = (afpmap **)realloc(map, count * sizeof (afpmap *)); + if (map == NULL) + perr("not enough memory"); + } + /* allocate memory for this entry */ + amap = (afpmap *) e_malloc(sizeof (afpmap)); + + t = amap->type; + c = amap->creator; + + /* extract the info */ + if (sscanf(buf, "%s%*s%*1s%c%c%c%c%*1s%*1s%c%c%c%c%*1s", + tmp, c, c + 1, c + 2, c + 3, + t, t + 1, t + 2, t + 3) != 9) { + fprintf(stderr, + "error scanning afpfile %s - continuing", name); + free(amap); + continue; + } + /* copy the extension found */ + if ((amap->extn = (char *) strdup(tmp)) == NULL) + perr("not enough memory"); + + /* set end-of-string */ + *(t + 4) = *(c + 4) = '\0'; + + /* find the length of the extension */ + amap->elen = strlen(amap->extn); + + /* set flags */ + amap->fdflags = fdflags; + + /* see if we have the default creator/type */ + if (strcmp(amap->extn, DEFMATCH) == 0) { + /* get rid of the old default */ + free(defmap); + /* make this the default */ + defmap = amap; + continue; + } + /* update the smallest extension length */ + mlen = MIN(mlen, amap->elen); + + /* add entry to the list */ + map[map_num++] = amap; + + } + + /* free up some memory */ + if (map_num != count) { + map = (afpmap **) realloc(map, map_num * sizeof (afpmap *)); + if (map == NULL) + perr("not enough memory"); + } +} + +#ifdef USE_MAGIC +static int +try_map_magic(char *whole_name, char **type, /* set type */ + char **creator /* set creator */) +{ + const char * ret = magic_file(magic_state, whole_name); + +#ifdef DEBUG + fprintf(stderr, "magic_file(magic_state, \"%s\"): %s\n", + whole_name, ret ? ret : "NULL"); +#endif + /* + * check that we found a match; ignore results in the + * wrong format (probably due to libmagic's built-in rules) + */ + if (ret && strcspn(ret, " ") == CT_SIZE + && ret[CT_SIZE] == ' ' + && strcspn(ret + CT_SIZE + 1, " ") == CT_SIZE) { + memcpy(tmp_type, ret, CT_SIZE); + tmp_type[CT_SIZE] = 0; + memcpy(tmp_creator, ret + CT_SIZE + 1, CT_SIZE); + tmp_creator[CT_SIZE] = 0; +#ifdef DEBUG + fprintf(stderr, "tmp_type = \"%s\"; tmp_creator = \"%s\"\n", + tmp_type, tmp_creator); +#endif + *type = tmp_type; + *creator = tmp_creator; + return (1); + } + + return (0); +} +#endif /* USE_MAGIC */ + +/* + * map_ext: map a files extension with the list to get type/creator + */ +static void +map_ext(char *name, /* filename */ + char **type, /* set type */ + char **creator, /* set creator */ + short *fdflags, /* set finder flags */ + char *whole_name) +{ + int i; /* loop counter */ + int len; /* filename length */ + afpmap *amap; /* mapping entry */ + const char *ret; + + /* we don't take fdflags from the map or magic file */ + *fdflags = defmap->fdflags; + +#ifdef USE_MAGIC + /* + * if we have a magic file and we want to search it first, + * then try to get a match + */ + if (magic_state && hfs_last == MAP_LAST + && try_map_magic(whole_name, type, creator)) + return; +#endif /* USE_MAGIC */ + + len = strlen(name); + + /* have an afpfile and filename if long enough */ + if (map && len >= mlen) { + /* + * search through the list - we start where we left off + * last time in case this file is of the same type as the + * last one + */ + for (i = 0; i < map_num; i++) { + amap = map[last_ent]; + + /* compare the end of the filename */ +/* if (strcmp((name+len - amap->elen), amap->extn) == 0) { */ + if (strcasecmp((name+len - amap->elen), amap->extn) == 0) { + /* set the required info */ + *type = amap->type; + *creator = amap->creator; + *fdflags = amap->fdflags; + return; + } + /* + * move on to the next entry - wrapping round + * if neccessary + */ + last_ent++; + last_ent %= map_num; + } + } + /* + * if no matches are found, file name too short, or no afpfile, + * then take defaults + */ + *type = defmap->type; + *creator = defmap->creator; + +#ifdef USE_MAGIC + /* + * if we have a magic file and we haven't searched yet, + * then try to get a match + */ + if (magic_state && hfs_last == MAG_LAST) + try_map_magic(whole_name, type, creator); +#endif /* USE_MAGIC */ +} + +void +delete_rsrc_ent(dir_ent *s_entry) +{ + dir_ent *s_entry1 = s_entry->next; + + if (s_entry1 == NULL) + return; + + s_entry->next = s_entry1->next; + s_entry->assoc = NULL; + + free(s_entry1->name); + free(s_entry1->whole_name); + + free(s_entry1); +} + +void +clean_hfs() +{ + if (map) + free(map); + + if (defmap) + free(defmap); + +#ifdef USE_MAGIC + if (magic_state) { + magic_close(magic_state); + magic_state = NULL; + } +#endif /* USE_MAGIC */ +} + +#endif /* APPLE_HYB */ + +void +perr(char *a) +{ +#ifdef USE_LIBSCHILY + if (a) + comerr("%s\n", a); + else + comerr("<no error message given>\n"); +#else + if (a) + fprintf(stderr, "mkhybrid: %s\n", a); + perror("mkhybrid"); + exit(1); +#endif +} diff --git a/genisoimage/apple.h b/genisoimage/apple.h new file mode 100644 index 0000000..685a812 --- /dev/null +++ b/genisoimage/apple.h @@ -0,0 +1,386 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)apple.h 1.7 04/03/02 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */ +/* + * Copyright (c) 1997, 1998, 1999, 2000 James Pearson + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * apple.h: cut down macfile.h from CAP distribution + */ +#ifndef _APPLE_H +#define _APPLE_H + +#include "mactypes.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif /* O_BINARY */ + +#ifdef _WIN32_TEST +#undef UNICODE +#include <windows.h> +#endif /* _WIN32 */ + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a):(b)) +#endif /* MIN */ + +#define CT_SIZE 4 /* Size of type/creator */ +#define NUMMAP 512 /* initial number of maps */ +#define BLANK " " /* blank type/creator */ +#define DEFMATCH "*" /* default mapping extension */ + +typedef struct { + char *extn; /* filename extension */ + int elen; /* length of extension */ + char type[CT_SIZE+1]; /* extension type */ + char creator[CT_SIZE+1]; /* extension creator */ + unsigned short fdflags; /* finder flags */ +} afpmap; + +/* from "data.h" - libhfs routines */ +unsigned long d_toutime(unsigned long); +unsigned long d_dtoutime(long); +long d_getl(unsigned char *); +short d_getw(unsigned char *); + +/* for libfile routines */ +int init_magic(char *); +char * get_magic_match(const char *); + +typedef unsigned char byte; +typedef unsigned char word[2]; +typedef unsigned char dword[4]; + +#define INFOLEN 32 /* Finder info is 32 bytes */ + +typedef struct { + /* base finder information */ + char fdType[4]; /* File type [4] */ + char fdCreator[4]; /* File creator [8] */ + word fdFlags; /* Finder flags [10] */ + word fdLocation[2]; /* File's location [14] */ + word fdFldr; /* File's window [16] */ + /* extended finder information */ + word fdIconID; /* Icon ID [18] */ + word fdUnused[3]; /* Unused [24] */ + byte fdScript; /* Script system used [25] */ + byte fdXFlags; /* Reserved [26] */ + word fdComment; /* Comment ID [28] */ + dword fdPutAway; /* Home directory ID [32] */ +} Finfo; + +typedef struct { + /* base finder information */ + word frRect[4]; /* Folder's rectangle [8] */ + word frFlags; /* Finder flags [10] */ + word frLocation[2]; /* Folder's location [14] */ + word frView; /* Folder's view [16] */ + /* extended finder information */ + word frScroll[2]; /* Folder's scroll position [20] */ + dword frOpenChain; /* ID's of open folders [24] */ + byte frScript; /* Script system used [25] */ + byte frXFlags; /* Reserved [26] */ + word frComment; /* Comment ID [28] */ + dword frPutAway; /* Home directory ID [32] */ +} Dinfo; + +/****** TYPE_CAP ******/ + +/* + * taken from the CAP distribution: + * macfile.h - header file with Macintosh file definitions + * + * AppleTalk package for UNIX (4.2 BSD). + * + * Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the + * City of New York. + * + * Edit History: + * + * Sept 1987 Created by Charlie + * + */ + + +#ifndef USE_MAC_DATES +#define USE_MAC_DATES +#endif /* USE_MAC_DATES */ + +#define MAXCLEN 199 /* max size of a comment string */ +#define FINFOLEN 32 /* Finder info is 32 bytes */ +#define MAXMACFLEN 31 /* max Mac file name length */ + +typedef struct { + byte finderinfo[INFOLEN]; /* Finder info */ + word fi_attr; /* attributes */ +#define FI_MAGIC1 255 + byte fi_magic1; /* was: length of comment */ +#define FI_VERSION 0x10 /* version major 1, minor 0 */ + /* if we have more than 8 versions wer're */ + /* doiong something wrong anyway */ + byte fi_version; /* version number */ +#define FI_MAGIC 0xda + byte fi_magic; /* magic word check */ + byte fi_bitmap; /* bitmap of included info */ +#define FI_BM_SHORTFILENAME 0x1 /* is this included? */ +#define FI_BM_MACINTOSHFILENAME 0x2 /* is this included? */ + byte fi_shortfilename[12+1]; /* possible short file name */ + byte fi_macfilename[32+1]; /* possible macintosh file name */ + byte fi_comln; /* comment length */ + byte fi_comnt[MAXCLEN+1]; /* comment string */ +#ifdef USE_MAC_DATES + byte fi_datemagic; /* sanity check */ +#define FI_MDATE 0x01 /* mtime & utime are valid */ +#define FI_CDATE 0x02 /* ctime is valid */ + byte fi_datevalid; /* validity flags */ + byte fi_ctime[4]; /* mac file create time */ + byte fi_mtime[4]; /* mac file modify time */ + byte fi_utime[4]; /* (real) time mtime was set */ +#endif /* USE_MAC_DATES */ +} FileInfo; + +/* Atribute flags */ +#define FI_ATTR_SETCLEAR 0x8000 /* set-clear attributes */ +#define FI_ATTR_READONLY 0x20 /* file is read-only */ +#define FI_ATTR_ROPEN 0x10 /* resource fork in use */ +#define FI_ATTR_DOPEN 0x80 /* data fork in use */ +#define FI_ATTR_MUSER 0x2 /* multi-user */ +#define FI_ATTR_INVISIBLE 0x1 /* invisible */ + +/**** MAC STUFF *****/ + +/* Flags */ +#define FNDR_fOnDesk 0x1 +#define FNDR_fHasBundle 0x2000 +#define FNDR_fInvisible 0x4000 +/* locations */ +#define FNDR_fTrash -3 /* File in Trash */ +#define FNDR_fDesktop -2 /* File on desktop */ +#define FNDR_fDisk 0 /* File in disk window */ + +/****** TYPE_ESHARE ******/ + +/* + * Information supplied by Jens-Uwe Mager (jum@helios.de) + */ + +#define ES_VERSION 0x0102 +#define ES_MAGIC 0x3681093 +#define ES_INFOLEN 32 +#define ES_INFO_SIZE 512 + +typedef struct { + dword magic; + dword serno; /* written only, never read */ + word version; + word attr; /* invisible... */ + word openMax; /* max number of opens */ + word filler0; + dword backupCleared; /* time backup bit cleared */ + dword id; /* dir/file id */ + dword createTime; /* unix format */ + dword backupTime; /* unix format */ + byte finderinfo[INFOLEN]; /* Finder info */ +} es_FileInfo; + +/****** TYPE_USHARE ******/ + +/* + * similar to the EtherShare layout, but the finder info stuff is different + * info provided by: Phil Sylvester <psylvstr@interaccess.com> + */ + +typedef struct { + byte finderinfo[INFOLEN]; /* Finder info */ + dword btime; /* mac file backup time [36]*/ + byte unknown2[4]; /* ignore [40] */ + dword ctime; /* mac file create time [44]*/ + byte unknown3[8]; /* ignore [52] */ + dword mtime; /* mac file modify time [56]*/ + byte unknown4[456]; /* ignore [512] */ +} us_FileInfo; + +/****** TYPE_DOUBLE, TYPE_SINGLE ******/ + +/* + * Taken from cvt2cap (c) May 1988, Paul Campbell + */ + +typedef struct { + dword id; + dword offset; + dword length; +} a_entry; + +typedef struct { + dword magic; + dword version; + char home[16]; + word nentries; + a_entry entries[1]; +} a_hdr; + +#define A_HDR_SIZE 26 +#define A_ENTRY_SIZE sizeof (a_entry) + +#define A_VERSION1 0x00010000 +#define A_VERSION2 0x00020000 +#define APPLE_SINGLE 0x00051600 +#define APPLE_DOUBLE 0x00051607 +#define ID_DATA 1 +#define ID_RESOURCE 2 +#define ID_NAME 3 +#define ID_FILEI 7 /* v1 */ +#define ID_FILEDATESI 8 /* v2 */ +#define ID_FINDER 9 + +#define A_DATE 16 + +/****** TYPE_MACBIN ******/ +/* + * taken from capit.c by Nigel Perry, np@doc.ic.ac.uk which is adapted + * from unmacbin by John M. Sellens, jmsellens@watdragon.uwaterloo.ca + */ + + +#define MB_NAMELEN 63 /* maximum legal Mac file name length */ +#define MB_SIZE 128 + +/* + * Format of a bin file: + * A bin file is composed of 128 byte blocks. The first block is the + * info_header (see below). Then comes the data fork, null padded to fill the + * last block. Then comes the resource fork, padded to fill the last block. A + * proposal to follow with the text of the Get Info box has not been implemented, + * to the best of my knowledge. Version, zero1 and zero2 are what the receiving + * program looks at to determine if a MacBinary transfer is being initiated. + */ +typedef struct { /* info file header (128 bytes). Unfortunately, these */ + /* longs don't align to word boundaries */ + byte version; /* there is only a version 0 at this time */ + byte nlen; /* Length of filename. */ + byte name[MB_NAMELEN]; /* Filename */ + byte type[4]; /* File type. */ + byte auth[4]; /* File creator. */ + byte flags; /* file flags: LkIvBnSyBzByChIt */ + byte zero1; /* Locked, Invisible,Bundle, System */ + /* Bozo, Busy, Changed, Init */ + byte icon_vert[2]; /* Vertical icon position within window */ + byte icon_horiz[2]; /* Horizontal icon postion in window */ + byte window_id[2]; /* Window or folder ID. */ + byte protect; /* = 1 for protected file, 0 otherwise */ + byte zero2; + byte dflen[4]; /* Data Fork length (bytes) - most sig. */ + byte rflen[4]; /* Resource Fork length byte first */ + byte cdate[4]; /* File's creation date. */ + byte mdate[4]; /* File's "last modified" date. */ + byte ilen[2]; /* GetInfo message length */ + byte flags2; /* Finder flags, bits 0-7 */ + byte unused[14]; + byte packlen[4]; /* length of total files when unpacked */ + byte headlen[2]; /* length of secondary header */ + byte uploadvers; /* Version of MacBinary II that the uploading program is written for */ + byte readvers; /* Minimum MacBinary II version needed to read this file */ + byte crc[2]; /* CRC of the previous 124 bytes */ + byte padding[2]; /* two trailing unused bytes */ +} mb_info; + +/****** TYPE_FE ******/ + +/* Information provided by Mark Weinstein <mrwesq@earthlink.net> */ + +typedef struct { + byte nlen; + byte name[31]; + byte finderinfo[INFOLEN]; /* Finder info */ + byte cdate[4]; + byte mdate[4]; + byte bdate[4]; + byte fileid[4]; + byte sname[8]; + byte ext[3]; + byte pad; +} fe_info; + +#define FE_SIZE 92 + +/****** TYPE_SGI ******/ + +typedef struct { + byte unknown1[8]; + byte finderinfo[INFOLEN]; /* Finder info */ + byte unknown2[214]; + byte name[32]; + byte unknown3[14]; +} sgi_info; + +#define SGI_SIZE 300 + +/****** TYPE_SFM ******/ + +/* + * Information provided by Lou Rieger <lrieger@meridiancg.com> taken from + * an email from Eddie Bowers <eddieb@microsoft.com> + */ + +typedef struct { + byte afpi_Signature[4]; /* Must be 0x00504641 */ + byte afpi_Version[4]; /* Must be 0x00010000 */ + byte afpi_Reserved1[4]; + byte afpi_BackupTime[4]; /* Backup time for the file/dir */ + byte finderinfo[INFOLEN]; /* Finder info */ + byte afpi_ProDosInfo[6]; /* ProDos Info */ + byte afpi_Reserved2[6]; +} sfm_info; + +#define SFM_MAGIC 0x00504641 +#define SFM_VERSION 0x00010000 + +/****** TYPE_DHFS ******/ + +#ifdef IS_MACOS_X + +/* + * Code ideas from 'hfstar' by Marcel Weiher marcel@metaobject.com, + * another GNU hfstar by Torres Vedras paulotex@yahoo.com and + * hfspax by Howard Oakley howard@quercus.demon.co.uk + */ + +#include <sys/attr.h> + +typedef struct { + unsigned long info_length; + struct timespec ctime; + struct timespec mtime; + byte info[32]; +} attrinfo; + +#endif /* IS_MACOS_X */ + +#endif /* _APPLE_H */ diff --git a/genisoimage/apple_driver.8 b/genisoimage/apple_driver.8 new file mode 100644 index 0000000..773a074 --- /dev/null +++ b/genisoimage/apple_driver.8 @@ -0,0 +1,72 @@ +'\" te +.\" To print, first run through tbl +.TH APPLE_DRIVER 8 "18 May 1998" "Version 1.0" +.SH NAME +apple_driver \- extract Macintosh partition label, maps and boot driver +.SH SYNOPSIS +.B apple_driver +CDROM_device > HFS_driver_file +.SH DESCRIPTION +.I Apple_driver +extracts the information from an Apple (or compatible) CD-ROM required +for the +.I \-hfs-boot-file +option to +.IR mkhybrid (1). +.PP +The +.I CDROM_device +is the device name used by the CD-ROM (e.g. /dev/cdrom). +.PP +The format of the HFS driver file is: +.PP +.TS +l l . +HFS CD Label Block 512 bytes +Driver Partition Map (for 2048 byte blocks) 512 bytes +Driver Partition Map (for 512 byte blocks) 512 bytes +Empty 512 bytes +Driver Partition N x 2048 bytes +HFS Partition Boot Block 1024 bytes +.TE +.PP +The Perl script +.I hdisk.pl +can be used to give a listing of what's on a Mac CD. hdisk.pl is part of +hfsutils. +.SH NOTE +By using a driver from an Apple CD and copying Apple software to your CD, +you become liable to obey Apple Computer, Inc. Software License Agreements. + +.SH SEE\ ALSO +.IR mkhybrid (1) +.SH PROGRAMMER +James Pearson (j.pearson@ge.ucl.ac.uk) 18/5/98 +.PP +The driver code (both extracting the driver and creating partitions etc. +is based on code from +.I genisoimage 1.05 PLUS +by Andy Polyakov <appro@fy.chalmers.se> +(see http://fy.chalmers.se/~appro/genisoimage_plus.html) +.PP +This manpage describes the program implementation of +.B +apple_driver +as shipped by the cdrkit distribution. See +.B +http://alioth.debian.org/projects/debburn/ +for details. It is a spinof from the original program distributed by the cdrtools project. However, the cdrtools developers are not involved in the development of this spinoff and therefore shall not be made responsible for any problem caused by it. Do not try to get support for this program by contacting the original authors. +.PP +If you have support questions, send them to +.PP +.B +debburn-devel@lists.alioth.debian.org +.br +.PP +If you have definitely found a bug, send a mail to this list or to +.PP +.B +submit@bugs.debian.org +.br +.PP +writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body. diff --git a/genisoimage/apple_driver.c b/genisoimage/apple_driver.c new file mode 100644 index 0000000..24f8544 --- /dev/null +++ b/genisoimage/apple_driver.c @@ -0,0 +1,190 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)apple_driver.c 1.6 04/03/04 joerg */ +/* + * apple_driver.c: extract Mac partition label, maps and boot driver + * + * Based on Apple_Driver.pl, part of "genisoimage 1.05 PLUS" by Andy Polyakov + * <appro@fy.chalmers.se> (I don't know Perl, so I rewrote it C ...) + * (see http://fy.chalmers.se/~appro/genisoimage_plus.html for details) + * + * usage: apple_driver CDROM_device > HFS_driver_file + * + * The format of the HFS driver file: + * + * HFS CD Label Block 512 bytes + * Driver Partition Map (for 2048 byte blocks) 512 bytes + * Driver Partition Map (for 512 byte blocks) 512 bytes + * Empty 512 bytes + * Driver Partition N x 2048 bytes + * HFS Partition Boot Block 1024 bytes + * + * By extracting a driver from an Apple CD, you become liable to obey + * Apple Computer, Inc. Software License Agreements. + * + * James Pearson 17/5/98 + */ + +#include <mconfig.h> +#include "genisoimage.h" +#include <mac_label.h> +#include <schily.h> + +int get_732(char *p); +int get_722(char *p); + +int +get_732(char *p) +{ + return ((p[3] & 0xff) + | ((p[2] & 0xff) << 8) + | ((p[1] & 0xff) << 16) + | ((p[0] & 0xff) << 24)); +} + +int +get_722(char *p) +{ + return ((p[1] & 0xff) + | ((p[0] & 0xff) << 8)); +} + +#if 0 +EXPORT int +main(argc, argv) + int argc; + char **argv; +{ + FILE *fp; + MacLabel *mac_label; + MacPart *mac_part; + unsigned char Block0[HFS_BLOCKSZ]; + unsigned char block[SECTOR_SIZE]; + unsigned char bootb[2*HFS_BLOCKSZ]; + unsigned char pmBlock512[HFS_BLOCKSZ]; + unsigned int sbBlkSize; + unsigned int pmPyPartStart; + unsigned int pmPartStatus; + unsigned int pmMapBlkCnt; + int have_boot = 0, have_hfs = 0; + int hfs_start; + int i, j; + + + save_args(argc, argv); + + if (argc != 2) + comerrno(EX_BAD, "Usage: %s device-path", argv[0]); + + if ((fp = fopen(argv[1], "rb")) == NULL) + comerr("Can't open '%s'.", argv[1]); + + if (fread(Block0, 1, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ) + comerr("Can't read '%s'.", argv[1]); + + mac_label = (MacLabel *)Block0; + mac_part = (MacPart *)block; + + sbBlkSize = get_722((char *)mac_label->sbBlkSize); + + if (! IS_MAC_LABEL(mac_label) || sbBlkSize != SECTOR_SIZE) + comerrno(EX_BAD, "%s is not a bootable Mac disk", argv[1]); + + i = 1; + do { + if (fseek(fp, i * HFS_BLOCKSZ, SEEK_SET) != 0) + comerr("Ccan't seek %s", argv[1]); + + if (fread(block, 1, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ) + comerr("Can't read '%s'.", argv[1]); + + pmMapBlkCnt = get_732((char *)mac_part->pmMapBlkCnt); + + if (!have_boot && strncmp((char *)mac_part->pmPartType, pmPartType_2, 12) == 0) { + hfs_start = get_732((char *)mac_part->pmPyPartStart); + + fprintf(stderr, "%s: found 512 driver partition (at block %d)\n", argv[0], hfs_start); + memcpy(pmBlock512, block, HFS_BLOCKSZ); + have_boot = 1; + } + + if (!have_hfs && strncmp((char *)mac_part->pmPartType, pmPartType_4, 9) == 0) { + + hfs_start = get_732((char *)mac_part->pmPyPartStart); + + if (fseek(fp, hfs_start*HFS_BLOCKSZ, SEEK_SET) != 0) + comerr("Can't seek '%s'.", argv[1]); + + if (fread(bootb, 2, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ) + comerr("Can't read '%s'.", argv[1]); + + if (get_722((char *)bootb) == 0x4c4b) { + + fprintf(stderr, "%s: found HFS partition (at blk %d)\n", argv[0], hfs_start); + have_hfs = 1; + } + } + } while (i++ < pmMapBlkCnt); + + if (!have_hfs || !have_boot) + comerrno(EX_BAD, "%s is not a bootable Mac disk", argv[1]); + + i = 1; + + do { + if (fseek(fp, i*sbBlkSize, SEEK_SET) != 0) + comerr("Can't seek '%s'.", argv[1]); + + if (fread(block, 1, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ) + comerr("Can't read '%s'.", argv[1]); + + pmMapBlkCnt = get_732((char *)mac_part->pmMapBlkCnt); + + if (strncmp((char *)mac_part->pmPartType, pmPartType_2, 12) == 0) { + + int start, num; + + fprintf(stderr, "%s: extracting %s ", argv[0], mac_part->pmPartType); + start = get_732((char *)mac_part->pmPyPartStart); + num = get_732((char *)mac_part->pmPartBlkCnt); + fwrite(Block0, 1, HFS_BLOCKSZ, stdout); + fwrite(block, 1, HFS_BLOCKSZ, stdout); + fwrite(pmBlock512, 1, HFS_BLOCKSZ, stdout); + memset(block, 0, HFS_BLOCKSZ); + fwrite(block, 1, HFS_BLOCKSZ, stdout); + + if (fseek(fp, start*sbBlkSize, SEEK_SET) != 0) + comerr("Can't seek '%s'.", argv[1]); + + for (j = 0; j < num; j++) { + if (fread(block, 1, sbBlkSize, fp) != sbBlkSize) + comerr("Can't read '%s'.", argv[1]); + + fwrite(block, 1, sbBlkSize, stdout); + fprintf(stderr, "."); + } + fprintf(stderr, "\n"); + + fwrite(bootb, 2, HFS_BLOCKSZ, stdout); + fclose(fp); + exit(0); + } + + if (!IS_MAC_PART(mac_part)) + comerrno(EX_BAD, "Unable to find boot partition"); + + } while (i++ < pmMapBlkCnt); + + return (0); +} +#endif diff --git a/genisoimage/boot-alpha.c b/genisoimage/boot-alpha.c new file mode 100644 index 0000000..cfd4862 --- /dev/null +++ b/genisoimage/boot-alpha.c @@ -0,0 +1,137 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* + * Program boot-alpha.c - Handle Linux alpha boot extensions to iso9660. + * + * Written by Steve McIntyre <steve@einval.com> June 2004 + * + * Heavily inspired by isomarkboot by David Mosberger in 1996. + * + * Copyright 2004 Steve McIntyre + * + * 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 <mconfig.h> +#include "genisoimage.h" +#include <fctldefs.h> +#include <utypes.h> +#include <intcvt.h> +#include "match.h" +#include "diskmbr.h" +#include "bootinfo.h" +#include <schily.h> +#include "endianconv.h" + + int add_boot_alpha_filename(char *filename); +static int boot_alpha_write(FILE *outfile); +static int boot_alpha_hppa_write(FILE *outfile); +static char *boot_file_name = NULL; + +unsigned long long alpha_hppa_boot_sector[256]; /* One (ISO) sector */ +int boot_sector_initialized = 0; + +#define BOOT_STRING "Linux/Alpha aboot for ISO filesystem." + +/* Simple function: store the filename to be used later when we need + to find the boot file */ +extern int add_boot_alpha_filename(char *filename) +{ + boot_file_name = filename; + return 0; +} + +static int boot_alpha_write(FILE *outfile) +{ + struct directory_entry *boot_file; /* Boot file we need to search for */ + unsigned long length = 0; + unsigned long extent = 0; + + if (!boot_sector_initialized) { + memset(alpha_hppa_boot_sector, 0, sizeof(alpha_hppa_boot_sector)); + boot_sector_initialized = 1; + } + + /* Write the text header into the boot sector */ + strcpy((char *)alpha_hppa_boot_sector, BOOT_STRING); + + /* Find the dir entry for the boot file by walking our file list */ + boot_file = search_tree_file(root, boot_file_name); + if (!boot_file) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Uh oh, I cant find the Alpha boot file '%s'!\n", + boot_file_name); +#else + fprintf(stderr, "Uh oh, I cant find the Alpha boot file '%s'!\n", + boot_file_name); + exit(1); +#endif + } + + /* Grab the ISO start sector and length from the dir entry. ISO + uses 2048-byte sectors, but we convert to 512-byte sectors here + for the sake of the firmware */ + extent = get_733(boot_file->isorec.extent); + extent *= 4; + + length = get_733(boot_file->isorec.size); + length /= 512; /* I'm sure we should take account of any overlap + here, but I'm copying what isomarkboot + does. Maybe the boot files are specified to be + exact multiples of 512 bytes? */ + + fprintf(stderr, "Found alpha boot image %s: using extent %lu, #blocks %lu\n", + boot_file_name, extent, length); + + /* Now write those values into the appropriate area of the boot + sector in LITTLE ENDIAN format. */ + write_le64(length, (unsigned char *)&alpha_hppa_boot_sector[60]); + write_le64(extent, (unsigned char *)&alpha_hppa_boot_sector[61]); + + return 0; +} + +static int boot_alpha_hppa_write(FILE *outfile) +{ + unsigned long long sum = 0; + int i = 0; + + /* Now generate a checksum of the first 504 bytes of the boot + sector and place it in alpha_hppa_boot_sector[63]. Isomarkboot currently + gets this wrong and will not work on big-endian systems! */ + for (i = 0; i < 63; i++) + sum += read_le64((unsigned char *)&alpha_hppa_boot_sector[i]); + + write_le64(sum, (unsigned char *)&alpha_hppa_boot_sector[63]); + + jtwrite(alpha_hppa_boot_sector, sizeof(alpha_hppa_boot_sector), 1, 0, FALSE); + xfwrite(alpha_hppa_boot_sector, sizeof(alpha_hppa_boot_sector), 1, outfile, 0, FALSE); + last_extent_written++; + + return 0; +} + +struct output_fragment alphaboot_desc = {NULL, NULL, NULL, boot_alpha_write, "alpha boot block"}; +struct output_fragment alpha_hppa_boot_desc = {NULL, oneblock_size, NULL, boot_alpha_hppa_write, "alpha/hppa boot block"}; diff --git a/genisoimage/boot-hppa.c b/genisoimage/boot-hppa.c new file mode 100644 index 0000000..5f3bd1c --- /dev/null +++ b/genisoimage/boot-hppa.c @@ -0,0 +1,207 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* + * Program boot-hppa.c - Handle HPPA boot extensions to iso9660. + * + * Written by Steve McIntyre <steve@einval.com> June 2004. + * + * Heavily inspired by palo: + * + **************************************************************************** + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) Hewlett-Packard (Paul Bame) paul_bame@hp.com + * + **************************************************************************** + * Copyright 2004 Steve McIntyre + * + * 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 <mconfig.h> +#include "genisoimage.h" +#include <fctldefs.h> +#include <utypes.h> +#include <intcvt.h> +#include "match.h" +#include "diskmbr.h" +#include "bootinfo.h" +#include <schily.h> +#include "endianconv.h" + +extern long long alpha_hppa_boot_sector[256]; +extern int boot_sector_initialized; + +int add_boot_hppa_cmdline(char *cmdline); +int add_boot_hppa_kernel_32(char *filename); +int add_boot_hppa_kernel_64(char *filename); +int add_boot_hppa_bootloader(char *filename); +int add_boot_hppa_ramdisk(char *filename); + +static int boot_hppa_write(FILE *outfile); + +static char *hppa_cmdline = NULL; +static char *hppa_kernel_32 = NULL; +static char *hppa_kernel_64 = NULL; +static char *hppa_bootloader = NULL; +static char *hppa_ramdisk = NULL; + +/* Simple function: store the filename to be used later when we need + to find the boot file */ +extern int add_boot_hppa_cmdline(char *cmdline) +{ + char *ptr = NULL; + hppa_cmdline = strdup(cmdline); + ptr = hppa_cmdline; + while (*ptr) + { + if (',' == *ptr) + *ptr = ' '; + ptr++; + } + return 0; +} + +/* Simple function: store the filename to be used later when we need + to find the boot file */ +extern int add_boot_hppa_kernel_32(char *filename) +{ + hppa_kernel_32 = filename; + return 0; +} + +/* Simple function: store the filename to be used later when we need + to find the boot file */ +extern int add_boot_hppa_kernel_64(char *filename) +{ + hppa_kernel_64 = filename; + return 0; +} + +/* Simple function: store the filename to be used later when we need + to find the boot file */ +extern int add_boot_hppa_bootloader(char *filename) +{ + hppa_bootloader = filename; + return 0; +} + +/* Simple function: store the filename to be used later when we need + to find the boot file */ +extern int add_boot_hppa_ramdisk(char *filename) +{ + hppa_ramdisk = filename; + return 0; +} + +static void exit_fatal(char *type, char *filename) +{ +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Uh oh, I can't find the %s '%s'!\n", + type, filename); +#else + fprintf(stderr, "Uh oh, I can't find the %s '%s'!\n", + type, filename); + exit(1); +#endif +} + +static int boot_hppa_write(FILE *outfile) +{ + struct directory_entry *boot_file; /* Boot file we need to search for */ + unsigned long length = 0; + unsigned long extent = 0; + unsigned char *boot_sector = (unsigned char *) alpha_hppa_boot_sector; + int i = 0; + + if (!boot_sector_initialized) { + memset(alpha_hppa_boot_sector, 0, sizeof(alpha_hppa_boot_sector)); + boot_sector_initialized = 1; + } + + printf("Address is: %p\n",alpha_hppa_boot_sector); + + boot_sector[0] = 0x80; /* magic */ + boot_sector[1] = 0x00; /* magic */ + boot_sector[2] = 'P'; + boot_sector[3] = 'A'; + boot_sector[4] = 'L'; + boot_sector[5] = 'O'; + boot_sector[6] = 0x00; + boot_sector[7] = 0x04; /* version */ + + /* Find the dir entry for the 32-bit kernel by walking our file list */ + boot_file = search_tree_file(root, hppa_kernel_32); + if (!boot_file) + exit_fatal("HPPA 32-bit kernel", hppa_kernel_32); + extent = 2048 * get_733(boot_file->isorec.extent); + length = get_733(boot_file->isorec.size); + fprintf(stderr, "Found hppa 32-bit kernel %s: using extent %lu (0x%lX), size %lu (0x%lX)\n", + hppa_kernel_32, extent, extent, length, length); + write_be32(extent, &boot_sector[8]); + write_be32(length, &boot_sector[12]); + + /* Find the dir entry for the ramdisk by walking our file list */ + boot_file = search_tree_file(root, hppa_ramdisk); + if (!boot_file) + exit_fatal("HPPA ramdisk", hppa_ramdisk); + extent = 2048 * get_733(boot_file->isorec.extent); + length = get_733(boot_file->isorec.size); + fprintf(stderr, "Found hppa ramdisk %s: using extent %lu (0x%lX), size %lu (0x%lX)\n", + hppa_ramdisk, extent, extent, length, length); + write_be32(extent, &boot_sector[16]); + write_be32(length, &boot_sector[20]); + + /* Now the commandline */ + snprintf((char *)&boot_sector[24], 127, "%s", hppa_cmdline); + + /* Find the dir entry for the 64-bit kernel by walking our file list */ + boot_file = search_tree_file(root, hppa_kernel_64); + if (!boot_file) + exit_fatal("HPPA 64-bit kernel", hppa_kernel_64); + extent = 2048 * get_733(boot_file->isorec.extent); + length = get_733(boot_file->isorec.size); + fprintf(stderr, "Found hppa 64-bit kernel %s: using extent %lu (0x%lX), size %lu (0x%lX)\n", + hppa_kernel_64, extent, extent, length, length); + write_be32(extent, &boot_sector[232]); + write_be32(length, &boot_sector[236]); + + /* Find the dir entry for the IPL by walking our file list */ + boot_file = search_tree_file(root, hppa_bootloader); + if (!boot_file) + exit_fatal("HPPA bootloader", hppa_bootloader); + extent = 2048 * get_733(boot_file->isorec.extent); + length = get_733(boot_file->isorec.size); + fprintf(stderr, "Found hppa bootloader %s: using extent %lu (0x%lX), size %lu (0x%lX)\n", + hppa_bootloader, extent, extent, length, length); + write_be32(extent, &boot_sector[240]); + write_be32(length, &boot_sector[244]); + + return 0; +} + +struct output_fragment hppaboot_desc = {NULL, NULL, NULL, boot_hppa_write, "hppa boot block"}; diff --git a/genisoimage/boot-mips.c b/genisoimage/boot-mips.c new file mode 100644 index 0000000..956b94f --- /dev/null +++ b/genisoimage/boot-mips.c @@ -0,0 +1,341 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* + * Program boot-mips.c - Handle big-endian boot extensions to iso9660. + * + * Written by Steve McIntyre <steve@einval.com> June 2004 + * + * Heavily inspired by / borrowed from genisovh: + * + * Copyright: (C) 2002 by Florian Lohoff <flo@rfc822.org> + * (C) 2004 by Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de> + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, Version 2, as published by the + * Free Software Foundation. + * + * Format for volume header information + * + * The volume header is a block located at the beginning of all disk + * media (sector 0). It contains information pertaining to physical + * device parameters and logical partition information. + * + * The volume header is manipulated by disk formatters/verifiers, + * partition builders (e.g. fx, dvhtool, and mkfs), and disk drivers. + * + * Previous versions of IRIX wrote a copy of the volume header is + * located at sector 0 of each track of cylinder 0. These copies were + * never used, and reduced the capacity of the volume header to hold large + * files, so this practice was discontinued. + * The volume header is constrained to be less than or equal to 512 + * bytes long. A particular copy is assumed valid if no drive errors + * are detected, the magic number is correct, and the 32 bit 2's complement + * of the volume header is correct. The checksum is calculated by initially + * zeroing vh_csum, summing the entire structure and then storing the + * 2's complement of the sum. Thus a checksum to verify the volume header + * should be 0. + * + * The error summary table, bad sector replacement table, and boot blocks are + * located by searching the volume directory within the volume header. + * + * Tables are sized simply by the integral number of table records that + * will fit in the space indicated by the directory entry. + * + * The amount of space allocated to the volume header, replacement blocks, + * and other tables is user defined when the device is formatted. + */ + +#include <inttypes.h> +#ifndef MIN +#define MIN(a,b) ( (a<b) ? a : b ) +#endif + +/* + * device parameters are in the volume header to determine mapping + * from logical block numbers to physical device addresses + * + * Linux doesn't care ... + */ +struct device_parameters { + uint8_t dp_skew; /* spiral addressing skew */ + uint8_t dp_gap1; /* words of 0 before header */ + uint8_t dp_gap2; /* words of 0 between hdr and data */ + uint8_t dp_spares_cyl; /* This is for drives (such as SCSI + that support zone oriented sparing, where the zone is larger + than one track. It gets subracteded from the cylinder size + ( dp_trks0 * dp_sec) when doing partition size calculations */ + uint16_t dp_cyls; /* number of usable cylinders (i.e., + doesn't include cylinders reserved by the drive for badblocks, + etc.). For drives with variable geometry, this number may be + decreased so that: + dp_cyls * ((dp_heads * dp_trks0) - dp_spares_cyl) <= actualcapacity + This happens on SCSI drives such as the Wren IV and Toshiba 156 + Also see dp_cylshi below */ + uint16_t dp_shd0; /* starting head vol 0 */ + uint16_t dp_trks0; /* number of tracks / cylinder vol 0*/ + uint8_t dp_ctq_depth; /* Depth of CTQ queue */ + uint8_t dp_cylshi; /* high byte of 24 bits of cylinder count */ + uint16_t dp_unused; /* not used */ + uint16_t dp_secs; /* number of sectors/track */ + uint16_t dp_secbytes; /* length of sector in bytes */ + uint16_t dp_interleave; /* sector interleave */ + int32_t dp_flags; /* controller characteristics */ + int32_t dp_datarate; /* bytes/sec for kernel stats */ + int32_t dp_nretries; /* max num retries on data error */ + int32_t dp_mspw; /* ms per word to xfer, for iostat */ + uint16_t dp_xgap1; /* Gap 1 for xylogics controllers */ + uint16_t dp_xsync; /* sync delay for xylogics controllers */ + uint16_t dp_xrdly; /* read delay for xylogics controllers */ + uint16_t dp_xgap2; /* gap 2 for xylogics controllers */ + uint16_t dp_xrgate; /* read gate for xylogics controllers */ + uint16_t dp_xwcont; /* write continuation for xylogics */ +}; + +/* + * Device characterization flags + * (dp_flags) + */ +#define DP_SECTSLIP 0x00000001 /* sector slip to spare sector */ +#define DP_SECTFWD 0x00000002 /* forward to replacement sector */ +#define DP_TRKFWD 0x00000004 /* forward to replacement track */ +#define DP_MULTIVOL 0x00000008 /* multiple volumes per spindle */ +#define DP_IGNOREERRORS 0x00000010 /* transfer data regardless of errors */ +#define DP_RESEEK 0x00000020 /* recalibrate as last resort */ +#define DP_CTQ_EN 0x00000040 /* enable command tag queueing */ + +/* + * Boot blocks, bad sector tables, and the error summary table, are located + * via the volume_directory. + */ +#define VDNAMESIZE 8 + +struct volume_directory { + int8_t vd_name[VDNAMESIZE]; /* name */ + int32_t vd_lbn; /* logical block number */ + int32_t vd_nbytes; /* file length in bytes */ +}; + +/* + * partition table describes logical device partitions + * (device drivers examine this to determine mapping from logical units + * to cylinder groups, device formatters/verifiers examine this to determine + * location of replacement tracks/sectors, etc) + * + * NOTE: pt_firstlbn SHOULD BE CYLINDER ALIGNED + */ +struct partition_table { /* one per logical partition */ + int32_t pt_nblks; /* # of logical blks in partition */ + int32_t pt_firstlbn; /* first lbn of partition */ + int32_t pt_type; /* use of partition */ +}; + +#define PTYPE_VOLHDR 0 /* partition is volume header */ +#define PTYPE_TRKREPL 1 /* partition is used for repl trks */ +#define PTYPE_SECREPL 2 /* partition is used for repl secs */ +#define PTYPE_RAW 3 /* partition is used for data */ +#define PTYPE_BSD42 4 /* partition is 4.2BSD file system */ +#define PTYPE_BSD 4 /* partition is 4.2BSD file system */ +#define PTYPE_SYSV 5 /* partition is SysV file system */ +#define PTYPE_VOLUME 6 /* partition is entire volume */ +#define PTYPE_EFS 7 /* partition is sgi EFS */ +#define PTYPE_LVOL 8 /* partition is part of a logical vol */ +#define PTYPE_RLVOL 9 /* part of a "raw" logical vol */ +#define PTYPE_XFS 10 /* partition is sgi XFS */ +#define PTYPE_XFSLOG 11 /* partition is sgi XFS log */ +#define PTYPE_XLV 12 /* partition is part of an XLV vol */ +#define PTYPE_XVM 13 /* partition is sgi XVM */ +#define PTYPE_LSWAP 0x82 /* partition is Linux swap */ +#define PTYPE_LINUX 0x83 /* partition is Linux native */ +#define NPTYPES 16 + +#define VHMAGIC 0xbe5a941 /* randomly chosen value */ +#define NPARTAB 16 /* 16 unix partitions */ +#define NVDIR 15 /* max of 15 directory entries */ +#define BFNAMESIZE 16 /* max 16 chars in boot file name */ + +/* Partition types for ARCS */ +#define NOT_USED 0 /* Not used */ +#define FAT_SHORT 1 /* FAT filesystem, 12-bit FAT entries */ +#define FAT_LONG 4 /* FAT filesystem, 16-bit FAT entries */ +#define EXTENDED 5 /* extended partition */ +#define HUGE 6 /* huge partition- MS/DOS 4.0 and later */ + +/* Active flags for ARCS */ +#define BOOTABLE 0x00; +#define NOT_BOOTABLE 0x80; + +struct volume_header { + int32_t vh_magic; /* identifies volume header */ + int16_t vh_rootpt; /* root partition number */ + int16_t vh_swappt; /* swap partition number */ + int8_t vh_bootfile[BFNAMESIZE]; /* name of file to boot */ + struct device_parameters vh_dp; /* device parameters */ + struct volume_directory vh_vd[NVDIR]; /* other vol hdr contents */ + struct partition_table vh_pt[NPARTAB]; /* device partition layout */ + int32_t vh_csum; /* volume header checksum */ + int32_t vh_fill; /* fill out to 512 bytes */ + char pad[1536]; /* pad out to 2048 */ +}; + +#include <mconfig.h> +#include "genisoimage.h" +#include <fctldefs.h> +#include <utypes.h> +#include <intcvt.h> +#include "match.h" +#include "diskmbr.h" +#include "bootinfo.h" +#include <schily.h> +#include "endianconv.h" + +int add_boot_mips_filename(char *filename); + +static int boot_mips_write(FILE *outfile); + +#define MAX_NAMES 15 +static char *boot_mips_filename[MAX_NAMES] = +{ + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL +}; + +static int boot_mips_num_files = 0; + +#define SECTORS_PER_TRACK 32 +#define BYTES_PER_SECTOR 512 + +int add_boot_mips_filename(char *filename) +{ + if (boot_mips_num_files < MAX_NAMES) + { + boot_mips_filename[boot_mips_num_files] = filename; + boot_mips_num_files++; + } + + else + { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Too many MIPS boot files!\n"); +#else + fprintf(stderr, "Too many MIPS boot files!\n"); + exit(1); +#endif + } + return 0; +} + +static void vh_calc_checksum(struct volume_header *vh) +{ + uint32_t newsum = 0; + unsigned char *buffer = (unsigned char *)vh; + unsigned int i; + + vh->vh_csum = 0; + + for(i = 0; i < sizeof(struct volume_header); i += 4) + newsum -= read_be32(&buffer[i]); + + write_be32(newsum, (unsigned char *)&vh->vh_csum); +} + +static char *file_base_name(char *path) +{ + char *endptr = path; + char *ptr = path; + + while (*ptr != '\0') + { + if ('/' == *ptr) + endptr = ++ptr; + else + ++ptr; + } + return endptr; +} + +static int boot_mips_write(FILE *outfile) +{ + struct directory_entry *boot_file; /* Boot file we need to search for */ + unsigned long length = 0; + unsigned long extent = 0; + int i; + struct volume_header vh; + unsigned long long iso_size = 0; + char *filename = NULL; + + memset(&vh, 0, sizeof(vh)); + + iso_size = last_extent * 2048; + + write_be32(VHMAGIC, (unsigned char *)&vh.vh_magic); + + /* Values from an IRIX cd */ + write_be16(BYTES_PER_SECTOR, (unsigned char *)&vh.vh_dp.dp_secbytes); + write_be16(SECTORS_PER_TRACK, (unsigned char *)&vh.vh_dp.dp_secs); + write_be32(DP_RESEEK|DP_IGNOREERRORS|DP_TRKFWD, (unsigned char *)&vh.vh_dp.dp_flags); + write_be16(1, (unsigned char *)&vh.vh_dp.dp_trks0); + + write_be16((iso_size + BYTES_PER_SECTOR - 1) / (SECTORS_PER_TRACK * BYTES_PER_SECTOR), + (unsigned char *)&vh.vh_dp.dp_cyls); + + for(i = 0; i < boot_mips_num_files; i++) + { + boot_file = search_tree_file(root, boot_mips_filename[i]); + + if (!boot_file) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Uh oh, I cant find the MIPS boot file '%s'!\n", + boot_mips_filename[i]); +#else + fprintf(stderr, "Uh oh, I cant find the MIPS boot file '%s'!\n", + boot_mips_filename[i]); + exit(1); +#endif + } + + extent = get_733(boot_file->isorec.extent) * 4; + length = ((get_733(boot_file->isorec.size) + 2047) / 2048) * 2048; + filename = file_base_name(boot_mips_filename[i]); + + strncpy((char *)vh.vh_vd[i].vd_name, filename, MIN(VDNAMESIZE, strlen(filename))); + write_be32(extent, (unsigned char *)&vh.vh_vd[i].vd_lbn); + write_be32(length, (unsigned char *)&vh.vh_vd[i].vd_nbytes); + + fprintf(stderr, "Found mips boot image %s, using extent %lu (0x%lX), #blocks %lu (0x%lX)\n", + filename, extent, extent, length, length); + } + + /* Create volume partition on whole cd iso */ + write_be32((iso_size + (BYTES_PER_SECTOR - 1))/ BYTES_PER_SECTOR, (unsigned char *)&vh.vh_pt[10].pt_nblks); + write_be32(0, (unsigned char *)&vh.vh_pt[10].pt_firstlbn); + write_be32(PTYPE_VOLUME, (unsigned char *)&vh.vh_pt[10].pt_type); + + /* Create volume header partition, also on WHOLE cd iso */ + write_be32((iso_size + (BYTES_PER_SECTOR - 1))/ BYTES_PER_SECTOR, (unsigned char *)&vh.vh_pt[8].pt_nblks); + write_be32(0, (unsigned char *)&vh.vh_pt[8].pt_firstlbn); + write_be32(PTYPE_VOLHDR, (unsigned char *)&vh.vh_pt[8].pt_type); + + /* Create checksum */ + vh_calc_checksum(&vh); + + jtwrite(&vh, sizeof(vh), 1, 0, FALSE); + xfwrite(&vh, sizeof(vh), 1, outfile, 0, FALSE); + last_extent_written++; + + return 0; +} + +struct output_fragment mipsboot_desc = {NULL, oneblock_size, NULL, boot_mips_write, "MIPS boot block"}; diff --git a/genisoimage/boot-mipsel.c b/genisoimage/boot-mipsel.c new file mode 100644 index 0000000..3d8ca65 --- /dev/null +++ b/genisoimage/boot-mipsel.c @@ -0,0 +1,259 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* + * Program boot-mipsel.c - Handle Mipsel boot extensions to iso9660. + * + * Written by Steve McIntyre <steve@einval.com> (2004). + * + * Heavily inspired by / borrowed from delo: + * + * Copyright: (C) 2002 by Florian Lohoff <flo@rfc822.org> + * (C) 2004 by Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de> + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, Version 2, as published by the + * Free Software Foundation. + * + * Format for volume header information + * + * The volume header is a block located at the beginning of all disk + * media (sector 0). It contains information pertaining to physical + * device parameters and logical partition information. + * + * The volume header is manipulated by disk formatters/verifiers, + * partition builders (e.g. fx, dvhtool, and mkfs), and disk drivers. + * + * Previous versions of IRIX wrote a copy of the volume header is + * located at sector 0 of each track of cylinder 0. These copies were + * never used, and reduced the capacity of the volume header to hold large + * files, so this practice was discontinued. + * The volume header is constrained to be less than or equal to 512 + * bytes long. A particular copy is assumed valid if no drive errors + * are detected, the magic number is correct, and the 32 bit 2's complement + * of the volume header is correct. The checksum is calculated by initially + * zeroing vh_csum, summing the entire structure and then storing the + * 2's complement of the sum. Thus a checksum to verify the volume header + * should be 0. + * + * The error summary table, bad sector replacement table, and boot blocks are + * located by searching the volume directory within the volume header. + * + * Tables are sized simply by the integral number of table records that + * will fit in the space indicated by the directory entry. + * + * The amount of space allocated to the volume header, replacement blocks, + * and other tables is user defined when the device is formatted. + */ + +#include <mconfig.h> +#include "genisoimage.h" +#include <fctldefs.h> +#include <utypes.h> +#include <intcvt.h> +#include "match.h" +#include "diskmbr.h" +#include "bootinfo.h" +#include <schily.h> +#include "endianconv.h" +#include <errno.h> +#include <glibc_elf.h> + +int add_boot_mipsel_filename(char *filename); +static int boot_mipsel_write(FILE *outfile); + +static char *boot_file_name = NULL; + +#define MAX_MAPS 51 +#define DEC_BOOT_MAGIC 0x02757a +#define HD_SECTOR_SIZE 512 + +/* Those were stolen from linux kernel headers. */ + +struct extent { + uint32_t count; + uint32_t start; +} +#ifdef __GNUC__ +__attribute__((packed)) +#endif + ; + +struct dec_bootblock { + int8_t pad[8]; + int32_t magic; /* We are a DEC BootBlock */ + int32_t mode; /* 0: Single extent, 1: Multi extent boot */ + int32_t loadAddr; /* Load below kernel */ + int32_t execAddr; /* And exec there */ + struct extent bootmap[MAX_MAPS]; +} +#ifdef __GNUC__ +__attribute__((packed)) +#endif + ; + +static void swap_in_elf32_ehdr(Elf32_Ehdr *ehdr) +{ + ehdr->e_type = read_le16((unsigned char *)&ehdr->e_type); + ehdr->e_machine = read_le16((unsigned char *)&ehdr->e_machine); + ehdr->e_version = read_le32((unsigned char *)&ehdr->e_version); + ehdr->e_entry = read_le32((unsigned char *)&ehdr->e_entry); + ehdr->e_phoff = read_le32((unsigned char *)&ehdr->e_phoff); + ehdr->e_shoff = read_le32((unsigned char *)&ehdr->e_shoff); + ehdr->e_flags = read_le32((unsigned char *)&ehdr->e_flags); + ehdr->e_ehsize = read_le16((unsigned char *)&ehdr->e_ehsize); + ehdr->e_phentsize = read_le16((unsigned char *)&ehdr->e_phentsize); + ehdr->e_phnum = read_le16((unsigned char *)&ehdr->e_phnum); + ehdr->e_shentsize = read_le16((unsigned char *)&ehdr->e_shentsize); + ehdr->e_shnum = read_le16((unsigned char *)&ehdr->e_shnum); + ehdr->e_shstrndx = read_le16((unsigned char *)&ehdr->e_shstrndx); +} + +static void swap_in_elf32_phdr(Elf32_Phdr *phdr) +{ + phdr->p_type = read_le32((unsigned char *)&phdr->p_type); + phdr->p_offset = read_le32((unsigned char *)&phdr->p_offset); + phdr->p_vaddr = read_le32((unsigned char *)&phdr->p_vaddr); + phdr->p_paddr = read_le32((unsigned char *)&phdr->p_paddr); + phdr->p_filesz = read_le32((unsigned char *)&phdr->p_filesz); + phdr->p_memsz = read_le32((unsigned char *)&phdr->p_memsz); + phdr->p_flags = read_le32((unsigned char *)&phdr->p_flags); + phdr->p_align = read_le32((unsigned char *)&phdr->p_align); +} + +/* Simple function: store the filename to be used later when we need + to find the boot file */ +extern int add_boot_mipsel_filename(char *filename) +{ + boot_file_name = filename; + return 0; +} + +/* Parse the ELF header of the boot loaded to work out the load + address and exec address */ +static int parse_boot_file(char *filename, int32_t *loadaddr, int32_t *execaddr, int32_t *offset, int32_t *count) +{ + int error = 0; + FILE *loader = NULL; + Elf32_Ehdr ehdr; + Elf32_Phdr phdr; + + loader = fopen(filename, "rb"); + if (!loader) + return errno; + + error = fread(&ehdr, sizeof(ehdr), 1, loader); + if (1 != error) + return EIO; + + swap_in_elf32_ehdr(&ehdr); + if (!(ehdr.e_ident[EI_MAG0] == ELFMAG0 + && ehdr.e_ident[EI_MAG1] == ELFMAG1 + && ehdr.e_ident[EI_MAG2] == ELFMAG2 + && ehdr.e_ident[EI_MAG3] == ELFMAG3 + && ehdr.e_ident[EI_CLASS] == ELFCLASS32 + && ehdr.e_ident[EI_DATA] == ELFDATA2LSB + && ehdr.e_ident[EI_VERSION] == EV_CURRENT + && ehdr.e_type == ET_EXEC + && ehdr.e_machine == EM_MIPS + && ehdr.e_version == EV_CURRENT)) + { + fprintf(stderr, "Sorry, %s is not a MIPS ELF32 little endian file", filename); + return EINVAL; + } + if (ehdr.e_phnum != 1) + { + fprintf(stderr, "Sorry, %s has more than one ELF segment", filename); + return EINVAL; + } + fseek(loader, ehdr.e_phoff, SEEK_SET); + error = fread(&phdr, sizeof(phdr), 1, loader); + if (1 != error) + return EIO; + + *loadaddr = phdr.p_vaddr; + *execaddr = ehdr.e_entry; + *offset = (phdr.p_offset + HD_SECTOR_SIZE - 1) / HD_SECTOR_SIZE; + *count = (phdr.p_filesz + HD_SECTOR_SIZE - 1) / HD_SECTOR_SIZE; + + fprintf(stderr, "Parsed mipsel boot image %s: using loadaddr 0x%X, execaddr 0x%X, offset 0x%X, count 0x%X\n", + filename, *loadaddr, *execaddr, *offset, *count); + + fclose(loader); + return 0; +} + +static int boot_mipsel_write(FILE *outfile) +{ + char sector[2048]; + struct dec_bootblock *bb = (struct dec_bootblock *)sector; + int error = 0; + int offset = 0; + int count = 0; + struct directory_entry *boot_file; /* Boot file we need to search for in the image */ + unsigned long length = 0; + unsigned long extent = 0; + int loadaddr = 0; + int execaddr = 0; + + memset(sector, 0, sizeof(sector)); + + /* Fill in our values we care on */ + write_le32(DEC_BOOT_MAGIC, (unsigned char *)&bb->magic); + write_le32(1, (unsigned char *)&bb->mode); + + /* Find the file entry in the CD image */ + boot_file = search_tree_file(root, boot_file_name); + if (!boot_file) + { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Uh oh, unable to find the mipsel boot file '%s'!\n", + boot_file_name); +#else + fprintf(stderr, "Uh oh, unable to find the mipsel boot file '%s'!\n", + boot_file_name); + exit(1); +#endif + } + + extent = get_733(boot_file->isorec.extent); + length = get_733(boot_file->isorec.size); + fprintf(stderr, "Found mipsel boot loader %s: using extent %lu, #blocks %lu\n", + boot_file_name, extent, length); + + /* Parse the ELF headers on the boot file */ + error = parse_boot_file(boot_file->whole_name, &loadaddr, &execaddr, &offset, &count); + if (error) + { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Uh oh, unable to parse the mipsel boot file '%s'!\n", + boot_file->whole_name); +#else + fprintf(stderr, "Uh oh, unable to parse the mipsel boot file '%s'!\n", + boot_file->whole_name); + exit(1); +#endif + } + + write_le32(loadaddr, (unsigned char *)&bb->loadAddr); + write_le32(execaddr, (unsigned char *)&bb->execAddr); + write_le32((extent * 4) + offset, (unsigned char *)&bb->bootmap[0].start); + write_le32(count, (unsigned char *)&bb->bootmap[0].count); + + jtwrite(sector, sizeof(sector), 1, 0, FALSE); + xfwrite(sector, sizeof(sector), 1, outfile, 0, FALSE); + last_extent_written++; + + return 0; +} + +struct output_fragment mipselboot_desc = {NULL, oneblock_size, NULL, boot_mipsel_write, "mipsel boot block"}; diff --git a/genisoimage/boot.c b/genisoimage/boot.c new file mode 100644 index 0000000..51b6fb7 --- /dev/null +++ b/genisoimage/boot.c @@ -0,0 +1,537 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)boot.c 1.13 04/02/22 Copyright 1999-2003 J. Schilling */ +/* + * Support for generic boot (sector 0..16) + * and to boot Sun sparc and Sun x86 systems. + * + * Copyright (c) 1999-2003 J. Schilling + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <mconfig.h> +#include "genisoimage.h" +#include <fctldefs.h> +#include <utypes.h> +#include <intcvt.h> +#include <schily.h> +#include "sunlabel.h" + +extern int use_sunx86boot; + +static struct sun_label cd_label; +static struct x86_label sx86_label; +static struct pc_part fdisk_part; +static char *boot_files[NDKMAP]; /* Change this for > 8 x86 parts */ + +static void init_sparc_label(void); +static void init_sunx86_label(void); +void sparc_boot_label(char *label); +void sunx86_boot_label(char *label); +void scan_sparc_boot(char *files); +void scan_sunx86_boot(char *files); +int make_sun_label(void); +int make_sunx86_label(void); +static void dup_sun_label(int part); +static int sunboot_write(FILE *outfile); +static int sunlabel_size(int starting_extent); +static int sunlabel_write(FILE * outfile); +static int genboot_size(int starting_extent); +static int genboot_write(FILE * outfile); + +/* + * Set the virtual geometry in the disk label. + * If we like to make the geometry variable, we may change + * dkl_ncyl and dkl_pcyl later. + */ +static void +init_sparc_label() +{ + i_to_4_byte(cd_label.dkl_vtoc.v_version, V_VERSION); + i_to_2_byte(cd_label.dkl_vtoc.v_nparts, NDKMAP); + i_to_4_byte(cd_label.dkl_vtoc.v_sanity, VTOC_SANE); + + i_to_2_byte(cd_label.dkl_rpm, CD_RPM); + i_to_2_byte(cd_label.dkl_pcyl, CD_PCYL); + i_to_2_byte(cd_label.dkl_apc, CD_APC); + i_to_2_byte(cd_label.dkl_intrlv, CD_INTRLV); + i_to_2_byte(cd_label.dkl_ncyl, CD_NCYL); + i_to_2_byte(cd_label.dkl_acyl, CD_ACYL); + i_to_2_byte(cd_label.dkl_nhead, CD_NHEAD); + i_to_2_byte(cd_label.dkl_nsect, CD_NSECT); + + cd_label.dkl_magic[0] = DKL_MAGIC_0; + cd_label.dkl_magic[1] = DKL_MAGIC_1; +} + +static void +init_sunx86_label() +{ + li_to_4_byte(sx86_label.dkl_vtoc.v_sanity, VTOC_SANE); + li_to_4_byte(sx86_label.dkl_vtoc.v_version, V_VERSION); + li_to_2_byte(sx86_label.dkl_vtoc.v_sectorsz, 512); + li_to_2_byte(sx86_label.dkl_vtoc.v_nparts, NX86MAP); + + li_to_4_byte(sx86_label.dkl_pcyl, CD_PCYL); + li_to_4_byte(sx86_label.dkl_ncyl, CD_NCYL); + li_to_2_byte(sx86_label.dkl_acyl, CD_ACYL); + li_to_2_byte(sx86_label.dkl_bcyl, 0); + + li_to_4_byte(sx86_label.dkl_nhead, CD_NHEAD); + li_to_4_byte(sx86_label.dkl_nsect, CD_NSECT); + li_to_2_byte(sx86_label.dkl_intrlv, CD_INTRLV); + li_to_2_byte(sx86_label.dkl_skew, 0); + li_to_2_byte(sx86_label.dkl_apc, CD_APC); + li_to_2_byte(sx86_label.dkl_rpm, CD_RPM); + + li_to_2_byte(sx86_label.dkl_write_reinstruct, 0); + li_to_2_byte(sx86_label.dkl_read_reinstruct, 0); + + li_to_2_byte(sx86_label.dkl_magic, DKL_MAGIC); +} + +/* + * For command line parser: set ASCII label. + */ +void +sparc_boot_label(char *label) +{ + strncpy(cd_label.dkl_ascilabel, label, 127); + cd_label.dkl_ascilabel[127] = '\0'; +} + +void +sunx86_boot_label(char *label) +{ + strncpy(sx86_label.dkl_vtoc.v_asciilabel, label, 127); + sx86_label.dkl_vtoc.v_asciilabel[127] = '\0'; +} + +/* + * Parse the command line argument for boot images. + */ +void +scan_sparc_boot(char *files) +{ + char *p; + int i = 1; + struct stat statbuf; + int status; + + init_sparc_label(); + + do { + if (i >= NDKMAP) + comerrno(EX_BAD, "Too many boot partitions.\n"); + boot_files[i++] = files; + if ((p = strchr(files, ',')) != NULL) + *p++ = '\0'; + files = p; + } while (p); + + i_to_2_byte(cd_label.dkl_vtoc.v_part[0].p_tag, V_USR); + i_to_2_byte(cd_label.dkl_vtoc.v_part[0].p_flag, V_RONLY); + for (i = 0; i < NDKMAP; i++) { + p = boot_files[i]; + if (p == NULL || *p == '\0') + continue; + if (strcmp(p, "...") == '\0') + break; + + status = stat_filter(p, &statbuf); + if (status < 0 || access(p, R_OK) < 0) + comerr("Cannot access '%s'.\n", p); + + i_to_4_byte(cd_label.dkl_map[i].dkl_nblk, + roundup(statbuf.st_size, CD_CYLSIZE)/512); + + i_to_2_byte(cd_label.dkl_vtoc.v_part[i].p_tag, V_ROOT); + i_to_2_byte(cd_label.dkl_vtoc.v_part[i].p_flag, V_RONLY); + } +} + +void +scan_sunx86_boot(char *files) +{ + char *p; + int i = 0; + struct stat statbuf; + int status; + + init_sunx86_label(); + + do { + if (i >= NDKMAP) + comerrno(EX_BAD, "Too many boot partitions.\n"); + boot_files[i++] = files; + if ((p = strchr(files, ',')) != NULL) + *p++ = '\0'; + files = p; + } while (p); + + li_to_2_byte(sx86_label.dkl_vtoc.v_part[0].p_tag, V_ROOT); /* UFS */ + li_to_2_byte(sx86_label.dkl_vtoc.v_part[0].p_flag, V_RONLY); + li_to_2_byte(sx86_label.dkl_vtoc.v_part[1].p_tag, V_USR); /* ISO */ + li_to_2_byte(sx86_label.dkl_vtoc.v_part[1].p_flag, V_RONLY); + li_to_2_byte(sx86_label.dkl_vtoc.v_part[2].p_tag, 0); /* ALL */ + li_to_2_byte(sx86_label.dkl_vtoc.v_part[2].p_flag, 0); + for (i = 0; i < NDKMAP; i++) { + p = boot_files[i]; + if (p == NULL || *p == '\0') + continue; + if (i == 1 || i == 2) { + comerrno(EX_BAD, + "Partition %d may not have a filename.\n", i); + } + + status = stat_filter(p, &statbuf); + if (status < 0 || access(p, R_OK) < 0) + comerr("Cannot access '%s'.\n", p); + + li_to_4_byte(sx86_label.dkl_vtoc.v_part[i].p_size, + roundup(statbuf.st_size, CD_CYLSIZE)/512); + + if (i > 2) { + li_to_2_byte(sx86_label.dkl_vtoc.v_part[i].p_tag, V_USR); + li_to_2_byte(sx86_label.dkl_vtoc.v_part[i].p_flag, V_RONLY); + } + } +} + +/* + * Finish the Sun disk label and compute the size of the additional data. + */ +int +make_sun_label() +{ + int last; + int cyl = 0; + int nblk; + int bsize; + int i; + char *p; + + /* + * Compute the size of the padding for the iso9660 image + * to allow the next partition to start on a cylinder boundary. + */ + last = roundup(last_extent, (CD_CYLSIZE/SECTOR_SIZE)); + + i_to_4_byte(cd_label.dkl_map[0].dkl_nblk, last*4); + bsize = 0; + for (i = 0; i < NDKMAP; i++) { + p = boot_files[i]; + if (p != NULL && strcmp(p, "...") == '\0') { + dup_sun_label(i); + break; + } + if ((nblk = a_to_4_byte(cd_label.dkl_map[i].dkl_nblk)) == 0) + continue; + + i_to_4_byte(cd_label.dkl_map[i].dkl_cylno, cyl); + cyl += nblk / (CD_CYLSIZE/512); + if (i > 0) + bsize += nblk; + } + bsize /= 4; + return (last-last_extent+bsize); +} + +/* + * A typical Solaris boot/install CD from a Sun CD set looks + * this way: + * + * UFS Part 0 tag 2 flag 10 start 3839 size 1314560 + * ISO Part 1 tag 4 flag 10 start 0 size 3839 + * ALL Part 2 tag 0 flag 0 start 0 size 1318400 + */ +int +make_sunx86_label() +{ + int last; + int cyl = 0; + int nblk; + int bsize; + int i; + int partoff = 1; /* The offset of the Solaris 0x82 partition */ + char *p; + + /* + * Compute the size of the padding for the iso9660 image + * to allow the next partition to start on a cylinder boundary. + */ + last = roundup(last_extent, (CD_CYLSIZE/SECTOR_SIZE)); + + li_to_4_byte(sx86_label.dkl_vtoc.v_part[1].p_size, last*4); + + /* + * Note that the Solaris fdisk partition with fdisk signature 0x82 + * is created at fixed offset 1 sector == 512 Bytes by this + * implementation. + * We need subtract this partition offset from all absolute + * partition offsets in order to get offsets relative to the + * Solaris primary partition. + */ + bsize = 0; + for (i = 0; i < NDKMAP; i++) { + if (i == 2) /* Never include the whole disk in */ + continue; /* size/offset computations */ + p = boot_files[i]; + + if ((nblk = la_to_4_byte(sx86_label.dkl_vtoc.v_part[i].p_size)) == 0) + continue; + + li_to_4_byte(sx86_label.dkl_vtoc.v_part[i].p_start, + cyl*(CD_CYLSIZE/512)-partoff); + cyl += nblk / (CD_CYLSIZE/512); + if (i == 0 || i > 2) + bsize += nblk; + } + li_to_4_byte(sx86_label.dkl_vtoc.v_part[0].p_start, last*4-partoff); + li_to_4_byte(sx86_label.dkl_vtoc.v_part[1].p_start, 0); + li_to_4_byte(sx86_label.dkl_vtoc.v_part[1].p_size, last*4-partoff); + li_to_4_byte(sx86_label.dkl_vtoc.v_part[2].p_start, 0); + li_to_4_byte(sx86_label.dkl_vtoc.v_part[2].p_size, last*4+bsize); + + fdisk_part.part[0].pr_status = STATUS_ACTIVE; + fdisk_part.part[0].pr_type = TYPE_SOLARIS; + li_to_4_byte(fdisk_part.part[0].pr_partoff, partoff); + li_to_4_byte(fdisk_part.part[0].pr_nsect, last*4+bsize-partoff); + fdisk_part.magic[0] = 0x55; + fdisk_part.magic[1] = 0xAA; + + bsize /= 4; + return (last-last_extent+bsize); +} + +/* + * Duplicate a partition of the Sun disk label until all partitions are filled up. + */ +static void +dup_sun_label(int part) +{ + int cyl; + int nblk; + int i; + + + if (part < 1 || part >= NDKMAP) + part = 1; + cyl = a_to_4_byte(cd_label.dkl_map[part-1].dkl_cylno); + nblk = a_to_4_byte(cd_label.dkl_map[part-1].dkl_nblk); + + for (i = part; i < NDKMAP; i++) { + i_to_4_byte(cd_label.dkl_map[i].dkl_cylno, cyl); + i_to_4_byte(cd_label.dkl_map[i].dkl_nblk, nblk); + + i_to_2_byte(cd_label.dkl_vtoc.v_part[i].p_tag, V_ROOT); + i_to_2_byte(cd_label.dkl_vtoc.v_part[i].p_flag, V_RONLY); + } +} + +/* + * Write out Sun boot partitions. + */ +static int +sunboot_write(FILE *outfile) +{ + char buffer[SECTOR_SIZE]; + int i; + int n; + int nblk; + int amt; + int f; + char *p; + + memset(buffer, 0, sizeof (buffer)); + + /* + * Write padding to the iso9660 image to allow the + * boot partitions to start on a cylinder boundary. + */ + amt = roundup(last_extent_written, (CD_CYLSIZE/SECTOR_SIZE)) - last_extent_written; + for (n = 0; n < amt; n++) { + jtwrite(buffer, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + } + if (use_sunx86boot) + i = 0; + else + i = 1; + for (; i < NDKMAP; i++) { + if (use_sunx86boot && (i == 1 || i == 2)) + continue; + p = boot_files[i]; + if (p == NULL || *p == '\0') + continue; + if (p != NULL && strcmp(p, "...") == '\0') + break; + if (use_sunx86boot) { + if ((nblk = la_to_4_byte(sx86_label.dkl_vtoc.v_part[i].p_size)) == 0) + continue; + } else { + if ((nblk = a_to_4_byte(cd_label.dkl_map[i].dkl_nblk)) == 0) + continue; + } + if ((f = open(boot_files[i], O_RDONLY| O_BINARY)) < 0) + comerr("Cannot open '%s'.\n", boot_files[i]); + + amt = nblk / 4; + for (n = 0; n < amt; n++) { + memset(buffer, 0, sizeof (buffer)); + if (read(f, buffer, SECTOR_SIZE) < 0) + comerr("Read error on '%s'.\n", boot_files[i]); + jtwrite(buffer, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + } + close(f); + } + fprintf(stderr, "Total extents including %s boot = %u\n", + use_sunx86boot ? "Solaris x86":"sparc", + last_extent_written - session_start); + return (0); +} + +/* + * Do size management for the Sun disk label that is located in the first + * sector of a disk. + */ +static int +sunlabel_size(int starting_extent) +{ + if (last_extent != session_start) + comerrno(EX_BAD, "Cannot create sparc boot on offset != 0.\n"); + last_extent++; + return (0); +} + +/* + * Cumpute the checksum and write a Sun disk label to the first sector + * of the disk. + * If the -generic-boot option has been specified too, overlay the + * Sun disk label on the firs 512 bytes of the generic boot code. + */ +static int +sunlabel_write(FILE *outfile) +{ + char buffer[SECTOR_SIZE]; + register char *p; + register short count = (512/2) - 1; + int f; + + memset(buffer, 0, sizeof (buffer)); + if (genboot_image) { + if ((f = open(genboot_image, O_RDONLY| O_BINARY)) < 0) + comerr("Cannot open '%s'.\n", genboot_image); + + if (read(f, buffer, SECTOR_SIZE) < 0) + comerr("Read error on '%s'.\n", genboot_image); + close(f); + } + + if (use_sunx86boot) { + if (sx86_label.dkl_vtoc.v_asciilabel[0] == '\0') + strcpy(sx86_label.dkl_vtoc.v_asciilabel, CD_X86LABEL); + + p = (char *)&sx86_label; + sx86_label.dkl_cksum[0] = 0; + sx86_label.dkl_cksum[1] = 0; + while (count-- > 0) { + sx86_label.dkl_cksum[0] ^= *p++; + sx86_label.dkl_cksum[1] ^= *p++; + } + memcpy(&buffer[0x1BE], &fdisk_part.part, 512-0x1BE); + memcpy(&buffer[1024], &sx86_label, 512); + } else { + /* + * If we don't already have a Sun disk label text + * set up the default. + */ + if (cd_label.dkl_ascilabel[0] == '\0') + strcpy(cd_label.dkl_ascilabel, CD_DEFLABEL); + + p = (char *)&cd_label; + cd_label.dkl_cksum[0] = 0; + cd_label.dkl_cksum[1] = 0; + while (count--) { + cd_label.dkl_cksum[0] ^= *p++; + cd_label.dkl_cksum[1] ^= *p++; + } + memcpy(buffer, &cd_label, 512); + } + + jtwrite(buffer, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + return (0); +} + +/* + * Do size management for the generic boot code on sectors 0..16. + */ +static int +genboot_size(int starting_extent) +{ + if (last_extent > (session_start + 1)) + comerrno(EX_BAD, "Cannot create generic boot on offset != 0.\n"); + last_extent = session_start + 16; + return (0); +} + +/* + * Write the generic boot code to sectors 0..16. + * If there is a Sun disk label, start writing at sector 1. + */ +static int +genboot_write(FILE *outfile) +{ + char buffer[SECTOR_SIZE]; + int i; + int f; + + if ((f = open(genboot_image, O_RDONLY| O_BINARY)) < 0) + comerr("Cannot open '%s'.\n", genboot_image); + + for (i = 0; i < 16; i++) { + memset(buffer, 0, sizeof (buffer)); + if (read(f, buffer, SECTOR_SIZE) < 0) + comerr("Read error on '%s'.\n", genboot_image); + + if (i != 0 || last_extent_written == session_start) { + jtwrite(buffer, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + } + } + close(f); + return (0); +} + +struct output_fragment sunboot_desc = {NULL, NULL, NULL, sunboot_write, "Sun Boot" }; +struct output_fragment sunlabel_desc = {NULL, sunlabel_size, NULL, sunlabel_write, "Sun Disk Label" }; +struct output_fragment genboot_desc = {NULL, genboot_size, NULL, genboot_write, "Generic Boot" }; diff --git a/genisoimage/bootinfo.h b/genisoimage/bootinfo.h new file mode 100644 index 0000000..a02bd65 --- /dev/null +++ b/genisoimage/bootinfo.h @@ -0,0 +1,46 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)bootinfo.h 1.3 04/03/02 Copyright 1999, 2004 J. Schilling */ +/* + * Header file bootinfo.h - genisoimage-defined boot information table + * useful for an El Torito-loaded disk image. + * + * Copyright (c) 1999, 2004 J. Schilling + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _BOOTINFO_H +#define _BOOTINFO_H + +struct genisoimage_boot_info { + char bi_pvd [ISODCL(1, 4)]; /* LBA of PVD */ + char bi_file [ISODCL(5, 8)]; /* LBA of boot image */ + char bi_length [ISODCL(9, 12)]; /* Length of boot image */ + char bi_csum [ISODCL(13, 16)]; /* Checksum of boot image */ + char bi_reserved [ISODCL(17, 56)]; /* Reserved */ +}; + +#endif /* _BOOTINFO_H */ diff --git a/genisoimage/bswap.h b/genisoimage/bswap.h new file mode 100644 index 0000000..5f3fd9d --- /dev/null +++ b/genisoimage/bswap.h @@ -0,0 +1,67 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)bswap.h 1.2 03/03/25 Copyright 2002 J. Schilling */ +#ifndef _BSWAP_H +#define _BSWAP_H + +/* + * Allow to use B2N_* macros found in libdvdread in a portable way. + * These macros should better be avoided as in place conversion in + * general only works on processors like Motorola 68000 and Intel x86. + * Modern processors usually have alignement restrictions that may + * cause problems. The stripped down libdvdread for genisoimage is known + * not to have these alignement problems, so we may use the macros + * as they have been introduced by the authors of libdvdread. + * + * Copyright (c) 2002 J. Schilling + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <mconfig.h> +#include <btorder.h> +#include <intcvt.h> + +#if defined(WORDS_BIGENDIAN) + +/* All bigendian systems are fine, just ignore the swaps. */ +#define B2N_16(x) (void)(x) +#define B2N_32(x) (void)(x) +#define B2N_64(x) (void)(x) + +#else + +/* + * It is a bad idea to convert numbers in place. + * In protocols, there is usually the additional problem that the + * data is not properly aligned. + */ +#define B2N_16(x) (x) = a_to_u_2_byte(&(x)) +#define B2N_32(x) (x) = a_to_u_4_byte(&(x)) +#define B2N_64(x) (x) = a_to_u_8_byte(&(x)) + +#endif + +#endif /* _BSWAP_H */ diff --git a/genisoimage/checksum.c b/genisoimage/checksum.c new file mode 100644 index 0000000..704167c --- /dev/null +++ b/genisoimage/checksum.c @@ -0,0 +1,583 @@ +/* + * checksum.c + * + * Copyright (c) 2008- Steve McIntyre <steve@einval.com> + * + * Implementation of a generic checksum interface, used in JTE. + * + * GNU GPL v2 + */ + +#include <mconfig.h> +#include "genisoimage.h" +#include <timedefs.h> +#include <fctldefs.h> +#include <regex.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "md5.h" +#include "sha1.h" +#include "sha256.h" +#include "sha512.h" +#include "checksum.h" + +#ifdef THREADED_CHECKSUMS +# include <pthread.h> +#endif + +static void md5_init(void *context) +{ + mk_MD5Init(context); +} +static void md5_update(void *context, unsigned char const *buf, unsigned int len) +{ + mk_MD5Update(context, buf, len); +} +static void md5_final(unsigned char *digest, void *context) +{ + mk_MD5Final(digest, context); +} + +static void sha1_init(void *context) +{ + sha1_init_ctx(context); +} +static void sha1_update(void *context, unsigned char const *buf, unsigned int len) +{ + sha1_process_bytes(buf, len, context); +} +static void sha1_final(unsigned char *digest, void *context) +{ + sha1_finish_ctx(context, digest); +} + +static void sha256_init(void *context) +{ + sha256_init_ctx(context); +} +static void sha256_update(void *context, unsigned char const *buf, unsigned int len) +{ + sha256_process_bytes(buf, len, context); +} +static void sha256_final(unsigned char *digest, void *context) +{ + sha256_finish_ctx(context, digest); +} + +static void sha512_init(void *context) +{ + sha512_init_ctx(context); +} +static void sha512_update(void *context, unsigned char const *buf, unsigned int len) +{ + sha512_process_bytes(buf, len, context); +} +static void sha512_final(unsigned char *digest, void *context) +{ + sha512_finish_ctx(context, digest); +} + +struct checksum_details +{ + char *name; + char *prog; + int digest_size; + int context_size; + void (*init)(void *context); + void (*update)(void *context, unsigned char const *buf, unsigned int len); + void (*final)(unsigned char *digest, void *context); +}; + +static const struct checksum_details algorithms[] = +{ + { + "MD5", + "md5sum", + 16, + sizeof(struct mk_MD5Context), + md5_init, + md5_update, + md5_final + }, + { + "SHA1", + "sha1sum", + 20, + sizeof(struct sha1_ctx), + sha1_init, + sha1_update, + sha1_final + }, + { + "SHA256", + "sha256sum", + 32, + sizeof(struct sha256_ctx), + sha256_init, + sha256_update, + sha256_final + }, + { + "SHA512", + "sha512sum", + 64, + sizeof(struct sha512_ctx), + sha512_init, + sha512_update, + sha512_final + } +}; + +struct algo_context +{ + void *context; + unsigned char *digest; + int enabled; + int finalised; + char *hexdump; +#ifdef THREADED_CHECKSUMS + unsigned char const *buf; + unsigned int len; + int which; + pthread_t thread; + struct _checksum_context *parent; + pthread_mutex_t start_mutex; + pthread_cond_t start_cv; +#endif +}; + +struct _checksum_context +{ +#ifdef THREADED_CHECKSUMS + unsigned int index; + unsigned int threads_running; + unsigned int threads_desired; + pthread_mutex_t done_mutex; + pthread_cond_t done_cv; +#endif + char *owner; + struct algo_context algo[NUM_CHECKSUMS]; +}; + +struct checksum_info *checksum_information(enum checksum_types which) +{ + return (struct checksum_info *)&algorithms[which]; +} + +/* Dump a buffer in hex */ +static void hex_dump_to_buffer(char *output_buffer, unsigned char *buf, size_t buf_size) +{ + unsigned int i; + char *p = output_buffer; + + memset(output_buffer, 0, 1 + (2*buf_size)); + for (i = 0; i < buf_size ; i++) + p += sprintf(p, "%2.2x", buf[i]); +} + +#ifdef THREADED_CHECKSUMS +static void *checksum_thread(void *arg) +{ + struct algo_context *a = arg; + struct _checksum_context *c = a->parent; + int num_blocks_summed = 0; + + while (1) + { + /* wait to be given some work to do */ + pthread_mutex_lock(&a->start_mutex); + while (a->buf == NULL) + { + pthread_cond_wait(&a->start_cv, &a->start_mutex); + } + pthread_mutex_unlock(&a->start_mutex); + + /* if we're given a zero-length buffer, then that means we're + * done */ + if (a->len == 0) + break; + + /* actually do the checksum on the supplied buffer */ + algorithms[a->which].update(a->context, a->buf, a->len); + num_blocks_summed++; + a->buf = NULL; + + /* and tell the main thread that we're done with that + * buffer */ + pthread_mutex_lock(&c->done_mutex); + c->threads_running--; + if (c->threads_running == 0) + pthread_cond_signal(&c->done_cv); + pthread_mutex_unlock(&c->done_mutex); + } + + pthread_exit(0); +} +#endif + +checksum_context_t *checksum_init_context(int checksums, const char *owner) +{ + int i = 0; + int ret = 0; + struct _checksum_context *context = calloc(1, sizeof(struct _checksum_context)); + + if (!context) + return NULL; + + context->owner = strdup(owner); + if (!context->owner) + { + free(context); + return NULL; + } + +#ifdef THREADED_CHECKSUMS + pthread_mutex_init(&context->done_mutex, NULL); + pthread_cond_init(&context->done_cv, NULL); + context->index = 0; + context->threads_running = 0; + context->threads_desired = 0; + + for (i = 0; i < NUM_CHECKSUMS; i++) + if ( (1 << i) & checksums) + context->threads_desired++; +#endif + + for (i = 0; i < NUM_CHECKSUMS; i++) + { + struct algo_context *a = &context->algo[i]; + if ( (1 << i) & checksums) + { + a->context = malloc(algorithms[i].context_size); + if (!a->context) + { + checksum_free_context(context); + return NULL; + } + a->digest = malloc(algorithms[i].digest_size); + if (!a->digest) + { + checksum_free_context(context); + return NULL; + } + a->hexdump = malloc(1 + (2*algorithms[i].digest_size)); + if (!a->hexdump) + { + checksum_free_context(context); + return NULL; + } + algorithms[i].init(a->context); + a->enabled = 1; + a->finalised = 0; +#ifdef THREADED_CHECKSUMS + a->which = i; + a->parent = context; + a->buf = NULL; + a->len = 0; + pthread_mutex_init(&a->start_mutex, NULL); + pthread_cond_init(&a->start_cv, NULL); + ret = pthread_create(&a->thread, NULL, checksum_thread, a); + if (ret != 0) + { + fprintf(stderr, "failed to create new thread: %d\n", ret); + checksum_free_context(context); + return NULL; + } +#endif + } + else + a->enabled = 0; + } + + return context; +} + +void checksum_free_context(checksum_context_t *context) +{ + int i = 0; + struct _checksum_context *c = context; + + for (i = 0; i < NUM_CHECKSUMS; i++) + { + struct algo_context *a = &c->algo[i]; + +#ifdef THREADED_CHECKSUMS + if (a->thread) + { + void *ret; + pthread_cancel(a->thread); + pthread_join(a->thread, &ret); + a->thread = 0; + } +#endif + free(a->context); + free(a->digest); + free(a->hexdump); + } + free(c->owner); + free(c); +} + +#ifdef THREADED_CHECKSUMS +void checksum_update(checksum_context_t *context, + unsigned char const *buf, unsigned int len) +{ + int i = 0; + struct _checksum_context *c = context; + static int index = 0; + + index++; + + c->threads_running = c->threads_desired; + for (i = 0; i < NUM_CHECKSUMS; i++) + { + if (c->algo[i].enabled) + { + struct algo_context *a = &c->algo[i]; + pthread_mutex_lock(&a->start_mutex); + a->len = len; + a->buf = buf; + pthread_cond_signal(&a->start_cv); + pthread_mutex_unlock(&a->start_mutex); + } + } + + /* Should now all be running, wait on them all to return */ + pthread_mutex_lock(&c->done_mutex); + while (c->threads_running > 0) + { + pthread_cond_wait(&c->done_cv, &c->done_mutex); + } + pthread_mutex_unlock(&c->done_mutex); +} + +#else // THREADED_CHECKSUMS + +void checksum_update(checksum_context_t *context, + unsigned char const *buf, unsigned int len) +{ + int i = 0; + struct _checksum_context *c = context; + + for (i = 0; i < NUM_CHECKSUMS; i++) + { + if (c->algo[i].enabled) + { + struct algo_context *a = &c->algo[i]; + algorithms[i].update(a->context, buf, len); + } + } +} + +#endif // THREADED_CHECKSUMS + +void checksum_final(checksum_context_t *context) +{ + int i = 0; + struct _checksum_context *c = context; + +#ifdef THREADED_CHECKSUMS + void *thread_ret; + /* Clean up the threads */ + c->threads_running = c->threads_desired; + + for (i = 0; i < NUM_CHECKSUMS; i++) + { + if (c->algo[i].enabled) + { + void *ret = 0; + struct algo_context *a = &c->algo[i]; + + pthread_mutex_lock(&a->start_mutex); + a->len = 0; + a->buf = (unsigned char *)-1; + pthread_cond_signal(&a->start_cv); + pthread_mutex_unlock(&a->start_mutex); + pthread_join(a->thread, &ret); + a->thread = 0; + } + } +#endif + + for (i = 0; i < NUM_CHECKSUMS; i++) + { + struct algo_context *a = &c->algo[i]; + if (a->enabled) + { + algorithms[i].final(a->digest, a->context); + hex_dump_to_buffer(a->hexdump, a->digest, algorithms[i].digest_size); + a->finalised = 1; + } + } +} + +void checksum_copy(checksum_context_t *context, + enum checksum_types which, + unsigned char *digest) +{ + struct _checksum_context *c = context; + + if (c->algo[which].enabled) + { + if (c->algo[which].finalised) + memcpy(digest, c->algo[which].digest, algorithms[which].digest_size); + else + memset(digest, 0, algorithms[which].digest_size); + } + else + fprintf(stderr, "Asked for %s checksum, not enabled!\n", + algorithms[which].name); +} + +const char *checksum_hex(checksum_context_t *context, + enum checksum_types which) +{ + struct _checksum_context *c = context; + + if (c->algo[which].enabled && c->algo[which].finalised) + return c->algo[which].hexdump; + + /* else */ + return NULL; +} + + +/* Parse the command line options for which checksums to use */ +int parse_checksum_algo(char *arg, int *algo) +{ + int error = 0; + int i = 0; + char *start_ptr = arg; + int len = 0; + + *algo = 0; + + if (!strcasecmp(arg, "all")) + { + *algo = 0xFF; + return 0; + } + + while (*start_ptr != 0) + { + int match = 0; + len = 0; + + while (start_ptr[len] != ',' && start_ptr[len] != 0) + len++; + + if (len) + { + for (i = 0; i < NUM_CHECKSUMS; i++) + { + if (len == strlen(algorithms[i].name) && + !strncasecmp(start_ptr, algorithms[i].name, len)) + { + match = 1; + *algo |= (1 << i); + } + } + + if (!match) + { + fprintf(stderr, "invalid algorithm name found in %s\n", arg); + return EINVAL; + } + } + + if (start_ptr[len] == 0) + break; + + start_ptr += len + 1; + } + + if (! (*algo & CHECK_MD5_USED)) + { + fprintf(stderr, "invalid choices: algorithms *must* include MD5\n"); + return EINVAL; + } + + return 0; +} + +#ifdef CHECKSUM_SELF_TEST +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdlib.h> + +int main(int argc, char **argv) +{ + char buf[1024]; + int fd = -1; + char *filename; + int err = 0; + static checksum_context_t *test_context = NULL; + int i = 0; + + if (argc != 2) + { + fprintf(stderr, "Need a filename to act on!\n"); + return 1; + } + + filename = argv[1]; + fd = open(filename, O_RDONLY); + if (fd < 0) + { + fprintf(stderr, "Unable to open file %s, errno %d\n", filename, errno); + return 1; + } + + test_context = checksum_init_context(CHECK_ALL_USED, "test"); + if (!test_context) + { + fprintf(stderr, "Unable to initialise checksum context\n"); + return 1; + } + + while(1) + { + err = read(fd, buf, sizeof(buf)); + if (err < 0) + { + fprintf(stderr, "Failed to read from file, errno %d\n", errno); + return 1; + } + + if (err == 0) + break; // EOF + + /* else */ + checksum_update(test_context, buf, err); + } + close(fd); + checksum_final(test_context); + + for (i = 0; i < NUM_CHECKSUMS; i++) + { + struct checksum_info *info; + unsigned char r[64]; + int j = 0; + + info = checksum_information(i); + memset(r, 0, sizeof(r)); + + checksum_copy(test_context, i, r); + + printf("OUR %s:\n", info->name); + for (j = 0; j < info->digest_size; j++) + printf("%2.2x", r[j]); + printf(" %s\n", filename); + printf("system checksum program (%s):\n", info->prog); + sprintf(buf, "%s %s", info->prog, filename); + system(buf); + printf("\n"); + } + return 0; +} +#endif /* CHECKSUM_SELF_TEST */ + diff --git a/genisoimage/checksum.h b/genisoimage/checksum.h new file mode 100644 index 0000000..367fae2 --- /dev/null +++ b/genisoimage/checksum.h @@ -0,0 +1,74 @@ +/* + * checksum.h + * + * Copyright (c) 2008- Steve McIntyre <steve@einval.com> + * + * Definitions and prototypes for a generic checksum interface, used + * in JTE. Inspired heavily by the interface to the MD5 code we're + * using already. + * + * GNU GPL v2 + */ + +enum checksum_types +{ + CHECK_MD5 = 0, + CHECK_SHA1, + CHECK_SHA256, + CHECK_SHA512, + NUM_CHECKSUMS +}; + +#define CHECK_MD5_USED (1 << CHECK_MD5) +#define CHECK_SHA1_USED (1 << CHECK_SHA1) +#define CHECK_SHA256_USED (1 << CHECK_SHA256) +#define CHECK_SHA512_USED (1 << CHECK_SHA512) +#define CHECK_ALL_USED 0xFFFFFFFF + +typedef void checksum_context_t; + +struct checksum_info +{ + char *name; + char *prog; + int digest_size; +}; + +/* Ask the library for information about a particular checksum + * algorithm. Returns a pointer to internal memory - DO NOT + * MODIFY/FREE! */ +struct checksum_info *checksum_information(enum checksum_types which); + +/* Allocate / initialise a context for the chosen checksums. OR + * together the desired checksums as the parameter */ +checksum_context_t *checksum_init_context(int checksums, const char *owner); + +/* Cleanup and free a context when it's finished with */ +void checksum_free_context(checksum_context_t *context); + +/* Pass a new buffer full of data through the checksum code */ +void checksum_update(checksum_context_t *context, + unsigned char const *buf, + unsigned int len); + +/* Finish the current set of checksums */ +void checksum_final(checksum_context_t *context); + +/* Extract a particular algorithm's checksum once checksum_final() has + * been called. Use the details in checksum_information() above first + * to see how big the digest will be. Only valid once checksum_final() + * has been called, otherwise the digest returned will be all + * zeroes. */ +void checksum_copy(checksum_context_t *context, + enum checksum_types which, + unsigned char *digest); + +/* Helper function: return a pointer to a string containing the ASCII + * hexadecimal dump of a checksum. Only valid once checksum_final() + * has been called, otherwise will return NULL */ +const char * checksum_hex(checksum_context_t *context, + enum checksum_types which); + + +extern int parse_checksum_algo(char *arg, + int *algo); diff --git a/genisoimage/config.h b/genisoimage/config.h new file mode 100644 index 0000000..b0f49ce --- /dev/null +++ b/genisoimage/config.h @@ -0,0 +1,34 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)config.h 1.1 97/05/16 Copyright 1997 J. Schilling */ +/* + * Adaption for mconfig.h from make file system. + * + * Copyright (c) 1997 J. Schilling + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <mconfig.h> diff --git a/genisoimage/defaults.h b/genisoimage/defaults.h new file mode 100644 index 0000000..60fea33 --- /dev/null +++ b/genisoimage/defaults.h @@ -0,0 +1,147 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)defaults.h 1.19 06/01/30 joerg */ +/* + * Header file defaults.h - assorted default values for character strings in + * the volume descriptor. + * + * Copyright (c) 1999-2004 J. Schilling + */ + +#define PREPARER_DEFAULT NULL +#define PUBLISHER_DEFAULT NULL +/* + * Define me when it's needed again +#ifndef APPID_DEFAULT +#ifdef APPLE_HYB +#define APPID_DEFAULT "MKISOFS ISO 9660/HFS FILESYSTEM BUILDER (C) 1993 E.YOUNGDALE (C) 1997 J.PEARSON/J.SCHILLING" +#else +#define APPID_DEFAULT "MKISOFS ISO 9660 FILESYSTEM BUILDER (C) 1993 E.YOUNGDALE (C) 1997 J.PEARSON/J.SCHILLING" +#endif / * APPLE_HYB * / +#endif */ +#define COPYRIGHT_DEFAULT NULL +#define BIBLIO_DEFAULT NULL +#define ABSTRACT_DEFAULT NULL +#define VOLSET_ID_DEFAULT NULL +#define VOLUME_ID_DEFAULT "CDROM" +#define BOOT_CATALOG_DEFAULT "boot.catalog" +#define BOOT_IMAGE_DEFAULT NULL +#define SILO_BOOT_IMAGE_DEFAULT "boot/second.b" +#define SILO_BOOTBLOCK_DEFAULT "boot/cd.b" +#define SILO_CONF_FILE_DEFAULT "/etc/silo.conf" +#ifdef APPLE_HYB +#define APPLE_TYPE_DEFAULT "TEXT" +#define APPLE_CREATOR_DEFAULT "unix" +#endif /* APPLE_HYB */ + +#ifdef __QNX__ +#define SYSTEM_ID_DEFAULT "QNX" +#endif + +#ifdef __osf__ +#define SYSTEM_ID_DEFAULT "OSF" +#endif + +#ifdef __sun +#ifdef __SVR4 +#define SYSTEM_ID_DEFAULT "Solaris" +#else +#define SYSTEM_ID_DEFAULT "SunOS" +#endif +#endif + +#ifdef __hpux +#define SYSTEM_ID_DEFAULT "HP-UX" +#endif + +#ifdef __sgi +#define SYSTEM_ID_DEFAULT "SGI" +#endif + +#if defined(_IBMR2) || defined(_AIX) +#define SYSTEM_ID_DEFAULT "AIX" +#endif + +#if defined(_WIN) || defined(__CYGWIN32__) || defined(__CYGWIN__) +#define SYSTEM_ID_DEFAULT "Win32" +#endif /* _WIN */ + +#ifdef __EMX__ +#define SYSTEM_ID_DEFAULT "OS/2" +#endif + +#ifdef __FreeBSD__ +#define SYSTEM_ID_DEFAULT "FreeBSD" +#endif + +#ifdef __DragonFly__ +#define SYSTEM_ID_DEFAULT "DragonFly" +#endif + +#ifdef __NetBSD__ +#define SYSTEM_ID_DEFAULT "NetBSD" +#endif + +#ifdef __OpenBSD__ +#define SYSTEM_ID_DEFAULT "OpenBSD" +#endif + +#ifdef __bsdi__ +#define SYSTEM_ID_DEFAULT "BSD/OS" +#endif + +#ifdef __NeXT__ +#define SYSTEM_ID_DEFAULT "NeXT" +#endif + +#if defined(__NeXT__) && defined(__TARGET_OSNAME) && __TARGET_OSNAME == rhapsody +#undef SYSTEM_ID_DEFAULT +#define SYSTEM_ID_DEFAULT "Rhapsody" +#endif + +#if defined(__APPLE__) && defined(__MACH__) +#undef SYSTEM_ID_DEFAULT +#define SYSTEM_ID_DEFAULT "Mac OS X" +#endif + +#ifdef __BEOS__ +#define SYSTEM_ID_DEFAULT "BeOS" +#endif + +#ifdef __OS2 +#define SYSTEM_ID_DEFAULT "OS/2" +#endif + +#ifdef VMS +#define SYSTEM_ID_DEFAULT "VMS" +#endif + +#ifdef OPENSERVER +#define SYSTEM_ID_DEFAULT "SCO-OPENSERVER" +#endif + +#ifdef UNIXWARE +#define SYSTEM_ID_DEFAULT "SCO-UNIXWARE" +#endif + +#ifdef linux +#define SYSTEM_ID_DEFAULT "LINUX" +#endif + +#ifdef __DJGPP__ +#define SYSTEM_ID_DEFAULT "DOS" +#endif + +#ifndef SYSTEM_ID_DEFAULT +#define SYSTEM_ID_DEFAULT "UNIX" +#endif diff --git a/genisoimage/desktop.c b/genisoimage/desktop.c new file mode 100644 index 0000000..51b0269 --- /dev/null +++ b/genisoimage/desktop.c @@ -0,0 +1,180 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)desktop.c 1.6 04/03/04 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */ +/* + * Copyright (c) 1997, 1998, 1999, 2000 James Pearson + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * make_desktop: create "Desktop DB" and "Desktop DF" files. + * + * These are set up to prevent the Mac "rebuilding the desktop" + * when the CD is inserted ??? + * + * I don't know if these files should be populated, but I've just + * created these files in their initial states: + * + * Desktop DB: Initial size == volume's clump size + * first block contents found by using od ... + * rest of file seems to be padding + * No resource fork + * + * Desktop DF: Empty + * + * If the files already exist, then set correct type/creator/flags + * + * James Pearson 11/8/97 + * Adapted from mkhfs routines for mkhybrid + */ + +#ifdef APPLE_HYB + +#include <mconfig.h> +#include "genisoimage.h" + +#define DB "Desktop DB" +#define DBFC "DMGR" +#define DBT "BTFL" + +#define DF "Desktop DF" +#define DFT "DTFL" + +/* + * from "data.h" - libhfs routines + */ +extern void d_putw(unsigned char *, short); +extern void d_putl(unsigned char *, long); + +int make_desktop(hfsvol *vol, int end); + + +extern hce_mem *hce; /* libhfs/genisoimage extras */ + +int +make_desktop(hfsvol *vol, int end) +{ + hfsfile *hfp; /* Mac file */ + hfsdirent ent; /* Mac finderinfo */ + unsigned long clps; /* clump size */ + unsigned short blks; /* blocks in a clump */ + unsigned char *blk; /* user data */ + + /* + * set up default directory entries - not all these fields are needed, + * but we'll set them up anyway ... + * First do a memset because there was a report about randomly + * changing Desktop DB/DF entries... + */ + memset(&ent, 0, sizeof (hfsdirent)); /* First clear all ... */ + ent.u.file.rsize = 0; /* resource size == 0 */ + strcpy(ent.u.file.creator, DBFC); /* creator */ + strcpy(ent.u.file.type, DBT); /* type */ + ent.crdate = ent.mddate = time(0); /* date is now */ + ent.fdflags = HFS_FNDR_ISINVISIBLE; /* invisible files */ + + /* + * clear the DB file + */ + blk = hce->hfs_ce + hce->hfs_ce_size * HFS_BLOCKSZ; + blks = hce->hfs_dt_size; + clps = blks * HFS_BLOCKSZ; + + memset(blk, 0, clps); + + /* + * create "Desktop DB" (if it doesn't exist) + */ + if (hfs_create(vol, DB, ent.u.file.type, ent.u.file.creator) == 0) { + /* + * DB file size from hce_mem info + * set up "Desktop DB" data - following found by od'ing the + * "Desktop DB" file + */ + d_putw(blk + 8, 0x100); + d_putw(blk + 10, 0x3); + + d_putw(blk + 32, 0x200); + d_putw(blk + 34, 0x25); + + d_putl(blk + 36, blks); + d_putl(blk + 40, blks - 1); + + d_putl(blk + 46, clps); + d_putw(blk + 50, 0xff); + + d_putw(blk + 120, 0x20a); + d_putw(blk + 122, 0x100); + + d_putw(blk + 248, 0x8000); + + d_putl(blk + 504, 0x1f800f8); + d_putl(blk + 508, 0x78000e); + + /* entries for "Desktop DB" */ + ent.u.file.dsize = clps; /* size = clump size */ + + /* open file */ + if ((hfp = hfs_open(vol, DB)) == 0) + perr(hfs_error); + + /* "write" file */ + write_fork(hfp, clps); + + /* set DB file attributes */ + if (hfs_fsetattr(hfp, &ent) < 0) + perr(hfs_error); + + /* find the real start of the file */ + end += hce->hfs_ce_size; + + /* close DB file */ + if (hfs_close(hfp, end, 0) < 0) + perr(hfs_error); + } else { + /* + * if it already exists, then make sure it has the correct + * type/creator and flags + */ + if (hfs_setattr(vol, DB, &ent) < 0) + perr(hfs_error); + } + + /* setup "Desktop DF" file as an empty file */ + strcpy(ent.u.file.type, DFT); /* type */ + ent.u.file.dsize = 0; /* empty */ + + /* create DF file (if it doesn't exist) - no need to open it */ + hfs_create(vol, DF, ent.u.file.type, ent.u.file.creator); + + /* set DB file attributes */ + if (hfs_setattr(vol, DF, &ent) < 0) + perr(hfs_error); + + return (0); +} + +#endif /* APPLE_HYB */ diff --git a/genisoimage/diag/README b/genisoimage/diag/README new file mode 100644 index 0000000..26851f2 --- /dev/null +++ b/genisoimage/diag/README @@ -0,0 +1,76 @@ +# @(#)README 1.1 97/02/23 eric +# + 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 genisoimage 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/genisoimage/diag/devdump.1 b/genisoimage/diag/devdump.1 new file mode 100644 index 0000000..b170c59 --- /dev/null +++ b/genisoimage/diag/devdump.1 @@ -0,0 +1,2 @@ +.so man1/isoinfo.1 +.\" %Z%%M% %I% %E% joerg diff --git a/genisoimage/diag/dump.c b/genisoimage/diag/dump.c new file mode 100644 index 0000000..b853c4e --- /dev/null +++ b/genisoimage/diag/dump.c @@ -0,0 +1,428 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)dump.c 1.24 05/05/15 joerg */ +/* + * File dump.c - dump a file/device both in hex and in ASCII. + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * Copyright (c) 1999-2004 J. Schilling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <mconfig.h> +#include <stdxlib.h> +#include <unixstd.h> +#include <strdefs.h> +#include <utypes.h> + +#include <stdio.h> +#include <standard.h> +#include <ttydefs.h> +#include <signal.h> +#include <schily.h> + +#include "../scsi.h" +#include "../../wodim/defaults.h" + +/* + * Note: always use these macros to avoid problems. + * + * ISO_ROUND_UP(X) may cause an integer overflow and thus give + * incorrect results. So avoid it if possible. + * + * ISO_BLOCKS(X) is overflow safe. Prefer this when ever it is possible. + */ +#define SECTOR_SIZE (2048) +#define ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1)) +#define ISO_BLOCKS(X) (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0)) + +#define infile in_image +FILE *infile = NULL; +static off_t file_addr; +static off_t sec_addr = (off_t)-1; +static Uchar sector[2048]; +#define PAGE 256 +static Uchar buffer[PAGE]; +static Uchar search[64]; + +#ifdef USE_V7_TTY +static struct sgttyb savetty; +static struct sgttyb newtty; +#else +static struct termios savetty; +static struct termios newtty; +#endif + +static void reset_tty(void); +static void set_tty(void); +static void onsusp(int sig); +static void crsr2(int row, int col); +static void readblock(void); +static void showblock(int flag); +static int getbyte(void); +static void usage(int excode); + +static void +reset_tty() +{ +#ifdef USE_V7_TTY + if (ioctl(STDIN_FILENO, TIOCSETN, &savetty) == -1) { +#else +#ifdef TCSANOW + if (tcsetattr(STDIN_FILENO, TCSANOW, &savetty) == -1) { +#else + if (ioctl(STDIN_FILENO, TCSETAF, &savetty) == -1) { +#endif +#endif +#ifdef USE_LIBSCHILY + comerr("Cannot put tty into normal mode\n"); +#else + printf("Cannot put tty into normal mode\n"); + exit(1); +#endif + } +} + +static void +set_tty() +{ +#ifdef USE_V7_TTY + if (ioctl(STDIN_FILENO, TIOCSETN, &newtty) == -1) { +#else +#ifdef TCSANOW + if (tcsetattr(STDIN_FILENO, TCSANOW, &newtty) == -1) { +#else + if (ioctl(STDIN_FILENO, TCSETAF, &newtty) == -1) { +#endif +#endif +#ifdef USE_LIBSCHILY + comerr("Cannot put tty into raw mode\n"); +#else + printf("Cannot put tty into raw mode\n"); + exit(1); +#endif + } +} + + +/* + * Come here when we get a suspend signal from the terminal + */ +static void +onsusp(int sig) +{ +#ifdef SIGTTOU + /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */ + signal(SIGTTOU, SIG_IGN); +#endif + reset_tty(); + fflush(stdout); +#ifdef SIGTTOU + 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); +#endif + set_tty(); +} + + +static void +crsr2(int row, int col) +{ + printf("\033[%d;%dH", row, col); +} + +static void +readblock() +{ + off_t dpos = file_addr - sec_addr; + + if (sec_addr < 0 || + dpos < 0 || (dpos + sizeof (buffer)) > sizeof (sector)) { + sec_addr = file_addr & ~2047; +#ifdef USE_SCG + readsecs(sec_addr/2048, sector, ISO_BLOCKS(sizeof (sector))); +#else + lseek(fileno(infile), sec_addr, SEEK_SET); + read(fileno(infile), sector, sizeof (sector)); +#endif + dpos = file_addr - sec_addr; + } + movebytes(§or[dpos], buffer, sizeof (buffer)); +} + +static void +showblock(int flag) +{ + unsigned int k; + int i; + int j; + + readblock(); + if (flag) { + for (i = 0; i < 16; i++) { + crsr2(i+3, 1); + if (sizeof (file_addr) > sizeof (long)) { + printf("%16.16llx ", (Llong)file_addr+(i<<4)); + } else { + printf("%8.8lx ", (long)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); + if (sizeof (file_addr) > sizeof (long)) { + printf(" Zone, zone offset: %14llx %12.12llx ", + (Llong)file_addr>>11, (Llong)file_addr & 0x7ff); + } else { + printf(" Zone, zone offset: %6lx %4.4lx ", + (long)(file_addr>>11), (long)(file_addr & 0x7ff)); + } + fflush(stdout); +} + +static int +getbyte() +{ + char c1; + + c1 = buffer[file_addr & (PAGE-1)]; + file_addr++; + if ((file_addr & (PAGE-1)) == 0) + showblock(0); + return (c1); +} + +static void +usage(int excode) +{ + errmsgno(EX_BAD, "Usage: %s [options] [image]\n", + get_progname()); + + fprintf(stderr, "Options:\n"); + fprintf(stderr, "\t-help, -h Print this help\n"); + fprintf(stderr, "\t-version Print version info and exit\n"); + fprintf(stderr, "\t-i filename Filename to read ISO-9660 image from\n"); + fprintf(stderr, "\tdev=target SCSI target to use as CD/DVD-Recorder\n"); + fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n"); + exit(excode); +} + +int +main(int argc, char *argv[]) +{ + int cac; + char * const *cav; + char *opts = "help,h,version,i*,dev*"; + BOOL help = FALSE; + BOOL prvers = FALSE; + char *filename = NULL; + char *devname = NULL; + char c; + int i; + int j; + + save_args(argc, argv); + + cac = argc - 1; + cav = argv + 1; + if (getallargs(&cac, &cav, opts, &help, &help, &prvers, + &filename, &devname) < 0) { + errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]); + usage(EX_BAD); + } + if (help) + usage(0); + if (prvers) { + printf("devdump %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM); + exit(0); + } + cac = argc - 1; + cav = argv + 1; + if (filename == NULL && devname == NULL) { + if (getfiles(&cac, &cav, opts) != 0) { + filename = cav[0]; + cac--, cav++; + } + } + if (getfiles(&cac, &cav, opts) != 0) { + errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]); + usage(EX_BAD); + } + if (filename != NULL && devname != NULL) { + errmsgno(EX_BAD, "Only one of -i or dev= allowed\n"); + usage(EX_BAD); + } +#ifdef USE_SCG + if (filename == NULL && devname == NULL) + cdr_defaults(&devname, NULL, NULL, NULL); +#endif + if (filename == NULL && devname == NULL) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "ISO-9660 image not specified\n"); +#else + fprintf(stderr, "ISO-9660 image not specified\n"); +#endif + usage(EX_BAD); + } + + if (filename != NULL) + infile = fopen(filename, "rb"); + else + filename = devname; + + if (infile != NULL) { + /* EMPTY */; +#ifdef USE_SCG + } else if (scsidev_open(filename) < 0) { +#else + } else { +#endif +#ifdef USE_LIBSCHILY + comerr("Cannot open '%s'\n", filename); +#else + fprintf(stderr, "Cannot open '%s'\n", filename); + exit(1); +#endif + } + + for (i = 0; i < 30; i++) + printf("\n"); + file_addr = (off_t)0; + + /* + * Now setup the keyboard for single character input. + */ +#ifdef USE_V7_TTY + if (ioctl(STDIN_FILENO, TIOCGETP, &savetty) == -1) { +#else +#ifdef TCSANOW + if (tcgetattr(STDIN_FILENO, &savetty) == -1) { +#else + if (ioctl(STDIN_FILENO, TCGETA, &savetty) == -1) { +#endif +#endif +#ifdef USE_LIBSCHILY + comerr("Stdin must be a tty\n"); +#else + printf("Stdin must be a tty\n"); + exit(1); +#endif + } + newtty = savetty; +#ifdef USE_V7_TTY + newtty.sg_flags &= ~(ECHO|CRMOD); + newtty.sg_flags |= CBREAK; +#else + newtty.c_lflag &= ~ICANON; + newtty.c_lflag &= ~ECHO; + newtty.c_cc[VMIN] = 1; +#endif + set_tty(); +#ifdef SIGTSTP + signal(SIGTSTP, onsusp); +#endif + on_comerr((void(*)(int, void *))reset_tty, NULL); + + do { + if (file_addr < (off_t)0) file_addr = (off_t)0; + showblock(1); + read(STDIN_FILENO, &c, 1); /* FIXME: check return value */ + 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):"); + if (sizeof (file_addr) > sizeof (long)) { + Llong ll; + scanf("%llx", &ll); /* FIXME: check return value */ + file_addr = (off_t)ll; + } else { + long l; + scanf("%lx", &l); /* FIXME: check return value */ + file_addr = (off_t)l; + } + file_addr = file_addr << 11; + crsr2(20, 1); + printf(" "); + } + if (c == 'f') { + crsr2(20, 1); + printf("Enter new search string:"); + fgets((char *)search, sizeof (search), stdin); /* FIXME: check return value */ + while (search[strlen((char *)search)-1] == '\n') + search[strlen((char *)search)-1] = 0; + crsr2(20, 1); + printf(" "); + } + if (c == '+') { + while (1 == 1) { + int slen; + + while (1 == 1) { + c = getbyte(); + if (c == search[0]) + break; + } + slen = (int)strlen((char *)search); + for (j = 1; j < slen; j++) { + if (search[j] != getbyte()) + break; + } + if (j == slen) + break; + } + file_addr &= ~(PAGE-1); + showblock(1); + } + if (c == 'q') + break; + } while (1 == 1); + reset_tty(); + if (infile != NULL) + fclose(infile); + return (0); +} diff --git a/genisoimage/diag/isodebug.1 b/genisoimage/diag/isodebug.1 new file mode 100644 index 0000000..58f0d9d --- /dev/null +++ b/genisoimage/diag/isodebug.1 @@ -0,0 +1,108 @@ +.\" @(#)isodebug.8 1.1 06/02/08 Copyr 2006 J. Schilling +.\" Manual page for isodebug +.\" Modified for cdrkit distribution by E.Bloch +.\" +.if t .ds a \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'a +.if t .ds o \v'-0.55m'\h'0.00n'\z.\h'0.45n'\z.\v'0.55m'\h'-0.45n'o +.if t .ds u \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'u +.if t .ds A \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'A +.if t .ds O \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'O +.if t .ds U \v'-0.77m'\h'0.30n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.75n'U +.if t .ds s \\(*b +.if t .ds S SS +.if n .ds a ae +.if n .ds o oe +.if n .ds u ue +.if n .ds s sz +.TH ISODEBUG 1 "06/02/08" "J\*org Schilling" "Schily\'s USER COMMANDS" +.SH NAME +isodebug \- print genisoimage debug info from ISO-9660 image +.SH SYNOPSIS +.B +isodebug +[ +.I options +] +[ +.I file +] +.SH DESCRIPTION +.B Isodebug +reads the debug info written by +.BR genisoimage (8) +from within a ISO-9660 file system image and prints them. +. \" .SH RETURNS +. \" .SH ERRORS +.SH OPTIONS +.TP +.B \-help +Prints a short summary of the +.B isodebug +options and exists. +.TP +.B \-version +Prints the +.B isodebug +version number string and exists. +.TP +.BI \-i " filename +Filename to read ISO-9660 image from. +.TP +.BI dev= target +SCSI target to use as CD/DVD-Recorder. +See +.BR wodim (1) +for more information on now to use this option. +.SH FILES +.SH "SEE ALSO" +.BR wodim (1), +.BR genisoimage (1). +.SH AUTHOR +.nf +J\*org Schilling +Seestr. 110 +D-13353 Berlin +Germany +.fi +.PP + + +.SH AUTHOR +.nf +J\*org Schilling +Seestr. 110 +D-13353 Berlin +Germany +.fi + +.PP +This manpage describes the program implementation of +.B +isodebug +as shipped by the cdrkit distribution. See +.B +http://alioth.debian.org/projects/debburn/ +for details. It is a spinoff from the original program distributed in the +cdrtools package [1]. However, the cdrtools developers are not +involved in the development of this spinoff and therefore shall not be made +responsible for any problem caused by it. Do not try to get support for this +program by contacting the original author(s). +.PP +If you have support questions, send them to +.PP +.B +debburn-devel@lists.alioth.debian.org +.br +.PP +If you have definitely found a bug, send a mail to this list or to +.PP +.B +submit@bugs.debian.org +.br +.PP +writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body. +.PP +.br +[1] Cdrtools 2.01.01a08 from May 2006, http://cdrecord.berlios.de + + diff --git a/genisoimage/diag/isodebug.c b/genisoimage/diag/isodebug.c new file mode 100644 index 0000000..f322021 --- /dev/null +++ b/genisoimage/diag/isodebug.c @@ -0,0 +1,281 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)isodebug.c 1.10 05/05/01 Copyright 1996-2004 J. Schilling */ +/* + * Copyright (c) 1996-2004 J. Schilling + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <mconfig.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <statdefs.h> +#include <stdxlib.h> +#include <unixstd.h> +#include <strdefs.h> +#include <standard.h> +#include <utypes.h> +#include <intcvt.h> +#include <schily.h> + +#include "../scsi.h" +#include "../../wodim/defaults.h" + +#define _delta(from, to) ((to) - (from) + 1) + +#define VD_BOOT 0 +#define VD_PRIMARY 1 +#define VD_SUPPLEMENT 2 +#define VD_PARTITION 3 +#define VD_TERM 255 + +#define VD_ID "CD001" + +struct iso9660_voldesc { + char vd_type [_delta(1, 1)]; + char vd_id [_delta(2, 6)]; + char vd_version [_delta(7, 7)]; + char vd_fill [_delta(8, 2048)]; +}; + +struct iso9660_boot_voldesc { + char vd_type [_delta(1, 1)]; + char vd_id [_delta(2, 6)]; + char vd_version [_delta(7, 7)]; + char vd_bootsys [_delta(8, 39)]; + char vd_bootid [_delta(40, 71)]; + char vd_bootcode [_delta(72, 2048)]; +}; + +struct iso9660_pr_voldesc { + char vd_type [_delta(1, 1)]; + char vd_id [_delta(2, 6)]; + char vd_version [_delta(7, 7)]; + char vd_unused1 [_delta(8, 8)]; + char vd_system_id [_delta(9, 40)]; + char vd_volume_id [_delta(41, 72)]; + char vd_unused2 [_delta(73, 80)]; + char vd_volume_space_size [_delta(81, 88)]; + char vd_unused3 [_delta(89, 120)]; + char vd_volume_set_size [_delta(121, 124)]; + char vd_volume_seq_number [_delta(125, 128)]; + char vd_lbsize [_delta(129, 132)]; + char vd_path_table_size [_delta(133, 140)]; + char vd_pos_path_table_l [_delta(141, 144)]; + char vd_opt_pos_path_table_l [_delta(145, 148)]; + char vd_pos_path_table_m [_delta(149, 152)]; + char vd_opt_pos_path_table_m [_delta(153, 156)]; + char vd_root_dir [_delta(157, 190)]; + char vd_volume_set_id [_delta(191, 318)]; + char vd_publisher_id [_delta(319, 446)]; + char vd_data_preparer_id [_delta(447, 574)]; + char vd_application_id [_delta(575, 702)]; + char vd_copyr_file_id [_delta(703, 739)]; + char vd_abstr_file_id [_delta(740, 776)]; + char vd_bibl_file_id [_delta(777, 813)]; + char vd_create_time [_delta(814, 830)]; + char vd_mod_time [_delta(831, 847)]; + char vd_expiry_time [_delta(848, 864)]; + char vd_effective_time [_delta(865, 881)]; + char vd_file_struct_vers [_delta(882, 882)]; + char vd_reserved1 [_delta(883, 883)]; + char vd_application_use [_delta(884, 1395)]; + char vd_fill [_delta(1396, 2048)]; +}; + +#define GET_UBYTE(a) a_to_u_byte(a) +#define GET_SBYTE(a) a_to_byte(a) +#define GET_SHORT(a) a_to_u_2_byte(&((unsigned char *) (a))[0]) +#define GET_BSHORT(a) a_to_u_2_byte(&((unsigned char *) (a))[2]) +#define GET_INT(a) a_to_4_byte(&((unsigned char *) (a))[0]) +#define GET_LINT(a) la_to_4_byte(&((unsigned char *) (a))[0]) +#define GET_BINT(a) a_to_4_byte(&((unsigned char *) (a))[4]) + +#define infile in_image +FILE *infile = NULL; + +static void usage(int excode); +static char *isodinfo(FILE *f); + +static void +usage(int excode) +{ + errmsgno(EX_BAD, "Usage: %s [options] image\n", + get_progname()); + + fprintf(stderr, "Options:\n"); + fprintf(stderr, "\t-help,-h Print this help\n"); + fprintf(stderr, "\t-version Print version info and exit\n"); + fprintf(stderr, "\t-i filename Filename to read ISO-9660 image from\n"); + fprintf(stderr, "\tdev=target SCSI target to use as CD/DVD-Recorder\n"); + fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n"); + exit(excode); +} + +static char * +isodinfo(FILE *f) +{ +static struct iso9660_voldesc vd; + struct iso9660_pr_voldesc *vp; +#ifndef USE_SCG + struct stat sb; + mode_t mode; +#endif + BOOL found = FALSE; + off_t sec_off = 16L; + +#ifndef USE_SCG + /* + * First check if a bad guy tries to call isosize() + * with an unappropriate file descriptor. + * return -1 in this case. + */ + if (isatty(fileno(f))) + return (NULL); + if (fstat(fileno(f), &sb) < 0) + return (NULL); + mode = sb.st_mode & S_IFMT; + if (!S_ISREG(mode) && !S_ISBLK(mode) && !S_ISCHR(mode)) + return (NULL); +#endif + + vp = (struct iso9660_pr_voldesc *) &vd; + + do { +#ifdef USE_SCG + readsecs(sec_off, &vd, 1); +#else + if (lseek(fileno(f), (off_t)(sec_off * 2048L), SEEK_SET) == -1) + return (NULL); + read(fileno(f), &vd, sizeof (vd)); +#endif + sec_off++; + + if (GET_UBYTE(vd.vd_type) == VD_PRIMARY) { + found = TRUE; +/* break;*/ + } + + } while (GET_UBYTE(vd.vd_type) != VD_TERM); + + if (GET_UBYTE(vd.vd_type) != VD_TERM) + return (NULL); + +#ifdef USE_SCG + readsecs(sec_off, &vd, 1); +#else + if (lseek(fileno(f), (off_t)(sec_off * 2048L), SEEK_SET) == -1) + return (NULL); + read(fileno(f), &vd, sizeof (vd)); +#endif + sec_off++; + + return ((char *)&vd); +} + +int +main(int argc, char *argv[]) +{ + int cac; + char * const *cav; + char *opts = "help,h,version,i*,dev*"; + BOOL help = FALSE; + BOOL prvers = FALSE; + char *filename = NULL; + char *devname = NULL; + char *p; + char *eol; + + save_args(argc, argv); + + cac = argc - 1; + cav = argv + 1; + if (getallargs(&cac, &cav, opts, &help, &help, &prvers, + &filename, &devname) < 0) { + errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]); + usage(EX_BAD); + } + if (help) + usage(0); + if (prvers) { + printf("isodebug %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM); + exit(0); + } + cac = argc - 1; + cav = argv + 1; + if (filename == NULL && devname == NULL) { + if (getfiles(&cac, &cav, opts) != 0) { + filename = cav[0]; + cac--, cav++; + } + } + if (getfiles(&cac, &cav, opts) != 0) { + errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]); + usage(EX_BAD); + } + if (filename != NULL && devname != NULL) { + errmsgno(EX_BAD, "Only one of -i or dev= allowed\n"); + usage(EX_BAD); + } +#ifdef USE_SCG + if (filename == NULL && devname == NULL) + cdr_defaults(&devname, NULL, NULL, NULL); +#endif + if (filename == NULL && devname == NULL) { + errmsgno(EX_BAD, "ISO-9660 image not specified\n"); + usage(EX_BAD); + } + + if (filename != NULL) + infile = fopen(filename, "rb"); + else + filename = devname; + + if (infile != NULL) { + /* EMPTY */; +#ifdef USE_SCG + } else if (scsidev_open(filename) < 0) { +#else + } else { +#endif + comerr("Cannot open '%s'\n", filename); + } + + p = isodinfo(infile); + if (p == NULL) { + printf("No ISO-9660 image debug info.\n"); + } else if (strncmp(p, "MKI ", 4) == 0) { + eol = strchr(p, '\n'); + if (eol) + *eol = '\0'; + printf("ISO-9660 image created at %s\n", &p[4]); + if (eol) { + printf("\nCmdline: '%s'\n", &eol[1]); + } + } + return (0); +} diff --git a/genisoimage/diag/isodump.1 b/genisoimage/diag/isodump.1 new file mode 100644 index 0000000..b170c59 --- /dev/null +++ b/genisoimage/diag/isodump.1 @@ -0,0 +1,2 @@ +.so man1/isoinfo.1 +.\" %Z%%M% %I% %E% joerg diff --git a/genisoimage/diag/isodump.c b/genisoimage/diag/isodump.c new file mode 100644 index 0000000..34fa8f1 --- /dev/null +++ b/genisoimage/diag/isodump.c @@ -0,0 +1,715 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)isodump.c 1.27 05/05/15 joerg */ +/* + * File isodump.c - dump iso9660 directory information. + * + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * Copyright (c) 1999-2004 J. Schilling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <mconfig.h> +#include <stdxlib.h> +#include <unixstd.h> +#include <strdefs.h> +#include <utypes.h> + +#include <stdio.h> +#include <standard.h> +#include <ttydefs.h> +#include <signal.h> +#include <schily.h> + +#include "../scsi.h" +#include "../../wodim/defaults.h" + +/* + * XXX JS: Some structures have odd lengths! + * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length. + * For this reason, we cannot use sizeof (struct iso_path_table) or + * sizeof (struct iso_directory_record) to compute on disk sizes. + * Instead, we use offsetof(..., name) and add the name size. + * See iso9660.h + */ +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +/* + * Note: always use these macros to avoid problems. + * + * ISO_ROUND_UP(X) may cause an integer overflow and thus give + * incorrect results. So avoid it if possible. + * + * ISO_BLOCKS(X) is overflow safe. Prefer this when ever it is possible. + */ +#define SECTOR_SIZE (2048) +#define ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1)) +#define ISO_BLOCKS(X) (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0)) + +#define infile in_image +FILE *infile = NULL; +off_t file_addr; +unsigned char buffer[2048]; +unsigned char search[64]; +int blocksize; + +#define PAGE sizeof (buffer) + +#define ISODCL(from, to) (to - from + 1) + +struct iso_primary_descriptor { + unsigned char type [ISODCL(1, 1)]; /* 711 */ + unsigned char id [ISODCL(2, 6)]; + unsigned char version [ISODCL(7, 7)]; /* 711 */ + unsigned char unused1 [ISODCL(8, 8)]; + unsigned char system_id [ISODCL(9, 40)]; /* aunsigned chars */ + unsigned char volume_id [ISODCL(41, 72)]; /* dunsigned chars */ + unsigned char unused2 [ISODCL(73, 80)]; + unsigned char volume_space_size [ISODCL(81, 88)]; /* 733 */ + unsigned char unused3 [ISODCL(89, 120)]; + unsigned char volume_set_size [ISODCL(121, 124)]; /* 723 */ + unsigned char volume_sequence_number [ISODCL(125, 128)]; /* 723 */ + unsigned char logical_block_size [ISODCL(129, 132)]; /* 723 */ + unsigned char path_table_size [ISODCL(133, 140)]; /* 733 */ + unsigned char type_l_path_table [ISODCL(141, 144)]; /* 731 */ + unsigned char opt_type_l_path_table [ISODCL(145, 148)]; /* 731 */ + unsigned char type_m_path_table [ISODCL(149, 152)]; /* 732 */ + unsigned char opt_type_m_path_table [ISODCL(153, 156)]; /* 732 */ + unsigned char root_directory_record [ISODCL(157, 190)]; /* 9.1 */ + unsigned char volume_set_id [ISODCL(191, 318)]; /* dunsigned chars */ + unsigned char publisher_id [ISODCL(319, 446)]; /* achars */ + unsigned char preparer_id [ISODCL(447, 574)]; /* achars */ + unsigned char application_id [ISODCL(575, 702)]; /* achars */ + unsigned char copyright_file_id [ISODCL(703, 739)]; /* 7.5 dchars */ + unsigned char abstract_file_id [ISODCL(740, 776)]; /* 7.5 dchars */ + unsigned char bibliographic_file_id [ISODCL(777, 813)]; /* 7.5 dchars */ + unsigned char creation_date [ISODCL(814, 830)]; /* 8.4.26.1 */ + unsigned char modification_date [ISODCL(831, 847)]; /* 8.4.26.1 */ + unsigned char expiration_date [ISODCL(848, 864)]; /* 8.4.26.1 */ + unsigned char effective_date [ISODCL(865, 881)]; /* 8.4.26.1 */ + unsigned char file_structure_version [ISODCL(882, 882)]; /* 711 */ + unsigned char unused4 [ISODCL(883, 883)]; + unsigned char application_data [ISODCL(884, 1395)]; + unsigned char unused5 [ISODCL(1396, 2048)]; +}; + +struct iso_directory_record { + unsigned char length [ISODCL(1, 1)]; /* 711 */ + unsigned char ext_attr_length [ISODCL(2, 2)]; /* 711 */ + unsigned char extent [ISODCL(3, 10)]; /* 733 */ + unsigned char size [ISODCL(11, 18)]; /* 733 */ + unsigned char date [ISODCL(19, 25)]; /* 7 by 711 */ + unsigned char flags [ISODCL(26, 26)]; + unsigned char file_unit_size [ISODCL(27, 27)]; /* 711 */ + unsigned char interleave [ISODCL(28, 28)]; /* 711 */ + unsigned char volume_sequence_number [ISODCL(29, 32)]; /* 723 */ + unsigned char name_len [ISODCL(33, 33)]; /* 711 */ + unsigned char name [1]; +}; + +static int isonum_731(char * p); +static int isonum_72(char * p); +static int isonum_723(char * p); +static int isonum_733(unsigned char * p); +static void reset_tty(void); +static void set_tty(void); +static void onsusp(int signo); +static void crsr2(int row, int col); +static int parse_rr(unsigned char * pnt, int len, int cont_flag); +static void dump_rr(struct iso_directory_record * idr); +static void showblock(int flag); +static int getbyte(void); +static void usage(int excode); + +static int +isonum_731(char *p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +static int +isonum_721(char *p) +{ + return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); +} + +static int +isonum_723(char *p) +{ +#if 0 + if (p[0] != p[3] || p[1] != p[2]) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "invalid format 7.2.3 number\n"); +#else + fprintf(stderr, "invalid format 7.2.3 number\n"); + exit(1); +#endif + } +#endif + return (isonum_721(p)); +} + + +static int +isonum_733(unsigned char *p) +{ + return (isonum_731((char *)p)); +} + +#ifdef USE_V7_TTY +static struct sgttyb savetty; +static struct sgttyb newtty; +#else +static struct termios savetty; +static struct termios newtty; +#endif + +static void +reset_tty() +{ +#ifdef USE_V7_TTY + if (ioctl(STDIN_FILENO, TIOCSETN, &savetty) == -1) { +#else +#ifdef TCSANOW + if (tcsetattr(STDIN_FILENO, TCSANOW, &savetty) == -1) { +#else + if (ioctl(STDIN_FILENO, TCSETAF, &savetty) == -1) { +#endif +#endif +#ifdef USE_LIBSCHILY + comerr("Cannot put tty into normal mode\n"); +#else + printf("Cannot put tty into normal mode\n"); + exit(1); +#endif + } +} + +static void +set_tty() +{ +#ifdef USE_V7_TTY + if (ioctl(STDIN_FILENO, TIOCSETN, &newtty) == -1) { +#else +#ifdef TCSANOW + if (tcsetattr(STDIN_FILENO, TCSANOW, &newtty) == -1) { +#else + if (ioctl(STDIN_FILENO, TCSETAF, &newtty) == -1) { +#endif +#endif +#ifdef USE_LIBSCHILY + comerr("Cannot put tty into raw mode\n"); +#else + printf("Cannot put tty into raw mode\n"); + exit(1); +#endif + } +} + +/* Come here when we get a suspend signal from the terminal */ + +static void +onsusp(int signo) +{ +#ifdef SIGTTOU + /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */ + signal(SIGTTOU, SIG_IGN); +#endif + reset_tty(); + fflush(stdout); +#ifdef SIGTTOU + 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); +#endif + set_tty(); +} + + + +static void +crsr2(int row, int col) +{ + printf("\033[%d;%dH", row, col); +} + +static int +parse_rr(unsigned char *pnt, int len, int cont_flag) +{ + int slen; + int ncount; + int extent; + off_t cont_extent; + int cont_offset; + int cont_size; + int flag1; + int flag2; + unsigned char *pnts; + char symlinkname[1024]; + char name[1024]; + int goof; + +/* printf(" RRlen=%d ", len); */ + + symlinkname[0] = 0; + + cont_extent = (off_t)0; + 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 && pnt[3] != 2) { + printf("**BAD RRVERSION (%d) for %c%c\n", pnt[3], pnt[0], pnt[1]); + return (0); /* JS ??? Is this right ??? */ + } else if (pnt[0] == 'R' && pnt[1] == 'R') { + printf("=%d", pnt[3]); + } + ncount++; + if (pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; + if (strncmp((char *)pnt, "PX", 2) == 0) flag2 |= 1; + if (strncmp((char *)pnt, "PN", 2) == 0) flag2 |= 2; + if (strncmp((char *)pnt, "SL", 2) == 0) flag2 |= 4; + if (strncmp((char *)pnt, "NM", 2) == 0) { + slen = pnt[2] - 5; + pnts = pnt+5; + if ((pnt[4] & 6) != 0) { + printf("*"); + } + memset(name, 0, sizeof (name)); + memcpy(name, pnts, slen); + printf("=%s", name); + flag2 |= 8; + } + if (strncmp((char *)pnt, "CL", 2) == 0) flag2 |= 16; + if (strncmp((char *)pnt, "PL", 2) == 0) flag2 |= 32; + if (strncmp((char *)pnt, "RE", 2) == 0) flag2 |= 64; + if (strncmp((char *)pnt, "TF", 2) == 0) flag2 |= 128; + + if (strncmp((char *)pnt, "PX", 2) == 0) { + extent = isonum_733(pnt+12); + printf("=%x", extent); + } + + if (strncmp((char *)pnt, "CE", 2) == 0) { + cont_extent = (off_t)isonum_733(pnt+4); + cont_offset = isonum_733(pnt+12); + cont_size = isonum_733(pnt+20); + printf("=[%x,%x,%d]", (int)cont_extent, cont_offset, + cont_size); + } + + if (strncmp((char *)pnt, "PL", 2) == 0 || strncmp((char *)pnt, "CL", 2) == 0) { + extent = isonum_733(pnt+4); + printf("=%x", extent); + } + + if (strncmp((char *)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(symlinkname, (char *)(pnts+2), pnts[1]); + break; + case 2: + strcat(symlinkname, "."); + break; + case 4: + strcat(symlinkname, ".."); + break; + case 8: + if ((pnts[0] & 1) == 0) + strcat(symlinkname, "/"); + break; + case 16: + strcat(symlinkname, "/mnt"); + printf("Warning - mount point requested"); + break; + case 32: + strcat(symlinkname, "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(symlinkname, "/"); + + slen -= (pnts[1] + 2); + pnts += (pnts[1] + 2); + } + if (cflag) + strcat(symlinkname, "+"); + printf("=%s", symlinkname); + symlinkname[0] = 0; + } + + len -= pnt[2]; + pnt += pnt[2]; + if (len <= 3 && cont_extent) { + unsigned char sector[2048]; + +#ifdef USE_SCG + readsecs(cont_extent * blocksize / 2048, sector, ISO_BLOCKS(sizeof (sector))); +#else + lseek(fileno(infile), cont_extent * blocksize, SEEK_SET); + read(fileno(infile), sector, sizeof (sector)); +#endif + 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); +} + +static void +dump_rr(struct iso_directory_record *idr) +{ + int len; + unsigned char *pnt; + + len = idr->length[0] & 0xff; + len -= offsetof(struct iso_directory_record, name[0]); + len -= idr->name_len[0]; + pnt = (unsigned char *) idr; + pnt += offsetof(struct iso_directory_record, name[0]); + pnt += idr->name_len[0]; + if ((idr->name_len[0] & 1) == 0) { + pnt++; + len--; + } + parse_rr(pnt, len, 0); +} + + +static void +showblock(int flag) +{ + int i; + int j; + int line; + struct iso_directory_record *idr; + +#ifdef USE_SCG + readsecs(file_addr / 2048, buffer, ISO_BLOCKS(sizeof (buffer))); +#else + lseek(fileno(infile), file_addr, SEEK_SET); + read(fileno(infile), buffer, sizeof (buffer)); +#endif + for (i = 0; i < 60; i++) + printf("\n"); + fflush(stdout); + i = line = 0; + if (flag) { + while (1 == 1) { + crsr2(line+3, 1); + idr = (struct iso_directory_record *) &buffer[i]; + if (idr->length[0] == 0) + break; + printf("%3d ", idr->length[0]); + printf("[%2d] ", idr->volume_sequence_number[0]); + printf("%5x ", isonum_733(idr->extent)); + printf("%8d ", isonum_733(idr->size)); + printf("%02x/", idr->flags[0]); + printf((idr->flags[0] & 2) ? "*" : " "); + if (idr->name_len[0] == 1 && idr->name[0] == 0) + printf(". "); + else if (idr->name_len[0] == 1 && idr->name[0] == 1) + printf(".. "); + else { + for (j = 0; j < (int)idr->name_len[0]; j++) printf("%c", idr->name[j]); + for (j = 0; j < (14 - (int)idr->name_len[0]); j++) printf(" "); + } + dump_rr(idr); + printf("\n"); + i += buffer[i]; + if (i > 2048 - offsetof(struct iso_directory_record, name[0])) + break; + line++; + } + } + printf("\n"); + if (sizeof (file_addr) > sizeof (long)) { + printf(" Zone, zone offset: %14llx %12.12llx ", + (Llong)file_addr / blocksize, + (Llong)file_addr & (Llong)(blocksize - 1)); + } else { + printf(" Zone, zone offset: %6lx %4.4lx ", + (long) (file_addr / blocksize), + (long) file_addr & (blocksize - 1)); + } + fflush(stdout); +} + +static int +getbyte() +{ + char c1; + + c1 = buffer[file_addr & (blocksize-1)]; + file_addr++; + if ((file_addr & (blocksize-1)) == 0) + showblock(0); + return (c1); +} + +static void +usage(int excode) +{ + errmsgno(EX_BAD, "Usage: %s [options] image\n", + get_progname()); + + fprintf(stderr, "Options:\n"); + fprintf(stderr, "\t-help, -h Print this help\n"); + fprintf(stderr, "\t-version Print version info and exit\n"); + fprintf(stderr, "\t-i filename Filename to read ISO-9660 image from\n"); + fprintf(stderr, "\tdev=target SCSI target to use as CD/DVD-Recorder\n"); + fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n"); + exit(excode); +} + +int +main(int argc, char *argv[]) +{ + int cac; + char * const *cav; + char *opts = "help,h,version,i*,dev*"; + BOOL help = FALSE; + BOOL prvers = FALSE; + char *filename = NULL; + char *devname = NULL; + char c; + int i; + struct iso_primary_descriptor ipd; + struct iso_directory_record *idr; + + save_args(argc, argv); + + cac = argc - 1; + cav = argv + 1; + if (getallargs(&cac, &cav, opts, &help, &help, &prvers, + &filename, &devname) < 0) { + errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]); + usage(EX_BAD); + } + if (help) + usage(0); + if (prvers) { + printf("isodump %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM); + exit(0); + } + cac = argc - 1; + cav = argv + 1; + if (filename == NULL && devname == NULL) { + if (getfiles(&cac, &cav, opts) != 0) { + filename = cav[0]; + cac--, cav++; + } + } + if (getfiles(&cac, &cav, opts) != 0) { + errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]); + usage(EX_BAD); + } + if (filename != NULL && devname != NULL) { + errmsgno(EX_BAD, "Only one of -i or dev= allowed\n"); + usage(EX_BAD); + } +#ifdef USE_SCG + if (filename == NULL && devname == NULL) + cdr_defaults(&devname, NULL, NULL, NULL); +#endif + if (filename == NULL && devname == NULL) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "ISO-9660 image not specified\n"); +#else + fprintf(stderr, "ISO-9660 image not specified\n"); +#endif + usage(EX_BAD); + } + + if (filename != NULL) + infile = fopen(filename, "rb"); + else + filename = devname; + + if (infile != NULL) { + /* EMPTY */; +#ifdef USE_SCG + } else if (scsidev_open(filename) < 0) { +#else + } else { +#endif +#ifdef USE_LIBSCHILY + comerr("Cannot open '%s'\n", filename); +#else + fprintf(stderr, "Cannot open '%s'\n", filename); + exit(1); +#endif + } + + file_addr = (off_t) (16 << 11); +#ifdef USE_SCG + readsecs(file_addr / 2048, &ipd, ISO_BLOCKS(sizeof (ipd))); +#else + lseek(fileno(infile), file_addr, SEEK_SET); + read(fileno(infile), &ipd, sizeof (ipd)); +#endif + idr = (struct iso_directory_record *)ipd.root_directory_record; + + blocksize = isonum_723((char *)ipd.logical_block_size); + if (blocksize != 512 && blocksize != 1024 && blocksize != 2048) { + blocksize = 2048; + } + + file_addr = (off_t)isonum_733(idr->extent); + file_addr = file_addr * blocksize; + +/* Now setup the keyboard for single character input. */ +#ifdef USE_V7_TTY + if (ioctl(STDIN_FILENO, TIOCGETP, &savetty) == -1) { +#else +#ifdef TCSANOW + if (tcgetattr(STDIN_FILENO, &savetty) == -1) { +#else + if (ioctl(STDIN_FILENO, TCGETA, &savetty) == -1) { +#endif +#endif +#ifdef USE_LIBSCHILY + comerr("Stdin must be a tty\n"); +#else + printf("Stdin must be a tty\n"); + exit(1); +#endif + } + newtty = savetty; +#ifdef USE_V7_TTY + newtty.sg_flags &= ~(ECHO|CRMOD); + newtty.sg_flags |= CBREAK; +#else + newtty.c_lflag &= ~ICANON; + newtty.c_lflag &= ~ECHO; + newtty.c_cc[VMIN] = 1; +#endif + set_tty(); +#ifdef SIGTSTP + signal(SIGTSTP, onsusp); +#endif + on_comerr((void(*)(int, void *))reset_tty, NULL); + + do { + if (file_addr < 0) + file_addr = (off_t)0; + showblock(1); + read(STDIN_FILENO, &c, 1); /* FIXME: check return value */ + if (c == 'a') + file_addr -= blocksize; + if (c == 'b') + file_addr += blocksize; + if (c == 'g') { + crsr2(20, 1); + printf("Enter new starting block (in hex):"); + if (sizeof (file_addr) > sizeof (long)) { + Llong ll; + scanf("%llx", &ll); /* FIXME: check return value */ + file_addr = (off_t)ll; + } else { + long l; + scanf("%lx", &l); /* FIXME: check return value */ + file_addr = (off_t)l; + } + file_addr = file_addr * blocksize; + crsr2(20, 1); + printf(" "); + } + if (c == 'f') { + crsr2(20, 1); + printf("Enter new search string:"); + fgets((char *)search, sizeof (search), stdin); /* FIXME: check return value */ + while (search[strlen((char *)search)-1] == '\n') + search[strlen((char *)search)-1] = 0; + crsr2(20, 1); + printf(" "); + } + if (c == '+') { + while (1 == 1) { + int slen; + + while (1 == 1) { + c = getbyte(); + if (c == search[0]) + break; + } + slen = (int)strlen((char *)search); + for (i = 1; i < slen; i++) { + if (search[i] != getbyte()) + break; + } + if (i == slen) + break; + } + file_addr &= ~(blocksize-1); + showblock(1); + } + if (c == 'q') + break; + } while (1 == 1); + reset_tty(); + if (infile != NULL) + fclose(infile); + return (0); +} diff --git a/genisoimage/diag/isoinfo.1 b/genisoimage/diag/isoinfo.1 new file mode 100644 index 0000000..1a00540 --- /dev/null +++ b/genisoimage/diag/isoinfo.1 @@ -0,0 +1,365 @@ +.\" +.\" @(#)isoinfo.8 1.7 04/06/01 joerg +.\" +.\" Modified for cdrkit in 12/2006 +.\" +.\" -*- nroff -*- +.if t .ds a \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'a +.if t .ds o \v'-0.55m'\h'0.00n'\z.\h'0.45n'\z.\v'0.55m'\h'-0.45n'o +.if t .ds u \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'u +.if t .ds A \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'A +.if t .ds O \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'O +.if t .ds U \v'-0.77m'\h'0.30n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.75n'U +.if t .ds s \\(*b +.if t .ds S SS +.if n .ds a ae +.if n .ds o oe +.if n .ds u ue +.if n .ds s sz +.TH ISOINFO 1 "04/06/01" "Version 2.0" +.SH NAME +devdump, isoinfo, isovfy, isodump \- Utility programs for dumping and verifying iso9660 +images. +.SH SYNOPSIS +.B devdump +.I isoimage +.PP +.B isodump +.I isoimage +.PP +.B isoinfo +[ +.B \-d +] +[ +.B \-h +] +[ +.B \-R +] +[ +.B \-J +] +[ +.B \-j +.I charset +] +[ +.B \-f +] +[ +.B \-l +] +[ +.B \-p +] +[ +.B \-T +.I sector +] +[ +.B \-N +.I sector +] +[ +.B \-i +.I isoimage +] +[ +.B \-x +.I path +] +.PP +.B isovfy +.I isoimage +.SH DESCRIPTION +.B devdump +is a crude utility to interactively display the contents of device or +filesystem images. +The initial screen is a display of the first 256 bytes of the first 2048 byte +sector. +The commands are the same as with +.BR isodump . +.PP +.B isodump +is a crude utility to interactively display the contents of iso9660 images +in order to verify directory integrity. +The initial screen is a display of the first part of the root directory, +and the prompt shows you the extent number and offset in the extent. +.RS +.PP +You can use the 'a' and 'b' +commands to move backwards and forwards within the image. The 'g' command +allows you to goto an arbitrary extent, and the 'f' command specifies +a search string to be used. The '+' command searches forward for the next +instance of the search string, and the 'q' command exits +.B devdump +or +.BR isodump . +.RE +.PP +.B isoinfo +is a utility to perform directory like listings of iso9660 images. +.PP +.B isovfy +is a utility to verify the integrity of an iso9660 image. Most of the tests +in +.B isovfy +were added after bugs were discovered in early versions of +.B genisoimage. +It isn't all that clear how useful this is anymore, but it doesn't hurt to +have this around. + +.SH OPTIONS +The options common to all programs are +.BR \-help , \-h , \-version , +.BI i =name, dev =name. +The +.B isoinfo +program has additional command line options. The options are: +.TP +.B \-help +.TP +.B \-h +print a summary of all options. +.TP +.B \-d +Print information from the primary volume descriptor (PVD) of the iso9660 +image. This includes information about Rock Ridge, Joliet extensions +and Eltorito boot information +if present. +.TP +.B \-f +generate output as if a 'find . -print' command had been run on the iso9660 +image. You should not use the +.B -l +image with the +.B -f +option. +.TP +.B \-i iso_image +Specifies the path of the iso9660 image that we wish to examine. +The options +.B \-i +and +.BI dev= target +are mutual exclusive. +.TP +.BI dev= target +Sets the SCSI target for the drive, see notes above. +A typical device specification is +.BI dev= 6,0 +\&. +If a filename must be provided together with the numerical target +specification, the filename is implementation specific. +The correct filename in this case can be found in the system specific +manuals of the target operating system. +On a +.I FreeBSD +system without +.I CAM +support, you need to use the control device (e.g. +.IR /dev/rcd0.ctl ). +A correct device specification in this case may be +.BI dev= /dev/rcd0.ctl:@ +\&. +.sp +On Linux, drives connected to a parallel port adapter are mapped +to a virtual SCSI bus. Different adapters are mapped to different +targets on this virtual SCSI bus. +.sp +If no +.I dev +option is present, the program +will try to get the device from the +.B CDR_DEVICE +environment. +.sp +If the argument to the +.B dev= +option does not contain the characters ',', '/', '@' or ':', +it is interpreted as an label name that may be found in the file +/etc/wodim.conf (see FILES section). +.sp +The options +.B \-i +and +.BI dev= target +are mutual exclusive. +.TP +.B \-l +generate output as if a 'ls -lR' command had been run on the iso9660 image. +You should not use the +.B -f +image with the +.B -l +option. +.TP +.B \-N sector +Quick hack to help examine single session disc files that are to be written to +a multi-session disc. The sector number specified is the sector number at +which the iso9660 image should be written when send to the cd-writer. Not +used for the first session on the disc. +.TP +.B \-p +Print path table information. +.TP +.B \-R +Extract information from Rock Ridge extensions (if present) for permissions, +file names and ownerships. +.TP +.B \-J +Extract information from Joliet extensions (if present) for file names. +.TP +.B \-j charset +Convert Joliet file names (if present) to the supplied charset. See +.BR genisoimage (8) +for details. +.TP +.B \-T sector +Quick hack to help examine multi-session images that have already been burned +to a multi-session disc. The sector number specified is the sector number for +the start of the session we wish to display. +.TP +.B \-x pathname +Extract specified file to stdout. +.SH AUTHOR +The author of the original sources (1993 .\|.\|. 1998) is +Eric Youngdale <ericy@gnu.ai.mit.edu> or <eric@andante.jic.com> is to blame +for these shoddy hacks. +J\*org Schilling wrote the SCSI transport library and its adaptation layer to +the programs and newer parts (starting from 1999) of the utilities, this makes +them +Copyright (C) 1999-2004 J\*org Schilling. +Patches to improve general usability would be gladly accepted. +.PP +This manpage describes the program implementation of +.B +isoinfo +as shipped by the cdrkit distribution. See +.B +http://alioth.debian.org/projects/debburn/ +for details. It is a spinoff from the original program distributed in the +cdrtools package [1]. However, the cdrtools +developers are not involved in the development of this spinoff and therefore +shall not be made responsible for any problem caused by it. Do not try to get +support for this program by contacting the original author(s). +.PP +If you have support questions, send them to +.PP +.B +debburn-devel@lists.alioth.debian.org +.br +.PP +If you have definitely found a bug, send a mail to this list or to +.PP +.B +submit@bugs.debian.org +.br +.PP +writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body. +.SH BUGS +The user interface really sucks. +.SH FUTURE IMPROVEMENTS +These utilities are really quick hacks, which are very useful for debugging +problems in genisoimage or in an iso9660 filesystem. In the long run, it would +be nice to have a daemon that would NFS export a iso9660 image. +.PP +The isoinfo program is probably the program that is of the most use to +the general user. +.SH AVAILABILITY +These utilities come with the +.B cdrkit +package, and the primary download site +is http://debburn.alioth.debian.org/ and FTP mirrors of distributions. +Despite the name, the software is not beta. + +.SH ENVIRONMENT +.TP +.B CDR_DEVICE +This may either hold a device identifier that is suitable to the open +call of the SCSI transport library or a label in the file /etc/wodim.conf. +.TP +.B RSH +If the +.B RSH +environment is present, the remote connection will not be created via +.BR rcmd (3) +but by calling the program pointed to by +.BR RSH . +Use e.g. +.BR RSH= /usr/bin/ssh +to create a secure shell connection. +.sp +Note that this forces the program +to create a pipe to the +.B rsh(1) +program and disallows the program +to directly access the network socket to the remote server. +This makes it impossible to set up performance parameters and slows down +the connection compared to a +.B root +initiated +.B rcmd(3) +connection. +.TP +.B RSCSI +If the +.B RSCSI +environment is present, the remote SCSI server will not be the program +.B /opt/schily/sbin/rscsi +but the program pointed to by +.BR RSCSI . +Note that the remote SCSI server program name will be ignored if you log in +using an account that has been created with a remote SCSI server program as +login shell. + +.SH FILES +.TP +/etc/wodim.conf +Default values can be set for the following options in /etc/wodim.conf. +.RS +.TP +CDR_DEVICE +This may either hold a device identifier that is suitable to the open +call of the SCSI transport library or a label in the file /etc/wodim.conf +that allows to identify a specific drive on the system. +.TP +Any other label +is an identifier for a specific drive on the system. +Such an identifier may not contain the characters ',', '/', '@' or ':'. +.sp +Each line that follows a label contains a TAB separated list of items. +Currently, four items are recognized: the SCSI ID of the drive, the +default speed that should be used for this drive, the default FIFO size +that should be used for this drive and drive specific options. The values for +.I speed +and +.I fifosize +may be set to -1 to tell the program to use the global defaults. +The value for driveropts may be set to "" if no driveropts are used. +A typical line may look this way: +.sp +teac1= 0,5,0 4 8m "" +.sp +yamaha= 1,6,0 -1 -1 burnfree +.sp +This tells the program +that a drive named +.I teac1 +is at scsibus 0, target 5, lun 0 and should be used with speed 4 and +a FIFO size of 8 MB. +A second drive may be found at scsibus 1, target 6, lun 0 and uses the +default speed and the default FIFO size. +.RE +.SH SEE ALSO +.BR genisoimage (1), +.BR wodim (1), +.BR readcd (1), +.BR ssh (1). +.RE +.SH SOURCES +.PP +.br +[1] Cdrtools 2.01.01a08 from May 2006, http://cdrecord.berlios.de + diff --git a/genisoimage/diag/isoinfo.c b/genisoimage/diag/isoinfo.c new file mode 100644 index 0000000..55396c2 --- /dev/null +++ b/genisoimage/diag/isoinfo.c @@ -0,0 +1,1321 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)isoinfo.c 1.50 05/05/15 joerg */ +/* + * File isodump.c - dump iso9660 directory information. + * + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * Copyright (c) 1999-2004 J. Schilling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Simple program to dump contents of iso9660 image in more usable format. + * + * Usage: + * To list contents of image (with or without RR): + * isoinfo -l [-R] -i imagefile + * To extract file from image: + * isoinfo -i imagefile -x xtractfile > outfile + * To generate a "find" like list of files: + * isoinfo -f -i imagefile + */ + +#include <mconfig.h> +#include <stdxlib.h> +#include <unixstd.h> +#include <strdefs.h> + +#include <stdio.h> +#include <utypes.h> +#include <standard.h> +#include <signal.h> +#include <sys/stat.h> +#include <statdefs.h> +#include <fctldefs.h> +#include <schily.h> + +#include "../iso9660.h" +#include "../scsi.h" +#include "../../wodim/defaults.h" + +#include <unls.h> + +#if defined(__CYGWIN32__) || defined(__EMX__) || defined(__DJGPP__) +#include <io.h> /* for setmode() prototype */ +#endif + +/* + * Make sure we have a definition for this. If not, take a very conservative + * guess. + * POSIX requires the max pathname component lenght to be defined in limits.h + * If variable, it may be undefined. If undefined, there should be + * a definition for _POSIX_NAME_MAX in limits.h or in unistd.h + * As _POSIX_NAME_MAX is defined to 14, we cannot use it. + * XXX Eric's wrong comment: + * XXX From what I can tell SunOS is the only one with this trouble. + */ +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +#ifndef NAME_MAX +#ifdef FILENAME_MAX +#define NAME_MAX FILENAME_MAX +#else +#define NAME_MAX 256 +#endif +#endif + +#ifndef PATH_MAX +#ifdef FILENAME_MAX +#define PATH_MAX FILENAME_MAX +#else +#define PATH_MAX 1024 +#endif +#endif + +/* + * XXX JS: Some structures have odd lengths! + * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length. + * For this reason, we cannot use sizeof (struct iso_path_table) or + * sizeof (struct iso_directory_record) to compute on disk sizes. + * Instead, we use offsetof(..., name) and add the name size. + * See iso9660.h + */ +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#ifndef S_ISLNK +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#endif +#ifndef S_ISSOCK +#ifdef S_IFSOCK +# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +#else +# define S_ISSOCK(m) (0) +#endif +#endif + +/* + * Note: always use these macros to avoid problems. + * + * ISO_ROUND_UP(X) may cause an integer overflow and thus give + * incorrect results. So avoid it if possible. + * + * ISO_BLOCKS(X) is overflow safe. Prefer this when ever it is possible. + */ +#define SECTOR_SIZE (2048) +#define ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1)) +#define ISO_BLOCKS(X) (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0)) + +#define infile in_image +FILE *infile = NULL; +int use_rock = 0; +int use_joliet = 0; +int do_listing = 0; +int do_find = 0; +int do_sectors = 0; +int do_pathtab = 0; +int do_pvd = 0; +BOOL debug = FALSE; +char *xtract = 0; +int su_version = 0; +int aa_version = 0; +int ucs_level = 0; + +struct stat fstat_buf; +int found_rr; +char name_buf[256]; +char xname[2048]; +unsigned char date_buf[9]; +/* + * Use sector_offset != 0 (-N #) if we have an image file + * of a single session and we need to list the directory contents. + * This is the session block (sector) number of the start + * of the session when it would be on disk. + */ +unsigned int sector_offset = 0; + +unsigned char buffer[2048]; + +struct unls_table *unls; + +#define PAGE sizeof (buffer) + +#define ISODCL(from, to) (to - from + 1) + + +int isonum_721(char * p); +int isonum_723(char * p); +int isonum_731(char * p); +int isonum_732(char * p); +int isonum_733(unsigned char * p); +void printchars(char *s, int n); +char *sdate(char *dp); +void dump_pathtab(int block, int size); +int parse_rr(unsigned char * pnt, int len, int cont_flag); +void find_rr(struct iso_directory_record * idr, Uchar **pntp, int *lenp); +int dump_rr(struct iso_directory_record * idr); +void dump_stat(struct iso_directory_record * idr, int extent); +void extract_file(struct iso_directory_record * idr); +void parse_dir(char * rootname, int extent, int len); +void usage(int excode); + +static void printf_bootinfo(FILE *f, int bootcat_offset); +static char *arch_name(int val); +static char *boot_name(int val); +static char *bootmedia_name(int val); + + +int +isonum_721(char *p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8)); +} + +int +isonum_723(char *p) +{ +#if 0 + if (p[0] != p[3] || p[1] != p[2]) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "invalid format 7.2.3 number\n"); +#else + fprintf(stderr, "invalid format 7.2.3 number\n"); + exit(1); +#endif + } +#endif + return (isonum_721(p)); +} + +int +isonum_731(char *p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +int +isonum_732(char *p) +{ + return ((p[3] & 0xff) + | ((p[2] & 0xff) << 8) + | ((p[1] & 0xff) << 16) + | ((p[0] & 0xff) << 24)); +} + +int +isonum_733(unsigned char *p) +{ + return (isonum_731((char *)p)); +} + +void +printchars(char *s, int n) +{ + int i; + char *p; + + for (; n > 0 && *s; n--) { + if (*s == ' ') { + p = s; + i = n; + while (--i >= 0 && *p++ == ' ') + ; + if (i <= 0) + break; + } + putchar(*s++); + } +} + +/* + * Print date info from PVD + */ +char * +sdate(char *dp) +{ + static char d[30]; + + sprintf(d, "%4.4s %2.2s %2.2s %2.2s:%2.2s:%2.2s.%2.2s", + &dp[0], /* Year */ + &dp[4], /* Month */ + &dp[6], /* Monthday */ + &dp[8], /* Hour */ + &dp[10], /* Minute */ + &dp[12], /* Seconds */ + &dp[14]); /* Hunreds of a Seconds */ + + /* + * dp[16] contains minute offset from Greenwich + * Positive values are to the east of Greenwich. + */ + return (d); +} + +void +dump_pathtab(int block, int size) +{ + unsigned char *buf; + int offset; + int idx; + int extent; + int pindex; + int j; + int len; + int jlen; + char namebuf[255]; + unsigned char uh, ul, uc, *up; + + + printf("Path table starts at block %d, size %d\n", block, size); + + buf = (unsigned char *) malloc(ISO_ROUND_UP(size)); + +#ifdef USE_SCG + readsecs(block - sector_offset, buf, ISO_BLOCKS(size)); +#else + lseek(fileno(infile), ((off_t)(block - sector_offset)) << 11, SEEK_SET); + read(fileno(infile), buf, size); +#endif + + offset = 0; + idx = 1; + while (offset < size) { + len = buf[offset]; + extent = isonum_731((char *)buf + offset + 2); + pindex = isonum_721((char *)buf + offset + 6); + switch (ucs_level) { + case 3: + case 2: + case 1: + jlen = len/2; + namebuf[0] = '\0'; + for (j = 0; j < jlen; j++) { + uh = buf[offset + 8 + j*2]; + ul = buf[offset + 8 + j*2+1]; + + up = unls->unls_uni2cs[uh]; + + if (up == NULL) + uc = '\0'; + else + uc = up[ul]; + + namebuf[j] = uc ? uc : '_'; + } + printf("%4d: %4d %x %.*s\n", + idx, pindex, extent, jlen, namebuf); + break; + case 0: + printf("%4d: %4d %x %.*s\n", + idx, pindex, extent, len, buf + offset + 8); + } + + idx++; + offset += 8 + len; + if (offset & 1) + offset++; + } + + free(buf); +} + +int +parse_rr(unsigned char *pnt, int len, int cont_flag) +{ + int slen; + int xlen; + int ncount; + int extent; + int cont_extent, cont_offset, cont_size; + int flag1, flag2; + unsigned char *pnts; + char symlinkname[1024]; + int goof; + + symlinkname[0] = 0; + + cont_extent = cont_offset = cont_size = 0; + + ncount = 0; + flag1 = flag2 = 0; + while (len >= 4) { + if (pnt[3] != 1 && pnt[3] != 2) { + printf("**BAD RRVERSION (%d)\n", pnt[3]); + return (0); /* JS ??? Is this right ??? */ + } + ncount++; + if (pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; + if (strncmp((char *)pnt, "PX", 2) == 0) flag2 |= 1; /* POSIX attributes */ + if (strncmp((char *)pnt, "PN", 2) == 0) flag2 |= 2; /* POSIX device number */ + if (strncmp((char *)pnt, "SL", 2) == 0) flag2 |= 4; /* Symlink */ + if (strncmp((char *)pnt, "NM", 2) == 0) flag2 |= 8; /* Alternate Name */ + if (strncmp((char *)pnt, "CL", 2) == 0) flag2 |= 16; /* Child link */ + if (strncmp((char *)pnt, "PL", 2) == 0) flag2 |= 32; /* Parent link */ + if (strncmp((char *)pnt, "RE", 2) == 0) flag2 |= 64; /* Relocated Direcotry */ + if (strncmp((char *)pnt, "TF", 2) == 0) flag2 |= 128; /* Time stamp */ + if (strncmp((char *)pnt, "SP", 2) == 0) { + flag2 |= 1024; /* SUSP record */ + su_version = pnt[3] & 0xff; + } + if (strncmp((char *)pnt, "AA", 2) == 0) { + flag2 |= 2048; /* Apple Signature record */ + aa_version = pnt[3] & 0xff; + } + + if (strncmp((char *)pnt, "PX", 2) == 0) { /* POSIX attributes */ + fstat_buf.st_mode = isonum_733(pnt+4); + fstat_buf.st_nlink = isonum_733(pnt+12); + fstat_buf.st_uid = isonum_733(pnt+20); + fstat_buf.st_gid = isonum_733(pnt+28); + } + + if (strncmp((char *)pnt, "NM", 2) == 0) { /* Alternate Name */ + int l = strlen(name_buf); + + if (!found_rr) + l = 0; + strncpy(&name_buf[l], (char *)(pnt+5), pnt[2] - 5); + name_buf[l + pnt[2] - 5] = 0; + found_rr = 1; + } + + if (strncmp((char *)pnt, "CE", 2) == 0) { /* Continuation Area */ + cont_extent = isonum_733(pnt+4); + cont_offset = isonum_733(pnt+12); + cont_size = isonum_733(pnt+20); + } + + if (strncmp((char *)pnt, "PL", 2) == 0 || strncmp((char *)pnt, "CL", 2) == 0) { + extent = isonum_733(pnt+4); + } + + if (strncmp((char *)pnt, "SL", 2) == 0) { /* Symlink */ + int cflag; + + cflag = pnt[4]; + pnts = pnt+5; + slen = pnt[2] - 5; + while (slen >= 1) { + switch (pnts[0] & 0xfe) { + case 0: + strncat(symlinkname, (char *)(pnts+2), pnts[1]); + symlinkname[pnts[1]] = 0; + break; + case 2: + strcat(symlinkname, "."); + break; + case 4: + strcat(symlinkname, ".."); + break; + case 8: + strcat(symlinkname, "/"); + break; + case 16: + strcat(symlinkname, "/mnt"); + printf("Warning - mount point requested"); + break; + case 32: + strcat(symlinkname, "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 (xname[0] == 0) strcpy(xname, "-> "); + strcat(xname, symlinkname); + symlinkname[0] = 0; + xlen = strlen(xname); + if ((pnts[0] & 1) == 0 && xname[xlen-1] != '/') strcat(xname, "/"); + + slen -= (pnts[1] + 2); + pnts += (pnts[1] + 2); + } + symlinkname[0] = 0; + } + + len -= pnt[2]; + pnt += pnt[2]; + if (len <= 3 && cont_extent) { + unsigned char sector[2048]; + +#ifdef USE_SCG + readsecs(cont_extent - sector_offset, sector, ISO_BLOCKS(sizeof (sector))); +#else + lseek(fileno(infile), ((off_t)(cont_extent - sector_offset)) << 11, SEEK_SET); + read(fileno(infile), sector, sizeof (sector)); +#endif + flag2 |= parse_rr(§or[cont_offset], cont_size, 1); + } + } + /* + * for symbolic links, strip out the last '/' + */ + if (xname[0] != 0 && xname[strlen(xname)-1] == '/') { + xname[strlen(xname)-1] = '\0'; + } + return (flag2); +} + +void +find_rr(struct iso_directory_record *idr, Uchar **pntp, int *lenp) +{ + struct iso_xa_dir_record *xadp; + int len; + unsigned char * pnt; + + len = idr->length[0] & 0xff; + len -= offsetof(struct iso_directory_record, name[0]); + len -= idr->name_len[0]; + + pnt = (unsigned char *) idr; + pnt += offsetof(struct iso_directory_record, name[0]); + pnt += idr->name_len[0]; + if ((idr->name_len[0] & 1) == 0) { + pnt++; + len--; + } + if (len >= 14) { + xadp = (struct iso_xa_dir_record *)pnt; + + if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' && + xadp->reserved[0] == '\0') { + len -= 14; + pnt += 14; + } + } + *pntp = pnt; + *lenp = len; +} + +int +dump_rr(struct iso_directory_record *idr) +{ + int len; + unsigned char * pnt; + + find_rr(idr, &pnt, &len); + return (parse_rr(pnt, len, 0)); +} + +struct todo +{ + struct todo *next; + char *name; + int extent; + int length; +}; + +struct todo *todo_idr = NULL; + +char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", + "Aug", "Sep", "Oct", "Nov", "Dec"}; + +void +dump_stat(struct iso_directory_record *idr, int extent) +{ + int i; + char outline[80]; + + memset(outline, ' ', sizeof (outline)); + + if (S_ISREG(fstat_buf.st_mode)) + outline[0] = '-'; + else if (S_ISDIR(fstat_buf.st_mode)) + outline[0] = 'd'; + else if (S_ISLNK(fstat_buf.st_mode)) + outline[0] = 'l'; + else if (S_ISCHR(fstat_buf.st_mode)) + outline[0] = 'c'; + else if (S_ISBLK(fstat_buf.st_mode)) + outline[0] = 'b'; + else if (S_ISFIFO(fstat_buf.st_mode)) + outline[0] = 'f'; + else if (S_ISSOCK(fstat_buf.st_mode)) + outline[0] = 's'; + else + outline[0] = '?'; + + memset(outline+1, '-', 9); + if (fstat_buf.st_mode & S_IRUSR) + outline[1] = 'r'; + if (fstat_buf.st_mode & S_IWUSR) + outline[2] = 'w'; + if (fstat_buf.st_mode & S_IXUSR) + outline[3] = 'x'; + + if (fstat_buf.st_mode & S_IRGRP) + outline[4] = 'r'; + if (fstat_buf.st_mode & S_IWGRP) + outline[5] = 'w'; + if (fstat_buf.st_mode & S_IXGRP) + outline[6] = 'x'; + + if (fstat_buf.st_mode & S_IROTH) + outline[7] = 'r'; + if (fstat_buf.st_mode & S_IWOTH) + outline[8] = 'w'; + if (fstat_buf.st_mode & S_IXOTH) + outline[9] = 'x'; + + /* + * XXX This is totally ugly code from Eric. + * XXX If one field is wider than expected then it is truncated. + */ + sprintf(outline+11, "%3ld", (long)fstat_buf.st_nlink); + sprintf(outline+15, "%4lo", (unsigned long)fstat_buf.st_uid); + sprintf(outline+20, "%4lo", (unsigned long)fstat_buf.st_gid); + sprintf(outline+30, "%10lld", (Llong)fstat_buf.st_size); + + if (do_sectors == 0) { + sprintf(outline+30, "%10lld", (Llong)fstat_buf.st_size); + } else { + sprintf(outline+30, "%10lld", (Llong)((fstat_buf.st_size+PAGE-1)/PAGE)); + } + + if (date_buf[1] >= 1 && date_buf[1] <= 12) { + memcpy(outline+41, months[date_buf[1]-1], 3); + } + + sprintf(outline+45, "%2d", date_buf[2]); + outline[63] = 0; + sprintf(outline+48, "%4d", date_buf[0]+1900); + + sprintf(outline+53, "[%7d", extent); /* XXX up to 20 GB */ + sprintf(outline+61, " %02X]", idr->flags[0]); + + for (i = 0; i < 66; i++) { + if (outline[i] == 0) outline[i] = ' '; + } + outline[66] = 0; + printf("%s %s %s\n", outline, name_buf, xname); +} + +void +extract_file(struct iso_directory_record *idr) +{ + int extent, len, tlen; + unsigned char buff[2048]; + +#if defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__EMX__) || defined(__DJGPP__) + setmode(fileno(stdout), O_BINARY); +#endif + + extent = isonum_733((unsigned char *)idr->extent); + len = isonum_733((unsigned char *)idr->size); + + while (len > 0) { +#ifdef USE_SCG + readsecs(extent - sector_offset, buff, ISO_BLOCKS(sizeof (buff))); + tlen = (len > sizeof (buff) ? sizeof (buff) : len); +#else + lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET); + tlen = (len > sizeof (buff) ? sizeof (buff) : len); + read(fileno(infile), buff, tlen); +#endif + len -= tlen; + extent++; + write(STDOUT_FILENO, buff, tlen); /* FIXME: check return value */ + } +} + +void +parse_dir(char *rootname, int extent, int len) +{ + char testname[PATH_MAX+1]; + struct todo *td; + int i; + struct iso_directory_record * idr; + unsigned char uh, ul, uc, *up; + + + if (do_listing) + printf("\nDirectory listing of %s\n", rootname); + + while (len > 0) { +#ifdef USE_SCG + readsecs(extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer))); +#else + lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET); + read(fileno(infile), buffer, sizeof (buffer)); +#endif + len -= sizeof (buffer); + extent++; + i = 0; + while (1 == 1) { + idr = (struct iso_directory_record *) &buffer[i]; + if (idr->length[0] == 0) break; + memset(&fstat_buf, 0, sizeof (fstat_buf)); + found_rr = 0; + name_buf[0] = xname[0] = 0; + fstat_buf.st_size = (off_t)(unsigned)isonum_733((unsigned char *)idr->size); + if (idr->flags[0] & 2) + fstat_buf.st_mode |= S_IFDIR; + else + fstat_buf.st_mode |= S_IFREG; + if (idr->name_len[0] == 1 && idr->name[0] == 0) + strcpy(name_buf, "."); + else if (idr->name_len[0] == 1 && idr->name[0] == 1) + strcpy(name_buf, ".."); + else { + switch (ucs_level) { + case 3: + case 2: + case 1: + /* + * Unicode name. Convert as best we can. + */ + { + int j; + + name_buf[0] = '\0'; + for (j = 0; j < (int)idr->name_len[0] / 2; j++) { + uh = idr->name[j*2]; + ul = idr->name[j*2+1]; + + up = unls->unls_uni2cs[uh]; + + if (up == NULL) + uc = '\0'; + else + uc = up[ul]; + + name_buf[j] = uc ? uc : '_'; + } + name_buf[idr->name_len[0]/2] = '\0'; + } + break; + case 0: + /* + * Normal non-Unicode name. + */ + strncpy(name_buf, idr->name, idr->name_len[0]); + name_buf[idr->name_len[0]] = 0; + break; + default: + /* + * Don't know how to do these yet. Maybe they are the same + * as one of the above. + */ + exit(1); + } + } + memcpy(date_buf, idr->date, 9); + if (use_rock) + dump_rr(idr); + if ((idr->flags[0] & 2) != 0 && + (idr->name_len[0] != 1 || + (idr->name[0] != 0 && idr->name[0] != 1))) { + /* + * Add this directory to the todo list. + */ + td = todo_idr; + if (td != NULL) { + while (td->next != NULL) + td = td->next; + td->next = (struct todo *) malloc(sizeof (*td)); + td = td->next; + } else { + todo_idr = td = (struct todo *) malloc(sizeof (*td)); + } + td->next = NULL; + td->extent = isonum_733((unsigned char *)idr->extent); + td->length = isonum_733((unsigned char *)idr->size); + td->name = (char *) malloc(strlen(rootname) + + strlen(name_buf) + 2); + strcpy(td->name, rootname); + strcat(td->name, name_buf); + strcat(td->name, "/"); + } else { + strcpy(testname, rootname); + strcat(testname, name_buf); + if (xtract && strcmp(xtract, testname) == 0) { + extract_file(idr); + } + } + if (do_find && + (idr->name_len[0] != 1 || + (idr->name[0] != 0 && idr->name[0] != 1))) { + strcpy(testname, rootname); + strcat(testname, name_buf); + printf("%s\n", testname); + } + if (do_listing) + dump_stat(idr, isonum_733((unsigned char *)idr->extent)); + i += buffer[i]; + if (i > 2048 - offsetof(struct iso_directory_record, name[0])) break; + } + } +} + +void +usage(int excode) +{ + errmsgno(EX_BAD, "Usage: %s [options] -i filename\n", get_progname()); + + fprintf(stderr, "Options:\n"); + fprintf(stderr, "\t-help,-h Print this help\n"); + fprintf(stderr, "\t-version Print version info and exit\n"); + fprintf(stderr, "\t-debug Print additional debug info\n"); + fprintf(stderr, "\t-d Print information from the primary volume descriptor\n"); + fprintf(stderr, "\t-f Generate output similar to 'find . -print'\n"); + fprintf(stderr, "\t-J Print information from Joliet extensions\n"); + fprintf(stderr, "\t-j charset Use charset to display Joliet file names\n"); + fprintf(stderr, "\t-l Generate output similar to 'ls -lR'\n"); + fprintf(stderr, "\t-p Print Path Table\n"); + fprintf(stderr, "\t-R Print information from Rock Ridge extensions\n"); + fprintf(stderr, "\t-s Print file size infos in multiples of sector size (%ld bytes).\n", (long)PAGE); + fprintf(stderr, "\t-N sector Sector number where ISO image should start on CD\n"); + fprintf(stderr, "\t-T sector Sector number where actual session starts on CD\n"); + fprintf(stderr, "\t-i filename Filename to read ISO-9660 image from\n"); + fprintf(stderr, "\tdev=target SCSI target to use as CD/DVD-Recorder\n"); + fprintf(stderr, "\t-x pathname Extract specified file to stdout\n"); + exit(excode); +} + +int +main(int argc, char *argv[]) +{ + int cac; + char * const *cav; + int c; + char * filename = NULL; + char * devname = NULL; + /* + * Use toc_offset != 0 (-T #) if we have a complete multi-session + * disc that we want/need to play with. + * Here we specify the offset where we want to + * start searching for the TOC. + */ + int toc_offset = 0; + int extent; + struct todo * td; + struct iso_primary_descriptor ipd; + struct iso_primary_descriptor jpd; + struct eltorito_boot_descriptor bpd; + struct iso_directory_record * idr; + char *charset = NULL; + char *opts = "help,h,version,debug,d,p,i*,dev*,J,R,l,x*,f,s,N#l,T#l,j*"; + BOOL help = FALSE; + BOOL prvers = FALSE; + BOOL found_eltorito = FALSE; + int bootcat_offset = 0; + + + save_args(argc, argv); + + cac = argc - 1; + cav = argv + 1; + if (getallargs(&cac, &cav, opts, + &help, &help, &prvers, &debug, + &do_pvd, &do_pathtab, + &filename, &devname, + &use_joliet, &use_rock, + &do_listing, + &xtract, + &do_find, &do_sectors, + §or_offset, &toc_offset, + &charset) < 0) { + errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]); + usage(EX_BAD); + } + if (help) + usage(0); + if (prvers) { + printf("isoinfo %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM); + exit(0); + } + cac = argc - 1; + cav = argv + 1; + if (getfiles(&cac, &cav, opts) != 0) { + errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]); + usage(EX_BAD); + } + + init_unls(); /* Initialize UNICODE tables */ + init_unls_file(charset); + if (charset == NULL) { +#if (defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__DJGPP__)) && !defined(IS_CYGWIN_1) + unls = load_unls("cp437"); +#else + unls = load_unls("iso8859-1"); +#endif + } else { + if (strcmp(charset, "default") == 0) + unls = load_unls_default(); + else + unls = load_unls(charset); + } + if (unls == NULL) { /* Unknown charset specified */ + fprintf(stderr, "Unknown charset: %s\nKnown charsets are:\n", + charset); + list_unls(); /* List all known charset names */ + exit(1); + } + + if (filename != NULL && devname != NULL) { + errmsgno(EX_BAD, "Only one of -i or dev= allowed\n"); + usage(EX_BAD); + } +#ifdef USE_SCG + if (filename == NULL && devname == NULL) + cdr_defaults(&devname, NULL, NULL, NULL); +#endif + if (filename == NULL && devname == NULL) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "ISO-9660 image not specified\n"); +#else + fprintf(stderr, "ISO-9660 image not specified\n"); +#endif + usage(EX_BAD); + } + + if (filename != NULL) + infile = fopen(filename, "rb"); + else + filename = devname; + + if (infile != NULL) { + /* EMPTY */; +#ifdef USE_SCG + } else if (scsidev_open(filename) < 0) { +#else + } else { +#endif +#ifdef USE_LIBSCHILY + comerr("Unable to open %s\n", filename); +#else + fprintf(stderr, "Unable to open %s\n", filename); + exit(1); +#endif + } + + /* + * Absolute sector offset, so don't subtract sector_offset here. + */ +#ifdef USE_SCG + readsecs(16 + toc_offset, &ipd, ISO_BLOCKS(sizeof (ipd))); +#else + lseek(fileno(infile), ((off_t)(16 + toc_offset)) <<11, SEEK_SET); + read(fileno(infile), &ipd, sizeof (ipd)); +#endif + idr = (struct iso_directory_record *)ipd.root_directory_record; + if (do_pvd) { + /* + * High sierra: + * + * DESC TYPE == 1 (VD_SFS) offset 8 len 1 + * STR ID == "CDROM" offset 9 len 5 + * STD_VER == 1 offset 14 len 1 + */ + if ((((char *)&ipd)[8] == 1) && + (strncmp(&((char *)&ipd)[9], "CDROM", 5) == 0) && + (((char *)&ipd)[14] == 1)) { + printf("CD-ROM is in High Sierra format\n"); + exit(0); + } + /* + * ISO 9660: + * + * DESC TYPE == 1 (VD_PVD) offset 0 len 1 + * STR ID == "CD001" offset 1 len 5 + * STD_VER == 1 offset 6 len 1 + */ + if ((ipd.type[0] != ISO_VD_PRIMARY) || + (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) || + (ipd.version[0] != 1)) { + printf("CD-ROM is NOT in ISO 9660 format\n"); + exit(1); + } + + printf("CD-ROM is in ISO 9660 format\n"); + printf("System id: "); + printchars(ipd.system_id, 32); + putchar('\n'); + printf("Volume id: "); + printchars(ipd.volume_id, 32); + putchar('\n'); + + printf("Volume set id: "); + printchars(ipd.volume_set_id, 128); + putchar('\n'); + printf("Publisher id: "); + printchars(ipd.publisher_id, 128); + putchar('\n'); + printf("Data preparer id: "); + printchars(ipd.preparer_id, 128); + putchar('\n'); + printf("Application id: "); + printchars(ipd.application_id, 128); + putchar('\n'); + + printf("Copyright File id: "); + printchars(ipd.copyright_file_id, 37); + putchar('\n'); + printf("Abstract File id: "); + printchars(ipd.abstract_file_id, 37); + putchar('\n'); + printf("Bibliographic File id: "); + printchars(ipd.bibliographic_file_id, 37); + putchar('\n'); + + printf("Volume set size is: %d\n", isonum_723(ipd.volume_set_size)); + printf("Volume set sequence number is: %d\n", isonum_723(ipd.volume_sequence_number)); + printf("Logical block size is: %d\n", isonum_723(ipd.logical_block_size)); + printf("Volume size is: %d\n", isonum_733((unsigned char *)ipd.volume_space_size)); + if (debug) { + int dextent; + int dlen; + + dextent = isonum_733((unsigned char *)idr->extent); + dlen = isonum_733((unsigned char *)idr->size); + printf("Root directory extent: %d size: %d\n", + dextent, dlen); + printf("Path table size is: %d\n", + isonum_733((unsigned char *)ipd.path_table_size)); + printf("L Path table start: %d\n", + isonum_731(ipd.type_l_path_table)); + printf("L Path opt table start: %d\n", + isonum_731(ipd.opt_type_l_path_table)); + printf("M Path table start: %d\n", + isonum_732(ipd.type_m_path_table)); + printf("M Path opt table start: %d\n", + isonum_732(ipd.opt_type_m_path_table)); + printf("Creation Date: %s\n", + sdate(ipd.creation_date)); + printf("Modification Date: %s\n", + sdate(ipd.modification_date)); + printf("Expiration Date: %s\n", + sdate(ipd.expiration_date)); + printf("Effective Date: %s\n", + sdate(ipd.effective_date)); + printf("File structure version: %d\n", + ipd.file_structure_version[0]); + } + { + int block = 16; + movebytes(&ipd, &jpd, sizeof (ipd)); + while ((Uchar)jpd.type[0] != ISO_VD_END) { + + if (debug && (Uchar) jpd.type[0] == ISO_VD_SUPPLEMENTARY) + fprintf(stderr, "Joliet escape sequence 0: '%c' 1: '%c' 2: '%c' 3: '%c'\n", + jpd.escape_sequences[0], + jpd.escape_sequences[1], + jpd.escape_sequences[2], + jpd.escape_sequences[3]); + /* + * If Joliet UCS escape sequence found, we may be wrong + */ + if (jpd.escape_sequences[0] == '%' && + jpd.escape_sequences[1] == '/' && + (jpd.escape_sequences[3] == '\0' || + jpd.escape_sequences[3] == ' ') && + (jpd.escape_sequences[2] == '@' || + jpd.escape_sequences[2] == 'C' || + jpd.escape_sequences[2] == 'E')) { + + if (jpd.version[0] == 1) + goto nextblock; + } + if (jpd.type[0] == 0) { + movebytes(&jpd, &bpd, sizeof (bpd)); + if (strncmp(bpd.system_id, EL_TORITO_ID, sizeof (EL_TORITO_ID)) == 0) { + bootcat_offset = (Uchar)bpd.bootcat_ptr[0] + + (Uchar)bpd.bootcat_ptr[1] * 256 + + (Uchar)bpd.bootcat_ptr[2] * 65536 + + (Uchar)bpd.bootcat_ptr[3] * 16777216; + found_eltorito = TRUE; + printf("El Torito VD version %d found, boot catalog is in sector %d\n", + bpd.version[0], + bootcat_offset); + } + } + if (jpd.version[0] == 2) { + printf("CD-ROM uses ISO 9660:1999 relaxed format\n"); + break; + } + + nextblock: + block++; +#ifdef USE_SCG + readsecs(block + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd))); +#else + lseek(fileno(infile), ((off_t)(block + toc_offset)) <<11, SEEK_SET); + read(fileno(infile), &jpd, sizeof (jpd)); +#endif + } + } + } + /* + * ISO 9660: + * + * DESC TYPE == 1 (VD_PVD) offset 0 len 1 + * STR ID == "CD001" offset 1 len 5 + * STD_VER == 1 offset 6 len 1 + */ + if ((ipd.type[0] != ISO_VD_PRIMARY) || + (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) || + (ipd.version[0] != 1)) { + printf("CD-ROM is NOT in ISO 9660 format\n"); + exit(1); + } + + if (use_joliet || do_pvd) { + int block = 16; + movebytes(&ipd, &jpd, sizeof (ipd)); + while ((unsigned char) jpd.type[0] != ISO_VD_END) { + if (debug && (unsigned char) jpd.type[0] == ISO_VD_SUPPLEMENTARY) + fprintf(stderr, "Joliet escape sequence 0: '%c' 1: '%c' 2: '%c' 3: '%c'\n", + jpd.escape_sequences[0], + jpd.escape_sequences[1], + jpd.escape_sequences[2], + jpd.escape_sequences[3]); + /* + * Find the UCS escape sequence. + */ + if (jpd.escape_sequences[0] == '%' && + jpd.escape_sequences[1] == '/' && + (jpd.escape_sequences[3] == '\0' || + jpd.escape_sequences[3] == ' ') && + (jpd.escape_sequences[2] == '@' || + jpd.escape_sequences[2] == 'C' || + jpd.escape_sequences[2] == 'E')) { + break; + } + + block++; +#ifdef USE_SCG + readsecs(block + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd))); +#else + lseek(fileno(infile), + ((off_t)(block + toc_offset)) <<11, SEEK_SET); + read(fileno(infile), &jpd, sizeof (jpd)); +#endif + } + + if (use_joliet && ((unsigned char) jpd.type[0] == ISO_VD_END)) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Unable to find Joliet SVD\n"); +#else + fprintf(stderr, "Unable to find Joliet SVD\n"); + exit(1); +#endif + } + + switch (jpd.escape_sequences[2]) { + case '@': + ucs_level = 1; + break; + case 'C': + ucs_level = 2; + break; + case 'E': + ucs_level = 3; + break; + } + + if (ucs_level > 3) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Don't know what ucs_level == %d means\n", + ucs_level); +#else + fprintf(stderr, + "Don't know what ucs_level == %d means\n", + ucs_level); + exit(1); +#endif + } + if (jpd.escape_sequences[3] == ' ') + errmsgno(EX_BAD, + "Warning: Joliet escape sequence uses illegal space at offset 3\n"); + } + + if (do_pvd) { + if (ucs_level > 0) + printf("Joliet with UCS level %d found\n", ucs_level); + else + printf("NO Joliet present\n"); + + extent = isonum_733((unsigned char *)idr->extent); + +#ifdef USE_SCG + readsecs(extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer))); +#else + lseek(fileno(infile), + ((off_t)(extent - sector_offset)) <<11, SEEK_SET); + read(fileno(infile), buffer, sizeof (buffer)); +#endif + idr = (struct iso_directory_record *) buffer; + if ((c = dump_rr(idr)) != 0) { +/* printf("RR %X %d\n", c, c);*/ + if (c & 1024) { + printf( + "Rock Ridge signatures version %d found\n", + su_version); + } else { + printf( + "Bad Rock Ridge signatures found (SU record missing)\n"); + } + /* + * This is currently a no op! + * We need to check the first plain file instead of + * the '.' entry in the root directory. + */ + if (c & 2048) { + printf("Apple signatures version %d found\n", + aa_version); + } + } else { + printf("NO Rock Ridge present\n"); + } + if (found_eltorito) + printf_bootinfo(infile, bootcat_offset); + exit(0); + } + + if (use_joliet) + idr = (struct iso_directory_record *)jpd.root_directory_record; + + if (do_pathtab) { + if (use_joliet) { + dump_pathtab(isonum_731(jpd.type_l_path_table), + isonum_733((unsigned char *)jpd.path_table_size)); + } else { + dump_pathtab(isonum_731(ipd.type_l_path_table), + isonum_733((unsigned char *)ipd.path_table_size)); + } + } + + parse_dir("/", isonum_733((unsigned char *)idr->extent), + isonum_733((unsigned char *)idr->size)); + td = todo_idr; + while (td) { + parse_dir(td->name, td->extent, td->length); + td = td->next; + } + + if (infile != NULL) + fclose(infile); + return (0); +} + +#include <intcvt.h> + +static void +printf_bootinfo(FILE *f, int bootcat_offset) +{ + struct eltorito_validation_entry *evp; + struct eltorito_defaultboot_entry *ebe; + +#ifdef USE_SCG + readsecs(bootcat_offset, buffer, ISO_BLOCKS(sizeof (buffer))); +#else + lseek(fileno(f), ((off_t)bootcat_offset) <<11, SEEK_SET); + read(fileno(f), buffer, sizeof (buffer)); +#endif + + evp = (struct eltorito_validation_entry *)buffer; + ebe = (struct eltorito_defaultboot_entry *)&buffer[32]; + + printf("Eltorito validation header:\n"); + printf(" Hid %d\n", (Uchar)evp->headerid[0]); + printf(" Arch %d (%s)\n", (Uchar)evp->arch[0], arch_name((Uchar)evp->arch[0])); + printf(" ID '%.23s'\n", evp->id); + printf(" Key %X %X\n", (Uchar)evp->key1[0], (Uchar)evp->key2[0]); + + printf(" Eltorito defaultboot header:\n"); + printf(" Bootid %X (%s)\n", (Uchar)ebe->boot_id[0], boot_name((Uchar)ebe->boot_id[0])); + printf(" Boot media %X (%s)\n", (Uchar)ebe->boot_media[0], bootmedia_name((Uchar)ebe->boot_media[0])); + printf(" Load segment %X\n", la_to_2_byte(ebe->loadseg)); + printf(" Sys type %X\n", (Uchar)ebe->sys_type[0]); + printf(" Nsect %X\n", la_to_2_byte(ebe->nsect)); + printf(" Bootoff %lX %ld\n", la_to_4_byte(ebe->bootoff), la_to_4_byte(ebe->bootoff)); + +} + +static char * +arch_name(int val) +{ + switch (val) { + + case EL_TORITO_ARCH_x86: + return ("x86"); + case EL_TORITO_ARCH_PPC: + return ("PPC"); + case EL_TORITO_ARCH_MAC: + return ("MAC"); + default: + return ("Unknown Arch"); + } +} + +static char * +boot_name(int val) +{ + switch (val) { + + case EL_TORITO_BOOTABLE: + return ("bootable"); + case EL_TORITO_NOT_BOOTABLE: + return ("not bootable"); + default: + return ("Illegal"); + } +} + +static char * +bootmedia_name(int val) +{ + switch (val) { + + case EL_TORITO_MEDIA_NOEMUL: + return ("No Emulation Boot"); + case EL_TORITO_MEDIA_12FLOP: + return ("1200 Floppy"); + case EL_TORITO_MEDIA_144FLOP: + return ("1.44MB Floppy"); + case EL_TORITO_MEDIA_288FLOP: + return ("2.88MB Floppy"); + case EL_TORITO_MEDIA_HD: + return ("Hard Disk Emulation"); + default: + return ("Illegal Bootmedia"); + } +} diff --git a/genisoimage/diag/isovfy.1 b/genisoimage/diag/isovfy.1 new file mode 100644 index 0000000..b170c59 --- /dev/null +++ b/genisoimage/diag/isovfy.1 @@ -0,0 +1,2 @@ +.so man1/isoinfo.1 +.\" %Z%%M% %I% %E% joerg diff --git a/genisoimage/diag/isovfy.c b/genisoimage/diag/isovfy.c new file mode 100644 index 0000000..18ed340 --- /dev/null +++ b/genisoimage/diag/isovfy.c @@ -0,0 +1,794 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)isovfy.c 1.26 05/05/15 joerg */ +/* + * File isovfy.c - verify consistency of iso9660 filesystem. + * + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * Copyright (c) 1999-2004 J. Schilling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <mconfig.h> +#include <stdxlib.h> +#include <unixstd.h> +#include <strdefs.h> +#include <utypes.h> + +#include <stdio.h> +#include <standard.h> +#include <signal.h> +#include <schily.h> + +#include "../scsi.h" +#include "../../wodim/defaults.h" + +/* + * XXX JS: Some structures have odd lengths! + * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length. + * For this reason, we cannot use sizeof (struct iso_path_table) or + * sizeof (struct iso_directory_record) to compute on disk sizes. + * Instead, we use offsetof(..., name) and add the name size. + * See iso9660.h + */ +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +/* + * Note: always use these macros to avoid problems. + * + * ISO_ROUND_UP(X) may cause an integer overflow and thus give + * incorrect results. So avoid it if possible. + * + * ISO_BLOCKS(X) is overflow safe. Prefer this when ever it is possible. + */ +#define SECTOR_SIZE (2048) +#define ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1)) +#define ISO_BLOCKS(X) (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0)) + +#define infile in_image +FILE *infile = NULL; +int blocksize; + +#define PAGE sizeof (buffer) + +#define ISODCL(from, to) (to - from + 1) + +struct iso_primary_descriptor { + unsigned char type [ISODCL(1, 1)]; /* 711 */ + unsigned char id [ISODCL(2, 6)]; + unsigned char version [ISODCL(7, 7)]; /* 711 */ + unsigned char unused1 [ISODCL(8, 8)]; + unsigned char system_id [ISODCL(9, 40)]; /* aunsigned chars */ + unsigned char volume_id [ISODCL(41, 72)]; /* dunsigned chars */ + unsigned char unused2 [ISODCL(73, 80)]; + unsigned char volume_space_size [ISODCL(81, 88)]; /* 733 */ + unsigned char unused3 [ISODCL(89, 120)]; + unsigned char volume_set_size [ISODCL(121, 124)]; /* 723 */ + unsigned char volume_sequence_number [ISODCL(125, 128)]; /* 723 */ + unsigned char logical_block_size [ISODCL(129, 132)]; /* 723 */ + unsigned char path_table_size [ISODCL(133, 140)]; /* 733 */ + unsigned char type_l_path_table [ISODCL(141, 144)]; /* 731 */ + unsigned char opt_type_l_path_table [ISODCL(145, 148)]; /* 731 */ + unsigned char type_m_path_table [ISODCL(149, 152)]; /* 732 */ + unsigned char opt_type_m_path_table [ISODCL(153, 156)]; /* 732 */ + unsigned char root_directory_record [ISODCL(157, 190)]; /* 9.1 */ + unsigned char volume_set_id [ISODCL(191, 318)]; /* dunsigned chars */ + unsigned char publisher_id [ISODCL(319, 446)]; /* achars */ + unsigned char preparer_id [ISODCL(447, 574)]; /* achars */ + unsigned char application_id [ISODCL(575, 702)]; /* achars */ + unsigned char copyright_file_id [ISODCL(703, 739)]; /* 7.5 dchars */ + unsigned char abstract_file_id [ISODCL(740, 776)]; /* 7.5 dchars */ + unsigned char bibliographic_file_id [ISODCL(777, 813)]; /* 7.5 dchars */ + unsigned char creation_date [ISODCL(814, 830)]; /* 8.4.26.1 */ + unsigned char modification_date [ISODCL(831, 847)]; /* 8.4.26.1 */ + unsigned char expiration_date [ISODCL(848, 864)]; /* 8.4.26.1 */ + unsigned char effective_date [ISODCL(865, 881)]; /* 8.4.26.1 */ + unsigned char file_structure_version [ISODCL(882, 882)]; /* 711 */ + unsigned char unused4 [ISODCL(883, 883)]; + unsigned char application_data [ISODCL(884, 1395)]; + unsigned char unused5 [ISODCL(1396, 2048)]; +}; + +struct iso_directory_record { + unsigned char length [ISODCL(1, 1)]; /* 711 */ + unsigned char ext_attr_length [ISODCL(2, 2)]; /* 711 */ + unsigned char extent [ISODCL(3, 10)]; /* 733 */ + unsigned char size [ISODCL(11, 18)]; /* 733 */ + unsigned char date [ISODCL(19, 25)]; /* 7 by 711 */ + unsigned char flags [ISODCL(26, 26)]; + unsigned char file_unit_size [ISODCL(27, 27)]; /* 711 */ + unsigned char interleave [ISODCL(28, 28)]; /* 711 */ + unsigned char volume_sequence_number [ISODCL(29, 32)]; /* 723 */ + unsigned char name_len [ISODCL(33, 33)]; /* 711 */ + unsigned char name [38]; +}; + +static int isonum_721(char * p); +static int isonum_723(char * p); +static int isonum_711(char * p); +static int isonum_731(char * p); +static int isonum_722(char * p); +static int isonum_732(char * p); +static int isonum_733(unsigned char * p); +static int parse_rr(unsigned char * pnt, int len, int cont_flag); +static int dump_rr(struct iso_directory_record * idr); +static void check_tree(off_t file_addr, int file_size, off_t parent_addr); +static void check_path_tables(int typel_extent, int typem_extent, + int path_table_size); +static void usage(int excode); + +static int +isonum_721(char *p) +{ + return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); +} + +static int +isonum_723(char *p) +{ +#if 0 + if (p[0] != p[3] || p[1] != p[2]) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "invalid format 7.2.3 number\n"); +#else + fprintf(stderr, "invalid format 7.2.3 number\n"); + exit(1); +#endif + } +#endif + return (isonum_721(p)); +} + +static int +isonum_711(char *p) +{ + return (*p & 0xff); +} + +static int +isonum_731(char *p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +static int +isonum_722(char *p) +{ + return ((p[1] & 0xff) + | ((p[0] & 0xff) << 8)); +} + +static int +isonum_732(char *p) +{ + return ((p[3] & 0xff) + | ((p[2] & 0xff) << 8) + | ((p[1] & 0xff) << 16) + | ((p[0] & 0xff) << 24)); +} + +static int +isonum_733(unsigned char *p) +{ + return (isonum_731((char *)p)); +} + +char lbuffer[1024]; +int iline; +int rr_goof; + + +static int +parse_rr(unsigned char *pnt, int len, int cont_flag) +{ + int slen; + int ncount; + int flag1; + int flag2; + int extent; + unsigned char *pnts; + off_t cont_extent; + int cont_offset; + int cont_size; + char symlinkname[1024]; + + sprintf(lbuffer+iline, " RRlen=%d ", len); + iline += strlen(lbuffer+iline); + + cont_extent = (off_t)0; + cont_offset = cont_size = 0; + + symlinkname[0] = 0; + + ncount = 0; + flag1 = flag2 = 0; + while (len >= 4) { + if (ncount) + sprintf(lbuffer+iline, ","); + else + sprintf(lbuffer+iline, "["); + iline += strlen(lbuffer + iline); + sprintf(lbuffer+iline, "%c%c", pnt[0], pnt[1]); + iline += strlen(lbuffer + iline); + if (pnt[0] < 'A' || pnt[0] > 'Z' || pnt[1] < 'A' || + pnt[1] > 'Z') { + sprintf(lbuffer+iline, "**BAD SUSP %d %d]", + pnt[0], pnt[1]); + rr_goof++; + iline += strlen(lbuffer + iline); + return (flag2); + } + + if (pnt[3] != 1 && pnt[3] != 2) { + sprintf(lbuffer+iline, "**BAD RRVERSION (%d)\n", pnt[3]); + rr_goof++; + iline += strlen(lbuffer + iline); + return (flag2); + } + ncount++; + if (pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; + if (strncmp((char *)pnt, "PX", 2) == 0) flag2 |= 1; + if (strncmp((char *)pnt, "PN", 2) == 0) flag2 |= 2; + if (strncmp((char *)pnt, "SL", 2) == 0) flag2 |= 4; + if (strncmp((char *)pnt, "NM", 2) == 0) flag2 |= 8; + if (strncmp((char *)pnt, "CL", 2) == 0) flag2 |= 16; + if (strncmp((char *)pnt, "PL", 2) == 0) flag2 |= 32; + if (strncmp((char *)pnt, "RE", 2) == 0) flag2 |= 64; + if (strncmp((char *)pnt, "TF", 2) == 0) flag2 |= 128; + + if (strncmp((char *)pnt, "CE", 2) == 0) { + cont_extent = (off_t)isonum_733(pnt+4); + cont_offset = isonum_733(pnt+12); + cont_size = isonum_733(pnt+20); + sprintf(lbuffer+iline, "=[%x,%x,%d]", + (int)cont_extent, cont_offset, cont_size); + iline += strlen(lbuffer + iline); + } + + if (strncmp((char *)pnt, "PL", 2) == 0 || strncmp((char *)pnt, "CL", 2) == 0) { + extent = isonum_733(pnt+4); + sprintf(lbuffer+iline, "=%x", extent); + iline += strlen(lbuffer + iline); + if (extent == 0) + rr_goof++; + } + if (strncmp((char *)pnt, "SL", 2) == 0) { + pnts = pnt+5; + slen = pnt[2] - 5; + while (slen >= 1) { + switch (pnts[0] & 0xfe) { + case 0: + strncat(symlinkname, (char *)(pnts+2), pnts[1]); + break; + case 2: + strcat(symlinkname, "."); + break; + case 4: + strcat(symlinkname, ".."); + break; + case 8: + strcat(symlinkname, "/"); + break; + case 16: + strcat(symlinkname, "/mnt"); + sprintf(lbuffer+iline, "Warning - mount point requested"); + iline += strlen(lbuffer + iline); + break; + case 32: + strcat(symlinkname, "kafka"); + sprintf(lbuffer+iline, "Warning - host_name requested"); + iline += strlen(lbuffer + iline); + break; + default: + sprintf(lbuffer+iline, "Reserved bit setting in symlink"); + rr_goof++; + iline += strlen(lbuffer + iline); + break; + } + if ((pnts[0] & 0xfe) && pnts[1] != 0) { + sprintf(lbuffer+iline, "Incorrect length in symlink component"); + iline += strlen(lbuffer + iline); + } + if ((pnts[0] & 1) == 0) + strcat(symlinkname, "/"); + slen -= (pnts[1] + 2); + pnts += (pnts[1] + 2); + } + if (symlinkname[0] != 0) { + sprintf(lbuffer+iline, "=%s", symlinkname); + iline += strlen(lbuffer + iline); + symlinkname[0] = 0; + } + } + + len -= pnt[2]; + pnt += pnt[2]; + if (len <= 3 && cont_extent) { + unsigned char sector[2048]; +#ifdef USE_SCG + readsecs(cont_extent * blocksize / 2048, sector, ISO_BLOCKS(sizeof (sector))); +#else + lseek(fileno(infile), cont_extent * blocksize, SEEK_SET); + read(fileno(infile), sector, sizeof (sector)); +#endif + flag2 |= parse_rr(§or[cont_offset], cont_size, 1); + } + } + if (ncount) { + sprintf(lbuffer+iline, "]"); + iline += strlen(lbuffer + iline); + } + if (!cont_flag && flag1 && flag1 != flag2) { + sprintf(lbuffer+iline, "Flag %x != %x", flag1, flag2); + rr_goof++; + iline += strlen(lbuffer + iline); + } + return (flag2); +} + +static int +dump_rr(struct iso_directory_record *idr) +{ + int len; + char * pnt; + + len = idr->length[0] & 0xff; + len -= offsetof(struct iso_directory_record, name[0]); + len -= idr->name_len[0]; + pnt = (char *) idr; + pnt += offsetof(struct iso_directory_record, name[0]); + pnt += idr->name_len[0]; + + if ((idr->name_len[0] & 1) == 0) { + pnt++; + len--; + } + + rr_goof = 0; + parse_rr((unsigned char *)pnt, len, 0); + return (rr_goof); +} + + +static int dir_count = 0; +static int dir_size_count = 0; +static int ngoof = 0; + +static void +check_tree(off_t file_addr, int file_size, off_t parent_addr) +{ + unsigned char buffer[2048]; + unsigned int k; + int rflag = 0; + int i; + int i1; + int j; + int goof; + int extent; + int size; + off_t orig_file_addr; + off_t parent_file_addr; + struct iso_directory_record *idr; + + i1 = 0; + + orig_file_addr = file_addr / blocksize; /* Actual extent of this directory */ + parent_file_addr = parent_addr / blocksize; + + if ((dir_count % 100) == 0) + printf("[%d %d]\n", dir_count, dir_size_count); +#if 0 + if (sizeof (file_addr) > sizeof (long)) { + printf("Starting directory %ld %d %lld\n", + file_addr, file_size, + (Llong)parent_addr); + } else { + printf("Starting directory %ld %d %ld\n", file_addr, file_size, parent_addr); + } +#endif + + dir_count++; + dir_size_count += file_size / blocksize; + + if (file_size & 0x3ff) + printf("********Directory has unusual size\n"); + + for (k = 0; k < (file_size / sizeof (buffer)); k++) { +#ifdef USE_SCG + readsecs(file_addr / 2048, buffer, ISO_BLOCKS(sizeof (buffer))); +#else + lseek(fileno(infile), file_addr, SEEK_SET); + read(fileno(infile), buffer, sizeof (buffer)); +#endif + i = 0; + while (1 == 1) { + goof = iline = 0; + idr = (struct iso_directory_record *) &buffer[i]; + if (idr->length[0] == 0) break; + sprintf(&lbuffer[iline], "%3d ", idr->length[0]); + iline += strlen(lbuffer + iline); + extent = isonum_733(idr->extent); + size = isonum_733(idr->size); + sprintf(&lbuffer[iline], "%5x ", extent); + iline += strlen(lbuffer + iline); + sprintf(&lbuffer[iline], "%8d ", size); + iline += strlen(lbuffer + iline); + sprintf(&lbuffer[iline], "%c", (idr->flags[0] & 2) ? '*' : ' '); + iline += strlen(lbuffer + iline); + + if (idr->name_len[0] > 33) { + sprintf(&lbuffer[iline], "File name length=(%d)", + idr->name_len[0]); + goof++; + iline += strlen(lbuffer + iline); + } else if (idr->name_len[0] == 1 && idr->name[0] == 0) { + sprintf(&lbuffer[iline], ". "); + iline += strlen(lbuffer + iline); + rflag = 0; + if (orig_file_addr != (off_t)(isonum_733(idr->extent) + isonum_711((char *) idr->ext_attr_length))) { + sprintf(&lbuffer[iline], "***** Directory has null extent."); + goof++; + iline += strlen(lbuffer + iline); + } + if (i1) { + sprintf(&lbuffer[iline], "***** . not first entry."); + rr_goof++; + iline += strlen(lbuffer + iline); + } + } else if (idr->name_len[0] == 1 && idr->name[0] == 1) { + sprintf(&lbuffer[iline], ".. "); + iline += strlen(lbuffer + iline); + rflag = 0; + if (parent_file_addr != (off_t)(isonum_733(idr->extent) + isonum_711((char *) idr->ext_attr_length))) { + sprintf(&lbuffer[iline], "***** Directory has null extent."); + goof++; + iline += strlen(lbuffer + iline); + } + if (i1 != 1) { + sprintf(&lbuffer[iline], "***** .. not second entry."); + rr_goof++; + iline += strlen(lbuffer + iline); + } + } else { + if (i1 < 2) { + sprintf(&lbuffer[iline], " Improper sorting."); + rr_goof++; + } + for (j = 0; j < (int)idr->name_len[0]; j++) { + sprintf(&lbuffer[iline], "%c", idr->name[j]); + } + for (j = 0; j < (14 - (int) idr->name_len[0]); j++) { + sprintf(&lbuffer[iline], " "); + iline += strlen(lbuffer + iline); + } + rflag = 1; + } + + if (size && extent == 0) { + sprintf(&lbuffer[iline], "****Extent==0, size != 0"); + goof++; + iline += strlen(lbuffer + iline); + } +#if 0 + /* This is apparently legal. */ + if (size == 0 && extent) { + sprintf(&lbuffer[iline], "****Extent!=0, size == 0"); + goof++; + iline += strlen(lbuffer + iline); + } +#endif + + if (idr->flags[0] & 0xf5) { + sprintf(&lbuffer[iline], "Flags=(%x) ", idr->flags[0]); + goof++; + iline += strlen(lbuffer + iline); + } + if (idr->interleave[0]) { + sprintf(&lbuffer[iline], "Interleave=(%d) ", idr->interleave[0]); + goof++; + iline += strlen(lbuffer + iline); + } + + if (idr->file_unit_size[0]) { + sprintf(&lbuffer[iline], "File unit size=(%d) ", idr->file_unit_size[0]); + goof++; + iline += strlen(lbuffer + iline); + } + + if (idr->volume_sequence_number[0] != 1) { + sprintf(&lbuffer[iline], "Volume sequence number=(%d) ", idr->volume_sequence_number[0]); + goof++; + iline += strlen(lbuffer + iline); + } + + goof += dump_rr(idr); + sprintf(&lbuffer[iline], "\n"); + iline += strlen(lbuffer + iline); + + + if (goof) { + ngoof++; + lbuffer[iline++] = 0; + if (sizeof (orig_file_addr) > sizeof (long)) { + printf("%llx: %s", (Llong)orig_file_addr, lbuffer); + } else { + printf("%lx: %s", (long)orig_file_addr, lbuffer); + } + } + + + + if (rflag && (idr->flags[0] & 2)) + check_tree((off_t)(isonum_733(idr->extent) + isonum_711((char *)idr->ext_attr_length)) * blocksize, + isonum_733(idr->size), + orig_file_addr * blocksize); + i += buffer[i]; + i1++; + if (i > 2048 - offsetof(struct iso_directory_record, name[0])) + 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; +}; + +static void +check_path_tables(int typel_extent, int typem_extent, int path_table_size) +{ + int count; + int j; + char *pnt; + char *typel; + char *typem; + + /* Now read in the path tables */ + + typel = (char *) malloc(ISO_ROUND_UP(path_table_size)); +#ifdef USE_SCG + readsecs(typel_extent * blocksize / 2048, typel, ISO_BLOCKS(path_table_size)); +#else + lseek(fileno(infile), (off_t)((off_t)typel_extent) * blocksize, SEEK_SET); + read(fileno(infile), typel, path_table_size); /* FIXME: check return value */ +#endif + typem = (char *) malloc(path_table_size); + lseek(fileno(infile), (off_t)((off_t)typem_extent) * blocksize, SEEK_SET); + read(fileno(infile), typem, path_table_size); /* FIXME: check return value */ + + j = path_table_size; + pnt = typel; + count = 1; + while (j) { + int namelen; + int extent; + int idx; + char name[32]; + + namelen = *pnt++; pnt++; + extent = isonum_731(pnt); + pnt += 4; + idx = 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++, idx, extent, name); + } + + j = path_table_size; + pnt = typem; + count = 1; + + while (j) { + int namelen; + int extent; + int idx; + char name[32]; + + namelen = *pnt++; pnt++; + extent = isonum_732(pnt); + pnt += 4; + idx = 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++, idx, extent, name); + } +} + +static void +usage(int excode) +{ + errmsgno(EX_BAD, "Usage: %s [options] image\n", + get_progname()); + + fprintf(stderr, "Options:\n"); + fprintf(stderr, "\t-help, -h Print this help\n"); + fprintf(stderr, "\t-version Print version info and exit\n"); + fprintf(stderr, "\t-i filename Filename to read ISO-9660 image from\n"); + fprintf(stderr, "\tdev=target SCSI target to use as CD/DVD-Recorder\n"); + fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n"); + exit(excode); +} + +int +main(int argc, char *argv[]) +{ + int cac; + char * const *cav; + char *opts = "help,h,version,i*,dev*"; + BOOL help = FALSE; + BOOL prvers = FALSE; + char *filename = NULL; + char *devname = NULL; + off_t file_addr; + int file_size; + struct iso_primary_descriptor ipd; + struct iso_directory_record *idr; + int typel_extent; + int typem_extent; + int path_table_size; + + save_args(argc, argv); + + cac = argc - 1; + cav = argv + 1; + if (getallargs(&cac, &cav, opts, &help, &help, &prvers, + &filename, &devname) < 0) { + errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]); + usage(EX_BAD); + } + if (help) + usage(0); + if (prvers) { + printf("isovfy %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM); + exit(0); + } + cac = argc - 1; + cav = argv + 1; + if (filename == NULL && devname == NULL) { + if (getfiles(&cac, &cav, opts) != 0) { + filename = cav[0]; + cac--, cav++; + } + } + if (getfiles(&cac, &cav, opts) != 0) { + errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]); + usage(EX_BAD); + } + if (filename != NULL && devname != NULL) { + errmsgno(EX_BAD, "Only one of -i or dev= allowed\n"); + usage(EX_BAD); + } +#ifdef USE_SCG + if (filename == NULL && devname == NULL) + cdr_defaults(&devname, NULL, NULL, NULL); +#endif + if (filename == NULL && devname == NULL) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "ISO-9660 image not specified\n"); +#else + fprintf(stderr, "ISO-9660 image not specified\n"); +#endif + usage(EX_BAD); + } + + if (filename != NULL) + infile = fopen(filename, "rb"); + else + filename = devname; + + if (infile != NULL) { + /* EMPTY */; +#ifdef USE_SCG + } else if (scsidev_open(filename) < 0) { +#else + } else { +#endif +#ifdef USE_LIBSCHILY + comerr("Cannot open '%s'\n", filename); +#else + fprintf(stderr, "Cannot open '%s'\n", filename); + exit(1); +#endif + } + + + file_addr = (off_t)32768; +#ifdef USE_SCG + readsecs(file_addr / 2048, &ipd, ISO_BLOCKS(sizeof (ipd))); +#else + lseek(fileno(infile), file_addr, SEEK_SET); + read(fileno(infile), &ipd, sizeof (ipd)); +#endif + + idr = (struct iso_directory_record *)ipd.root_directory_record; + + blocksize = isonum_723((char *)ipd.logical_block_size); + if (blocksize != 512 && blocksize != 1024 && blocksize != 2048) { + blocksize = 2048; + } + + file_addr = (off_t)isonum_733(idr->extent) + isonum_711((char *)idr->ext_attr_length); + file_size = isonum_733(idr->size); + + if (sizeof (file_addr) > sizeof (long)) { + printf("Root at extent %llx, %d bytes\n", (Llong)file_addr, file_size); + } else { + printf("Root at extent %lx, %d bytes\n", (long)file_addr, file_size); + } + file_addr = file_addr * blocksize; + + check_tree(file_addr, file_size, file_addr); + + typel_extent = isonum_731((char *)ipd.type_l_path_table); + typem_extent = isonum_732((char *)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 + + if (infile != NULL) + fclose(infile); + + if (!ngoof) + printf("No errors found\n"); + return (0); +} diff --git a/genisoimage/diskmbr.h b/genisoimage/diskmbr.h new file mode 100644 index 0000000..84501bd --- /dev/null +++ b/genisoimage/diskmbr.h @@ -0,0 +1,65 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)diskmbr.h 1.2 04/03/02 Copyright 1999-2004 J. Schilling */ +/* + * Header file diskmbr.h - assorted structure definitions and macros + * describing standard PC partition table + * + * Copyright (c) 1999-2004 J. Schilling + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _DISKMBR_H +#define _DISKMBR_H + +#define MBR_MAGIC 0xAA55 + +#define PARTITION_UNUSED 0x00 +#define PARTITION_ACTIVE 0x80 + +#define PARTITION_COUNT 4 + +#define MBR_SECTOR(x) ((x)&0x3F) +#define MBR_CYLINDER(x) ((x)>>8|((x)<<2&0x300)) + +struct disk_partition { + unsigned char status; + unsigned char s_head; + unsigned char s_cyl_sec[2]; + unsigned char type; + unsigned char e_head; + unsigned char e_cyl_sec[2]; + unsigned char boot_sec[4]; + unsigned char size[4]; +}; + +struct disk_master_boot_record { + char pad[0x1BE]; + struct disk_partition partition[PARTITION_COUNT]; + unsigned char magic[2]; +}; + +#endif /* _DISKMBR_H */ diff --git a/genisoimage/dvd_file.c b/genisoimage/dvd_file.c new file mode 100644 index 0000000..ffd4ef1 --- /dev/null +++ b/genisoimage/dvd_file.c @@ -0,0 +1,771 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)dvd_file.c 1.3 04/03/04 joerg */ +/* + * DVD_VIDEO code + * Copyright (c) 2002 Olaf Beck - olaf_sc@yahoo.com + * Jörg Schilling <schilling@fokus.gmd.de> + * (making the code portable) + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef DVD_VIDEO + +#include <mconfig.h> +#include "genisoimage.h" +#include <schily.h> +#include "dvd_reader.h" +#include "dvd_file.h" +#include "ifo_read.h" + +static void bsort(int sector[], int title[], int size); +static void uniq(int sector[], int title[], int title_sets_array[], + int sector_sets_array[], int titles); +static void DVDFreeFileSetArrays(int *sector, int *title, + int *title_sets_array, + int *sector_sets_array); +void DVDFreeFileSet(title_set_info_t *title_set_info); +title_set_info_t *DVDGetFileSet(char *dvd); +int DVDGetFilePad(title_set_info_t *title_set_info, char *name); + + +static void +bsort(int sector[], int title[], int size) +{ + int temp_title; + int temp_sector; + int i; + int j; + + /* this is not bubble sort, this is primitive selection sort. Replace with + * bubble sort later, maybe bidirectional, aka Coctail Sort */ + for (i = 0; i < size; i++) { + for (j = 0; j < size; j++) { + if (sector[i] < sector[j]) { + temp_sector = sector[i]; + temp_title = title[i]; + sector[i] = sector[j]; + title[i] = title[j]; + sector[j] = temp_sector; + title[j] = temp_title; + } + } + } +} + + +static void +uniq(int sector[], int title[], int title_sets_array[], + int sector_sets_array[], int titles) +{ + int i; + int j; + + + for (i = 0, j = 0; j < titles; ) { + if (sector[j] != sector[j+1]) { + title_sets_array[i] = title[j]; + sector_sets_array[i] = sector[j]; +#ifdef DEBUG + fprintf(stderr, "Sector offset is %d\n", sector_sets_array[i]); +#endif + i++; + j++; + } else { + do { + if (j < titles) + j++; + + } while (sector[j] == sector[j+1]); + + } + } + +} + +static void +DVDFreeFileSetArrays(int *sector, int *title, int *title_sets_array, + int *sector_sets_array) +{ + free(sector); + free(title); + free(title_sets_array); + free(sector_sets_array); +} + +void +DVDFreeFileSet(title_set_info_t *title_set_info) +{ + free(title_set_info->title_set); + free(title_set_info); +} + +title_set_info_t * +DVDGetFileSet(char *dvd) +{ + /* + * TODO Fix close of files if + * we error out + * We also assume that all + * DVD files are of valid + * size i.e. file%2048 == 0 + */ + + /* title interation */ + int title_sets; + int titles; + int counter; + int i; + + /* DVD file structures */ + dvd_reader_t * _dvd = NULL; + + ifo_handle_t * vmg_ifo = NULL; + ifo_handle_t * vts_ifo = NULL; + + dvd_file_t * vmg_vob_file = NULL; + dvd_file_t * vmg_ifo_file = NULL; + + dvd_file_t * vts_ifo_file = NULL; + dvd_file_t * vts_menu_file = NULL; + dvd_file_t * vts_title_file = NULL; + + /* The sizes it self of each file */ + int ifo; + int bup; + int menu_vob; + int title_vob; + + /* Arrays keeping the title - filset relationship */ + int * sector; + int * title; + int * title_sets_array; + int * sector_sets_array; + + /* DVD Video files */ + struct stat fileinfo; + char temppoint[PATH_MAX + 1]; + + /* The Title Set Info struct*/ + title_set_info_t * title_set_info; + + /* Temporary mount point - to be used later */ + char mountpoint[PATH_MAX + 1]; + + strncpy(mountpoint, dvd, sizeof (mountpoint)); + mountpoint[sizeof (mountpoint)-1] = '\0'; + + + _dvd = DVDOpen(dvd); + if (!_dvd) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Can't open device '%s'\n", dvd); +#else + fprintf(stderr, "Can't open device\n"); +#endif + return (0); + } + vmg_ifo = ifoOpen(_dvd, 0); + if (!vmg_ifo) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Can't open VMG info for '%s'.\n", dvd); +#else + fprintf(stderr, "Can't open VMG info.\n"); +#endif + return (0); + } + + /* Check mount point */ + + snprintf(temppoint, sizeof (temppoint), + "%s/VIDEO_TS/VIDEO_TS.IFO", mountpoint); + + + if (stat(temppoint, &fileinfo) < 0) { + /* If we can't stat the file, give up */ +#ifdef USE_LIBSCHILY + errmsg("Can't stat %s\n", temppoint); +#else + fprintf(stderr, "Can't stat %s\n", temppoint); + perror(""); +#endif + return (0); + } + + + + title_sets = vmg_ifo->vmgi_mat->vmg_nr_of_title_sets; + titles = vmg_ifo->tt_srpt->nr_of_srpts; + + sector = e_malloc(titles * sizeof (int)); + memset(sector, 0, titles * sizeof (int)); + title = e_malloc(titles * sizeof (int)); + title_sets_array = e_malloc(title_sets * sizeof (int)); + sector_sets_array = e_malloc(title_sets * sizeof (int)); + title_set_info = (title_set_info_t *)e_malloc(sizeof (title_set_info_t)); + title_set_info->title_set = (title_set_t *)e_malloc((title_sets + 1) * + sizeof (title_set_t)); + + title_set_info->num_titles = title_sets; + + + /* Fill and sort the arrays for titles*/ + + if (titles >= 1) { + for (counter = 0; counter < titles; counter++) { + sector[counter] = vmg_ifo->tt_srpt->title[counter].title_set_sector; + title[counter] = counter + 1; + } + } + + /* Yes, we should probably do a better sort than B - but what the heck*/ + bsort(sector, title, titles); + + + /* + * Since title sets and titles are not the same we will need to sort + * out "bogus" titles + */ + + uniq(sector, title, title_sets_array, sector_sets_array, titles); + + + /* Open VIDEO_TS.VOB is present */ + + vmg_vob_file = DVDOpenFile(_dvd, 0, DVD_READ_MENU_VOBS); + + /* Check VIDEO_TS title set */ + + vmg_ifo_file = DVDOpenFile(_dvd, 0, DVD_READ_INFO_FILE); + + if ((vmg_vob_file == 0) && vmg_ifo->vmgi_mat->vmg_last_sector + 1 + < 2 * DVDFileSize(vmg_ifo_file)) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "IFO is not of correct size aborting\n"); +#else + fprintf(stderr, "IFO is not of correct size aborting\n"); +#endif + DVDFreeFileSetArrays(sector, title, title_sets_array, + sector_sets_array); + DVDFreeFileSet(title_set_info); + return (0); + } else if ((vmg_vob_file != 0) && (vmg_ifo->vmgi_mat->vmg_last_sector + + 1 < 2 * DVDFileSize(vmg_ifo_file) + + DVDFileSize(vmg_vob_file))) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size"); +#else + fprintf(stderr, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size"); +#endif + DVDFreeFileSetArrays(sector, title, title_sets_array, + sector_sets_array); + DVDFreeFileSet(title_set_info); + return (0); + } + + /* Find the actuall right size of VIDEO_TS.IFO */ + if (vmg_vob_file == 0) { + if (vmg_ifo->vmgi_mat->vmg_last_sector + 1 > 2 + * DVDFileSize(vmg_ifo_file)) { + ifo = vmg_ifo->vmgi_mat->vmg_last_sector + - DVDFileSize(vmg_ifo_file) + 1; + } else { + ifo = vmg_ifo->vmgi_mat->vmgi_last_sector + 1; + } + } else { + if (vmg_ifo->vmgi_mat->vmgi_last_sector + 1 + < vmg_ifo->vmgi_mat->vmgm_vobs) { + ifo = vmg_ifo->vmgi_mat->vmgm_vobs; + } else { + ifo = vmg_ifo->vmgi_mat->vmgi_last_sector + 1; + } + } + + title_set_info->title_set[0].size_ifo = ifo * 2048; + title_set_info->title_set[0].realsize_ifo = fileinfo.st_size; + title_set_info->title_set[0].pad_ifo = ifo - DVDFileSize(vmg_ifo_file); + + /* Find the actuall right size of VIDEO_TS.VOB */ + if (vmg_vob_file != 0) { + if (ifo + DVDFileSize(vmg_ifo_file) + + DVDFileSize(vmg_vob_file) - 1 < + vmg_ifo->vmgi_mat->vmg_last_sector) { + menu_vob = vmg_ifo->vmgi_mat->vmg_last_sector - + ifo - DVDFileSize(vmg_ifo_file) + 1; + } else { + menu_vob = vmg_ifo->vmgi_mat->vmg_last_sector + - ifo - DVDFileSize(vmg_ifo_file) + 1; + } + + snprintf(temppoint, sizeof (temppoint), + "%s/VIDEO_TS/VIDEO_TS.VOB", mountpoint); + if (stat(temppoint, &fileinfo) < 0) { +#ifdef USE_LIBSCHILY + errmsg("calc: Can't stat %s\n", temppoint); +#else + fprintf(stderr, "calc: Can't stat %s\n", temppoint); + perror(""); +#endif + DVDFreeFileSetArrays(sector, title, title_sets_array, + sector_sets_array); + DVDFreeFileSet(title_set_info); + return (0); + } + + title_set_info->title_set[0].realsize_menu = fileinfo.st_size; + title_set_info->title_set[0].pad_menu = menu_vob - + DVDFileSize(vmg_vob_file); + title_set_info->title_set[0].size_menu = menu_vob * 2048; + DVDCloseFile(vmg_vob_file); + } else { + title_set_info->title_set[0].size_menu = 0; + title_set_info->title_set[0].realsize_menu = 0; + title_set_info->title_set[0].pad_menu = 0; + menu_vob = 0; + } + + + /* Finding the actuall right size of VIDEO_TS.BUP */ + if (title_sets >= 1) { + bup = sector_sets_array[0] - menu_vob - ifo; + } else { + /* Just in case we burn a DVD-Video without any title_sets */ + bup = vmg_ifo->vmgi_mat->vmg_last_sector + 1 - menu_vob - ifo; + } + + /* Never trust the BUP file - use a copy of the IFO */ + snprintf(temppoint, sizeof (temppoint), + "%s/VIDEO_TS/VIDEO_TS.IFO", mountpoint); + + if (stat(temppoint, &fileinfo) < 0) { +#ifdef USE_LIBSCHILY + errmsg("calc: Can't stat %s\n", temppoint); +#else + fprintf(stderr, "calc: Can't stat %s\n", temppoint); + perror(""); +#endif + DVDFreeFileSetArrays(sector, title, title_sets_array, + sector_sets_array); + DVDFreeFileSet(title_set_info); + return (0); + } + + title_set_info->title_set[0].realsize_bup = fileinfo.st_size; + title_set_info->title_set[0].size_bup = bup * 2048; + title_set_info->title_set[0].pad_bup = bup - DVDFileSize(vmg_ifo_file); + + /* Take care of the titles which we don't have in VMG */ + + title_set_info->title_set[0].number_of_vob_files = 0; + title_set_info->title_set[0].realsize_vob[0] = 0; + title_set_info->title_set[0].pad_title = 0; + + DVDCloseFile(vmg_ifo_file); + + if (title_sets >= 1) { + for (counter = 0; counter < title_sets; counter++) { + + vts_ifo = ifoOpen(_dvd, counter + 1); + + if (!vts_ifo) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Can't open VTS info.\n"); +#else + fprintf(stderr, "Can't open VTS info.\n"); +#endif + DVDFreeFileSetArrays(sector, title, + title_sets_array, sector_sets_array); + DVDFreeFileSet(title_set_info); + return (0); + } + + snprintf(temppoint, sizeof (temppoint), + "%s/VIDEO_TS/VTS_%02i_0.IFO", + mountpoint, counter + 1); + + if (stat(temppoint, &fileinfo) < 0) { +#ifdef USE_LIBSCHILY + errmsg("calc: Can't stat %s\n", temppoint); +#else + fprintf(stderr, "calc: Can't stat %s\n", + temppoint); + perror(""); +#endif + DVDFreeFileSetArrays(sector, title, + title_sets_array, sector_sets_array); + DVDFreeFileSet(title_set_info); + return (0); + } + + + /* Test if VTS_XX_0.VOB is present */ + + vts_menu_file = DVDOpenFile(_dvd, counter + 1, + DVD_READ_MENU_VOBS); + + /* Test if VTS_XX_X.VOB are present */ + + vts_title_file = DVDOpenFile(_dvd, counter + 1, + DVD_READ_TITLE_VOBS); + + /* Check VIDEO_TS.IFO */ + + vts_ifo_file = DVDOpenFile(_dvd, counter + 1, + DVD_READ_INFO_FILE); + + /* + * Checking that title will fit in the + * space given by the ifo file + */ + + + if (vts_ifo->vtsi_mat->vts_last_sector + 1 + < 2 * DVDFileSize(vts_ifo_file)) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "IFO is not of correct size aborting.\n"); +#else + fprintf(stderr, "IFO is not of correct size aborting\n"); +#endif + DVDFreeFileSetArrays(sector, title, + title_sets_array, sector_sets_array); + DVDFreeFileSet(title_set_info); + return (0); + } else if ((vts_title_file != 0) && + (vts_menu_file != 0) && + (vts_ifo->vtsi_mat->vts_last_sector + 1 + < 2 * DVDFileSize(vts_ifo_file) + + DVDFileSize(vts_title_file) + + DVDFileSize(vts_menu_file))) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size.\n"); +#else + fprintf(stderr, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size"); +#endif + DVDFreeFileSetArrays(sector, title, + title_sets_array, sector_sets_array); + DVDFreeFileSet(title_set_info); + return (0); + } else if ((vts_title_file != 0) && + (vts_menu_file == 0) && + (vts_ifo->vtsi_mat->vts_last_sector + 1 + < 2 * DVDFileSize(vts_ifo_file) + + DVDFileSize(vts_title_file))) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size.\n"); +#else + fprintf(stderr, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size"); +#endif + DVDFreeFileSetArrays(sector, title, + title_sets_array, sector_sets_array); + DVDFreeFileSet(title_set_info); + return (0); + } else if ((vts_menu_file != 0) && + (vts_title_file == 0) && + (vts_ifo->vtsi_mat->vts_last_sector + 1 + < 2 * DVDFileSize(vts_ifo_file) + + DVDFileSize(vts_menu_file))) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size.\n"); +#else + fprintf(stderr, "Either VIDEO_TS.IFO or VIDEO_TS.VOB is not of correct size"); +#endif + DVDFreeFileSetArrays(sector, title, + title_sets_array, sector_sets_array); + DVDFreeFileSet(title_set_info); + return (0); + } + + + /* Find the actuall right size of VTS_XX_0.IFO */ + if ((vts_title_file == 0) && (vts_menu_file == 0)) { + if (vts_ifo->vtsi_mat->vts_last_sector + 1 > + 2 * DVDFileSize(vts_ifo_file)) { + ifo = vts_ifo->vtsi_mat->vts_last_sector + - DVDFileSize(vts_ifo_file) + 1; + } else { + ifo = vts_ifo->vtsi_mat->vts_last_sector + - DVDFileSize(vts_ifo_file) + 1; + } + } else if (vts_title_file == 0) { + if (vts_ifo->vtsi_mat->vtsi_last_sector + 1 < + vts_ifo->vtsi_mat->vtstt_vobs) { + ifo = vmg_ifo->vtsi_mat->vtstt_vobs; + } else { + ifo = vmg_ifo->vtsi_mat->vtstt_vobs; + } + } else { + if (vts_ifo->vtsi_mat->vtsi_last_sector + 1 < + vts_ifo->vtsi_mat->vtsm_vobs) { + ifo = vts_ifo->vtsi_mat->vtsm_vobs; + } else { + ifo = vts_ifo->vtsi_mat->vtsi_last_sector + 1; + } + } + title_set_info->title_set[counter + 1].size_ifo = + ifo * 2048; + title_set_info->title_set[counter + 1].realsize_ifo = + fileinfo.st_size; + title_set_info->title_set[counter + 1].pad_ifo = + ifo - DVDFileSize(vts_ifo_file); + + + /* Find the actuall right size of VTS_XX_0.VOB */ + if (vts_menu_file != 0) { + if (vts_ifo->vtsi_mat->vtsm_vobs == 0) { + /* + * Apparently start sector 0 means that + * VTS_XX_0.VOB is empty after all... + */ + menu_vob = 0; + if (DVDFileSize(vts_menu_file) != 0) { + /* + * Paranoia: we most likely never + * come here... + */ +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "%s/VIDEO_TS/VTS_%02i_0.IFO appears to be corrupted.\n", + mountpoint, counter+1); +#else + fprintf(stderr, + "%s/VIDEO_TS/VTS_%02i_0.IFO appears to be corrupted.\n", + mountpoint, counter+1); +#endif + return (0); + } + } else if ((vts_title_file != 0) && + (vts_ifo->vtsi_mat->vtstt_vobs - + vts_ifo->vtsi_mat->vtsm_vobs > + DVDFileSize(vts_menu_file))) { + menu_vob = vts_ifo->vtsi_mat->vtstt_vobs - + vts_ifo->vtsi_mat->vtsm_vobs; + } else if ((vts_title_file == 0) && + (vts_ifo->vtsi_mat->vtsm_vobs + + DVDFileSize(vts_menu_file) + + DVDFileSize(vts_ifo_file) - 1 < + vts_ifo->vtsi_mat->vts_last_sector)) { + menu_vob = vts_ifo->vtsi_mat->vts_last_sector + - DVDFileSize(vts_ifo_file) + - vts_ifo->vtsi_mat->vtsm_vobs + 1; + } else { + menu_vob = vts_ifo->vtsi_mat->vtstt_vobs - + vts_ifo->vtsi_mat->vtsm_vobs; + } + + snprintf(temppoint, sizeof (temppoint), + "%s/VIDEO_TS/VTS_%02i_0.VOB", mountpoint, counter + 1); + + if (stat(temppoint, &fileinfo) < 0) { +#ifdef USE_LIBSCHILY + errmsg("calc: Can't stat %s\n", temppoint); +#else + fprintf(stderr, "calc: Can't stat %s\n", + temppoint); + perror(""); +#endif + DVDFreeFileSetArrays(sector, title, + title_sets_array, sector_sets_array); + DVDFreeFileSet(title_set_info); + return (0); + } + + title_set_info->title_set[counter + 1].realsize_menu = fileinfo.st_size; + title_set_info->title_set[counter + 1].size_menu = menu_vob * 2048; + title_set_info->title_set[counter + 1].pad_menu = menu_vob - DVDFileSize(vts_menu_file); + + } else { + title_set_info->title_set[counter + 1].size_menu = 0; + title_set_info->title_set[counter + 1].realsize_menu = 0; + title_set_info->title_set[counter + 1].pad_menu = 0; + menu_vob = 0; + } + + + /* Find the actuall total size of VTS_XX_[1 to 9].VOB */ + + if (vts_title_file != 0) { + if (ifo + menu_vob + DVDFileSize(vts_ifo_file) - + 1 < vts_ifo->vtsi_mat->vts_last_sector) { + title_vob = vts_ifo->vtsi_mat->vts_last_sector + + 1 - ifo - menu_vob - + DVDFileSize(vts_ifo_file); + } else { + title_vob = vts_ifo->vtsi_mat->vts_last_sector + + 1 - ifo - menu_vob - + DVDFileSize(vts_ifo_file); + } + /* + * Find out how many vob files + * and the size of them + */ + for (i = 0; i < 9; ++i) { + snprintf(temppoint, sizeof (temppoint), + "%s/VIDEO_TS/VTS_%02i_%i.VOB", + mountpoint, counter + 1, i + 1); + if (stat(temppoint, &fileinfo) < 0) { + break; + } + title_set_info->title_set[counter + 1].realsize_vob[i] = fileinfo.st_size; + } + title_set_info->title_set[counter + 1].number_of_vob_files = i; + title_set_info->title_set[counter + 1].size_title = title_vob * 2048; + title_set_info->title_set[counter + 1].pad_title = title_vob - DVDFileSize(vts_title_file); + } else { + title_set_info->title_set[counter + 1].number_of_vob_files = 0; + title_set_info->title_set[counter + 1].realsize_vob[0] = 0; + title_set_info->title_set[counter + 1].size_title = 0; + title_set_info->title_set[counter + 1].pad_title = 0; + title_vob = 0; + + } + + + /* Find the actuall total size of VTS_XX_0.BUP */ + if (title_sets - 1 > counter) { + bup = sector_sets_array[counter+1] + - sector_sets_array[counter] + - title_vob - menu_vob - ifo; + } else { + bup = vts_ifo->vtsi_mat->vts_last_sector + 1 + - title_vob - menu_vob - ifo; + } + + /* Never trust the BUP use a copy of the IFO */ + snprintf(temppoint, sizeof (temppoint), + "%s/VIDEO_TS/VTS_%02i_0.IFO", + mountpoint, counter + 1); + + if (stat(temppoint, &fileinfo) < 0) { +#ifdef USE_LIBSCHILY + errmsg("calc: Can't stat %s\n", temppoint); +#else + fprintf(stderr, "calc: Can't stat %s\n", + temppoint); + perror(""); +#endif + DVDFreeFileSetArrays(sector, title, + title_sets_array, sector_sets_array); + DVDFreeFileSet(title_set_info); + return (0); + } + + title_set_info->title_set[counter + 1].size_bup = + bup * 2048; + title_set_info->title_set[counter + 1].realsize_bup = + fileinfo.st_size; + title_set_info->title_set[counter + 1].pad_bup = + bup - DVDFileSize(vts_ifo_file); + + + /* Closing files */ + + if (vts_menu_file != 0) { + DVDCloseFile(vts_menu_file); + } + + if (vts_title_file != 0) { + DVDCloseFile(vts_title_file); + } + + + if (vts_ifo_file != 0) { + DVDCloseFile(vts_ifo_file); + } + + ifoClose(vts_ifo); + + } + + } + + DVDFreeFileSetArrays(sector, title, title_sets_array, sector_sets_array); + + /* Close the VMG ifo file we got all the info we need */ + ifoClose(vmg_ifo); + + + /* Close the DVD */ + DVDClose(_dvd); + + /* Return the actuall info*/ + return (title_set_info); + + +} + +int +DVDGetFilePad(title_set_info_t *title_set_info, char *name) +{ + char title_a[3]; + char vob_a[2]; + int title; + int vob; + + title_a[0] = title_a[1] = title_a[2] = '\0'; + vob_a[0] = vob_a[1] = '\0'; + + if (name[0] != 'V') { + return (0); + } + if (memcmp(name, "VIDEO_TS", 8) == 0) { + if (strstr(name, ".IFO") != 0) { + return (title_set_info->title_set[0].pad_ifo); + } else if (strstr(name, ".VOB") != 0) { + return (title_set_info->title_set[0].pad_menu); + } else if (strstr(name, ".BUP") != 0) { + return (title_set_info->title_set[0].pad_bup); + } else { + return (0); + } + } else if (memcmp(name, "VTS_", 4) == 0) { + title_a[0] = name[4]; + title_a[1] = name[5]; + title_a[2] = '\0'; + vob_a[0] = name[7]; + vob_a[1] = '\0'; + title = atoi(title_a); + vob = atoi(vob_a); + if (title > title_set_info->num_titles) { + return (0); + } else { + if (strstr(name, ".IFO") != 0) { + return (title_set_info->title_set[title].pad_ifo); + } else if (strstr(name, ".BUP") != 0) { + return (title_set_info->title_set[title].pad_bup); + } else if (vob == 0) { + return (title_set_info->title_set[title].pad_menu); + } else if (vob == title_set_info->title_set[title].number_of_vob_files) { + return (title_set_info->title_set[title].pad_title); + } else { + return (0); + } + } + } else { + return (0); + } +} + +#endif /*DVD_VIDEO*/ diff --git a/genisoimage/dvd_file.h b/genisoimage/dvd_file.h new file mode 100644 index 0000000..234a1de --- /dev/null +++ b/genisoimage/dvd_file.h @@ -0,0 +1,41 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)dvd_file.h 1.1 02/07/21 Copyright 2002 J. Schilling */ +/* + * Defnitions for users of dvd_file.c + * + * Copyright (c) 2002 J. Schilling + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _DVD_FILE_H +#define _DVD_FILE_H + +extern void DVDFreeFileSet(title_set_info_t *title_set_info); +extern title_set_info_t *DVDGetFileSet(char *dvd); +extern int DVDGetFilePad(title_set_info_t *title_set_info, char *name); + +#endif /* _DVD_FILE_H */ diff --git a/genisoimage/dvd_reader.c b/genisoimage/dvd_reader.c new file mode 100644 index 0000000..1a85abe --- /dev/null +++ b/genisoimage/dvd_reader.c @@ -0,0 +1,295 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)dvd_reader.c 1.3 04/03/04 joerg */ +/* + * Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>, + * Håkan Hjort <d95hjort@dtek.chalmers.se>, + * Olaf Beck <olaf_sc@yahoo.com> + * (I only did the cut down no other contribs) + * Jörg Schilling <schilling@fokus.gmd.de> + * (making the code portable) + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * NOTE: This is a cut down version of libdvdread for genisoimage, due + * to portability issues with the current libdvdread according to + * the maintainer of genisoimage. + * This cut down version only reads from a harddisk file structure + * and it only implements the functions necessary inorder to make + * genisoimage produce valid DVD-Video images. + * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL + * LIBDVDREAD INSTEAD + */ +#ifdef DVD_VIDEO + +#include "genisoimage.h" +#include <fctldefs.h> +#include <schily.h> + +#include "dvd_reader.h" + +struct dvd_file_s { + /* Basic information. */ + dvd_reader_t *dvd; + + /* Calculated at open-time, size in blocks. */ + ssize_t filesize; +}; + + +void DVDCloseFile(dvd_file_t *dvd_file); +static dvd_file_t *DVDOpenFilePath(dvd_reader_t *dvd, char *filename); +static dvd_file_t *DVDOpenVOBPath(dvd_reader_t *dvd, int title, int menu); +dvd_file_t *DVDOpenFile(dvd_reader_t *dvd, int titlenum, + dvd_read_domain_t domain); +static dvd_reader_t *DVDOpenPath(const char *path_root); +dvd_reader_t *DVDOpen(const char *path); +void DVDClose(dvd_reader_t *dvd); +ssize_t DVDFileSize(dvd_file_t *dvd_file); + + +/* + * Free a DVD file + */ +void +DVDCloseFile(dvd_file_t *dvd_file) +{ + free(dvd_file); + dvd_file = 0; +} + + +/* + * Stat a IFO or BUP file from a DVD directory tree. + */ +static dvd_file_t * +DVDOpenFilePath(dvd_reader_t *dvd, char *filename) +{ + + char full_path[PATH_MAX + 1]; + dvd_file_t *dvd_file; + struct stat fileinfo; + + /* Get the full path of the file. */ + + snprintf(full_path, sizeof (full_path), + "%s/%s", dvd->path_root, filename); + + + dvd_file = (dvd_file_t *) e_malloc(sizeof (dvd_file_t)); + if (!dvd_file) + return (0); + dvd_file->dvd = dvd; + dvd_file->filesize = 0; + + if (stat(full_path, &fileinfo) < 0) { + free(dvd_file); + return (0); + } + dvd_file->filesize = fileinfo.st_size / DVD_VIDEO_LB_LEN; + + return (dvd_file); +} + + +/* + * Stat a VOB file from a DVD directory tree. + */ +static dvd_file_t * +DVDOpenVOBPath(dvd_reader_t *dvd, int title, int menu) +{ + + char filename[PATH_MAX + 1]; + struct stat fileinfo; + dvd_file_t *dvd_file; + int i; + + dvd_file = (dvd_file_t *) e_malloc(sizeof (dvd_file_t)); + if (!dvd_file) + return (0); + dvd_file->dvd = dvd; + dvd_file->filesize = 0; + + if (menu) { + if (title == 0) { + snprintf(filename, sizeof (filename), + "%s/VIDEO_TS/VIDEO_TS.VOB", dvd->path_root); + } else { + snprintf(filename, sizeof (filename), + "%s/VIDEO_TS/VTS_%02i_0.VOB", dvd->path_root, title); + } + if (stat(filename, &fileinfo) < 0) { + free(dvd_file); + return (0); + } + dvd_file->filesize = fileinfo.st_size / DVD_VIDEO_LB_LEN; + } else { + for (i = 0; i < 9; ++i) { + + snprintf(filename, sizeof (filename), + "%s/VIDEO_TS/VTS_%02i_%i.VOB", dvd->path_root, title, i + 1); + if (stat(filename, &fileinfo) < 0) { + break; + } + + dvd_file->filesize += fileinfo.st_size / DVD_VIDEO_LB_LEN; + } + } + + return (dvd_file); +} + +/* + * Stat a DVD file from a DVD directory tree + */ +EXPORT dvd_file_t * +DVDOpenFile(dvd_reader_t *dvd, int titlenum, dvd_read_domain_t domain) +{ + char filename[MAX_UDF_FILE_NAME_LEN]; + + switch (domain) { + + case DVD_READ_INFO_FILE: + if (titlenum == 0) { + snprintf(filename, sizeof (filename), + "/VIDEO_TS/VIDEO_TS.IFO"); + } else { + snprintf(filename, sizeof (filename), + "/VIDEO_TS/VTS_%02i_0.IFO", titlenum); + } + break; + + case DVD_READ_INFO_BACKUP_FILE: + if (titlenum == 0) { + snprintf(filename, sizeof (filename), + "/VIDEO_TS/VIDEO_TS.BUP"); + } else { + snprintf(filename, sizeof (filename), + "/VIDEO_TS/VTS_%02i_0.BUP", titlenum); + } + break; + + case DVD_READ_MENU_VOBS: + return (DVDOpenVOBPath(dvd, titlenum, 1)); + + case DVD_READ_TITLE_VOBS: + if (titlenum == 0) + return (0); + return (DVDOpenVOBPath(dvd, titlenum, 0)); + + default: +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Invalid domain for file open.\n"); +#else + fprintf(stderr, "Invalid domain for file open.\n"); +#endif + return (0); + } + return (DVDOpenFilePath(dvd, filename)); +} + + + +/* + * Stat a DVD directory structure + */ +static dvd_reader_t * +DVDOpenPath(const char *path_root) +{ + dvd_reader_t *dvd; + + dvd = (dvd_reader_t *) e_malloc(sizeof (dvd_reader_t)); + if (!dvd) + return (0); + dvd->path_root = strdup(path_root); + + return (dvd); +} + + +/* + * Stat a DVD structure - this one only works with directory structures + */ +dvd_reader_t * +DVDOpen(const char *path) +{ + struct stat fileinfo; + int ret; + + if (!path) + return (0); + + ret = stat(path, &fileinfo); + if (ret < 0) { + /* If we can't stat the file, give up */ +#ifdef USE_LIBSCHILY + errmsg("Can't stat %s\n", path); +#else + fprintf(stderr, "Can't stat %s\n", path); + perror(""); +#endif + return (0); + } + + + if (S_ISDIR(fileinfo.st_mode)) { + return (DVDOpenPath(path)); + } + + /* If it's none of the above, screw it. */ +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Could not open %s\n", path); +#else + fprintf(stderr, "Could not open %s\n", path); +#endif + return (0); +} + +/* + * Free a DVD structure - this one will only close a directory tree + */ +void +DVDClose(dvd_reader_t *dvd) +{ + if (dvd) { + if (dvd->path_root) free(dvd->path_root); + free(dvd); + dvd = 0; + } +} + + + +/* + * Return the size of a DVD file + */ +ssize_t +DVDFileSize(dvd_file_t *dvd_file) +{ + return (dvd_file->filesize); +} + +#endif /* DVD_VIDEO */ diff --git a/genisoimage/dvd_reader.h b/genisoimage/dvd_reader.h new file mode 100644 index 0000000..1ec2648 --- /dev/null +++ b/genisoimage/dvd_reader.h @@ -0,0 +1,151 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)dvd_reader.h 1.2 04/03/02 joerg */ + +#ifndef _DVD_READER_H +#define _DVD_READER_H + +/* + * Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>, + * Håkan Hjort <d95hjort@dtek.chalmers.se + * Olaf Beck <olaf_sc@yahoo.com> + * (I only did the cut down no other contribs) + * Jörg Schilling <schilling@fokus.gmd.de> + * (making the code portable) + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * NOTE: This is a cut down version of libdvdread for genisoimage, due + * to portability issues with the current libdvdread according to + * the maintainer of genisoimage. + * This cut down version only reads from a harddisk file structure + * and it only implements the functions necessary inorder to make + * genisoimage produce valid DVD-Video images. + * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL + * LIBDVDREAD INSTEAD + */ + + +#include <unixstd.h> /* Make sure <sys/types.h> is included */ + +/* + * Maximum length of filenames for UDF. + */ +#define MAX_UDF_FILE_NAME_LEN 2048 + +/* + * The length of one Logical Block of a DVD Video. + */ +#define DVD_VIDEO_LB_LEN 2048 + +#ifdef __cplusplus +extern "C" { +#endif + + +struct dvd_reader_s { + /* Information required for a directory path drive. */ + char *path_root; +}; + + +typedef struct dvd_reader_s dvd_reader_t; +typedef struct dvd_file_s dvd_file_t; + + +/* + * dvd = DVDOpen(path); + * Opens a directory name of a DVD-Video structure on HD. + * Returns zero if it fails. + * The path should be like this + * "path/VIDEO_TS/VTS_01_1.VOB" + */ + + +extern dvd_reader_t *DVDOpen(const char *); + + +/* + * DVDClose(dvd); + * + * Closes and cleans up the DVD reader object. You must close all open files + * before calling this function. + */ + + +extern void DVDClose(dvd_reader_t *); + +/* + * INFO_FILE : VIDEO_TS.IFO (manager) + * VTS_XX_0.IFO (title) + * + * INFO_BACKUP_FILE: VIDEO_TS.BUP (manager) + * VTS_XX_0.BUP (title) + * + * MENU_VOBS : VIDEO_TS.VOB (manager) + * VTS_XX_0.VOB (title) + * + * TITLE_VOBS : VTS_XX_[1-9].VOB (title) + * All files in the title set are opened and + * read as a single file. + */ +typedef enum { + DVD_READ_INFO_FILE, + DVD_READ_INFO_BACKUP_FILE, + DVD_READ_MENU_VOBS, + DVD_READ_TITLE_VOBS +} dvd_read_domain_t; + +/* + * dvd_file = DVDOpenFile(dvd, titlenum, domain); + * + * Opens a file on the DVD given the title number and domain. If the title + * number is 0, the video manager information is opened + * (VIDEO_TS.[IFO,BUP,VOB]). Returns a file structure which may be used for + * reads, or 0 if the file was not found. + */ +extern dvd_file_t * DVDOpenFile(dvd_reader_t *, int, dvd_read_domain_t); + +/* + * DVDCloseFile(dvd_file); + * + * Closes a file and frees the associated structure. + */ +extern void DVDCloseFile(dvd_file_t *); + + +/* + * blocks = DVDFileSize(dvd_file); + * + * Returns the file size in blocks. + */ +extern ssize_t DVDFileSize(dvd_file_t *); + + +#ifdef __cplusplus +}; +#endif +#endif /* _DVD_READER_H */ diff --git a/genisoimage/eltorito.c b/genisoimage/eltorito.c new file mode 100644 index 0000000..d52e17e --- /dev/null +++ b/genisoimage/eltorito.c @@ -0,0 +1,716 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)eltorito.c 1.33 05/02/27 joerg */ +/* + * Program eltorito.c - Handle El Torito specific extensions to iso9660. + * + * + * Written by Michael Fulbright <msf@redhat.com> (1996). + * + * Copyright 1996 RedHat Software, Incorporated + * Copyright (c) 1999-2004 J. Schilling + * + * 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 <mconfig.h> +#include "genisoimage.h" +#include <fctldefs.h> +#include <utypes.h> +#include <intcvt.h> +#include "match.h" +#include "diskmbr.h" +#include "bootinfo.h" +#include <schily.h> + +#undef MIN +#define MIN(a, b) (((a) < (b))? (a): (b)) + +static struct eltorito_validation_entry valid_desc; +static struct eltorito_boot_descriptor gboot_desc; +static struct disk_master_boot_record disk_mbr; +static unsigned int bcat_de_flags; + +void init_boot_catalog(const char *path); +void insert_boot_cat(void); +static void get_torito_desc(struct eltorito_boot_descriptor *boot_desc); +static void fill_boot_desc(struct eltorito_defaultboot_entry *boot_desc_entry, + struct eltorito_boot_entry_info *boot_entry); +void get_boot_entry(void); +void new_boot_entry(void); +static int tvd_write(FILE *outfile); + + +static char *bootcat_path; /* filename of boot catalog */ +/* + * Make sure any existing boot catalog is excluded + */ +void +init_boot_catalog(const char *path) +{ +#ifdef SORTING + struct eltorito_boot_entry_info * cbe; + + for (cbe = first_boot_entry; + cbe != NULL; + cbe = cbe->next) { + char *p; + + if (cbe->boot_image == NULL) + comerrno(EX_BAD, "Missing boot image name, use -eltorito-boot option.\n"); + p = (char *) e_malloc(strlen(cbe->boot_image) + strlen(path) + 2); + strcpy(p, path); + if (p[strlen(p) - 1] != '/') { + strcat(p, "/"); + } + strcat(p, cbe->boot_image); + add_sort_match(p, sort_matches(p, 1)); + free(p); + } +#endif + bootcat_path = (char *) e_malloc(strlen(boot_catalog) + strlen(path) + 2); + strcpy(bootcat_path, path); + if (bootcat_path[strlen(bootcat_path) - 1] != '/') { + strcat(bootcat_path, "/"); + } + strcat(bootcat_path, boot_catalog); + + /* + * we are going to create a virtual catalog file + * - so make sure any existing is excluded + */ + add_match(bootcat_path); + + /* flag the file as a memory file */ + bcat_de_flags = MEMORY_FILE; + + /* find out if we want to "hide" this file */ + if (i_matches(boot_catalog) || i_matches(bootcat_path)) + bcat_de_flags |= INHIBIT_ISO9660_ENTRY; + + if (j_matches(boot_catalog) || j_matches(bootcat_path)) + bcat_de_flags |= INHIBIT_JOLIET_ENTRY; + +}/* init_boot_catalog(... */ + +/* + * Create a boot catalog file in memory - genisoimage already uses this type of + * file for the TRANS.TBL files. Therefore the boot catalog is set up in + * similar way + */ +void +insert_boot_cat() +{ + struct directory_entry *de; + struct directory_entry *s_entry; + char *p1; + char *p2; + char *p3; + struct directory *this_dir; + struct directory *dir; + char *buffer; + + init_fstatbuf(); + + buffer = (char *) e_malloc(SECTOR_SIZE); + memset(buffer, 0, SECTOR_SIZE); + + /* + * try to find the directory that will contain the boot.cat file + * - not very neat, but I can't think of a better way + */ + p1 = strdup(boot_catalog); + + /* get dirname (p1) and basename (p2) of boot.cat */ + if ((p2 = strrchr(p1, '/')) != NULL) { + *p2 = '\0'; + p2++; + + /* find the dirname directory entry */ + de = search_tree_file(root, p1); + if (!de) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Uh oh, I cant find the boot catalog directory '%s'!\n", + p1); +#else + fprintf(stderr, + "Uh oh, I cant find the boot catalog directory '%s'!\n", + p1); + exit(1); +#endif + } + this_dir = 0; + + /* get the basename (p3) of the directory */ + if ((p3 = strrchr(p1, '/')) != NULL) + p3++; + else + p3 = p1; + + /* find the correct sub-directory entry */ + for (dir = de->filedir->subdir; dir; dir = dir->next) + if (!(strcmp(dir->de_name, p3))) + this_dir = dir; + + if (this_dir == 0) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Uh oh, I cant find the boot catalog directory '%s'!\n", + p3); +#else + fprintf(stderr, + "Uh oh, I cant find the boot catalog directory '%s'!\n", + p3); + exit(1); +#endif + } + } else { + /* boot.cat is in the root directory */ + this_dir = root; + p2 = p1; + } + + /* + * make a directory entry in memory (using the same set up as for table + * entries + */ + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memset(s_entry, 0, sizeof (struct directory_entry)); + s_entry->next = this_dir->contents; + this_dir->contents = s_entry; + +#ifdef SORTING + /* inherit any sort weight from parent directory */ + s_entry->sort = this_dir->sort; + s_entry->sort += 2; + + /* see if this entry should have a new weighting */ + if (do_sort) { + s_entry->sort = sort_matches(bootcat_path, s_entry->sort); + } +#endif /* SORTING */ + + s_entry->isorec.flags[0] = ISO_FILE; + s_entry->priority = 32768; + iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime); + s_entry->inode = TABLE_INODE; + s_entry->dev = (dev_t) UNCACHED_DEVICE; + set_723(s_entry->isorec.volume_sequence_number, + volume_sequence_number); + set_733((char *) s_entry->isorec.size, SECTOR_SIZE); + s_entry->size = SECTOR_SIZE; + s_entry->filedir = this_dir; + s_entry->name = strdup(p2); + iso9660_file_length(p2, s_entry, 0); + + /* flag file as necessary */ + + /* + * If the current directory is hidden, then hide this entry + */ + if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY) + bcat_de_flags |= INHIBIT_ISO9660_ENTRY; + if (this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) + bcat_de_flags |= INHIBIT_JOLIET_ENTRY; + + s_entry->de_flags = bcat_de_flags; + + if ((use_XA || use_RockRidge) && + !(bcat_de_flags & INHIBIT_ISO9660_ENTRY)) { + fstatbuf.st_mode = 0444 | S_IFREG; + fstatbuf.st_nlink = 1; + generate_xa_rr_attributes("", + p2, s_entry, + &fstatbuf, &fstatbuf, 0); + } + /* + * memory files are stored at s_entry->table + * - but this is also used for each s_entry to generate + * TRANS.TBL entries. So if we are generating tables, + * store the TRANS.TBL data here for the moment + */ + if (generate_tables && !(bcat_de_flags & INHIBIT_ISO9660_ENTRY)) { + sprintf(buffer, "F\t%s\n", s_entry->name); + + /* copy the TRANS.TBL entry info and clear the buffer */ + s_entry->table = strdup(buffer); + memset(buffer, 0, SECTOR_SIZE); + + /* + * store the (empty) file data in the + * unused s_entry->whole_name element for the time being + * - this will be transferred to s_entry->table after any + * TRANS.TBL processing later + */ + s_entry->whole_name = buffer; + } else { + /* store the (empty) file data in the s_entry->table element */ + s_entry->table = buffer; + s_entry->whole_name = NULL; + } +} + +static void +get_torito_desc(struct eltorito_boot_descriptor *boot_desc) +{ + int checksum; + unsigned char *checksum_ptr; + struct directory_entry *de2; /* Boot catalog */ + int i; + int offset; + struct eltorito_defaultboot_entry boot_desc_record; + + memset(boot_desc, 0, sizeof (*boot_desc)); + boot_desc->type[0] = 0; + memcpy(boot_desc->id, ISO_STANDARD_ID, sizeof (ISO_STANDARD_ID)); + boot_desc->version[0] = 1; + + memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof (EL_TORITO_ID)); + + /* + * search from root of iso fs to find boot catalog + * - we already know where the boot catalog is + * - we created it above - but lets search for it anyway + * - good sanity check! + */ + de2 = search_tree_file(root, boot_catalog); + if (!de2 || !(de2->de_flags & MEMORY_FILE)) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Uh oh, I cant find the boot catalog '%s'!\n", + boot_catalog); +#else + fprintf(stderr, "Uh oh, I cant find the boot catalog '%s'!\n", + boot_catalog); + exit(1); +#endif + } + set_731(boot_desc->bootcat_ptr, + (unsigned int) get_733(de2->isorec.extent)); + + /* + * we have the boot image, so write boot catalog information + * Next we write out the primary descriptor for the disc + */ + memset(&valid_desc, 0, sizeof (valid_desc)); + valid_desc.headerid[0] = 1; + valid_desc.arch[0] = EL_TORITO_ARCH_x86; + + /* + * we'll shove start of publisher id into id field, + * may get truncated but who really reads this stuff! + */ + if (publisher) + memcpy_max(valid_desc.id, publisher, + MIN(23, strlen(publisher))); + + valid_desc.key1[0] = (char) 0x55; + valid_desc.key2[0] = (char) 0xAA; + + /* compute the checksum */ + checksum = 0; + checksum_ptr = (unsigned char *) &valid_desc; + /* Set checksum to 0 before computing checksum */ + set_721(valid_desc.cksum, 0); + for (i = 0; i < (int)sizeof (valid_desc); i += 2) { + checksum += (unsigned int) checksum_ptr[i]; + checksum += ((unsigned int) checksum_ptr[i + 1]) * 256; + } + + /* now find out the real checksum */ + checksum = -checksum; + set_721(valid_desc.cksum, (unsigned int) checksum); + + /* now write it to the virtual boot catalog */ + memcpy(de2->table, &valid_desc, 32); + + for (current_boot_entry = first_boot_entry, offset = sizeof (valid_desc); + current_boot_entry != NULL; + current_boot_entry = current_boot_entry->next, + offset += sizeof (boot_desc_record)) { + + if (offset >= SECTOR_SIZE) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Too many El Torito boot entries\n"); +#else + fprintf(stderr, + "Too many El Torito boot entries\n"); + exit(1); +#endif + } + fill_boot_desc(&boot_desc_record, current_boot_entry); + memcpy(de2->table + offset, &boot_desc_record, + sizeof (boot_desc_record)); + } +}/* get_torito_desc(... */ + +static void +fill_boot_desc(struct eltorito_defaultboot_entry *boot_desc_entry, + struct eltorito_boot_entry_info *boot_entry) +{ + struct directory_entry *de; /* Boot file */ + int bootmbr; + int i; + int nsectors; + int geosec; + + if (!boot_desc_entry || !boot_entry) + return; + + /* now adjust boot catalog lets find boot image first */ + de = search_tree_file(root, boot_entry->boot_image); + if (!de) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Uh oh, I cant find the boot image '%s' !\n", + boot_entry->boot_image); +#else + fprintf(stderr, "Uh oh, I cant find the boot image '%s' !\n", + boot_entry->boot_image); + exit(1); +#endif + } + /* now make the initial/default entry for boot catalog */ + memset(boot_desc_entry, 0, sizeof (*boot_desc_entry)); + boot_desc_entry->boot_id[0] = (char) boot_entry->not_bootable ? + EL_TORITO_NOT_BOOTABLE : EL_TORITO_BOOTABLE; + + /* use default BIOS loadpnt */ + set_721(boot_desc_entry->loadseg, boot_entry->load_addr); + + /* + * figure out size of boot image in 512-byte sectors. + * However, round up to the nearest integral CD (2048-byte) sector. + * This is only used for no-emulation booting. + */ + nsectors = boot_entry->load_size ? boot_entry->load_size : + ISO_BLOCKS(de->size) * (SECTOR_SIZE/512); + + if (verbose > 0) { + fprintf(stderr, + "Size of boot image is %d sectors -> ", nsectors); + } + + if (boot_entry->hard_disk_boot) { + /* sanity test hard disk boot image */ + boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_HD; + if (verbose > 0) + fprintf(stderr, "Emulating a hard disk\n"); + + /* read MBR */ + bootmbr = open(de->whole_name, O_RDONLY | O_BINARY); + if (bootmbr == -1) { +#ifdef USE_LIBSCHILY + comerr("Error opening boot image '%s' for read.\n", + de->whole_name); +#else + fprintf(stderr, + "Error opening boot image '%s' for read.\n", + de->whole_name); + perror(""); + exit(1); +#endif + } + if (read(bootmbr, &disk_mbr, sizeof (disk_mbr)) != + sizeof (disk_mbr)) { +#ifdef USE_LIBSCHILY + comerr("Error reading MBR from boot image '%s'.\n", + de->whole_name); +#else + fprintf(stderr, + "Error reading MBR from boot image '%s'.\n", + de->whole_name); + exit(1); +#endif + } + close(bootmbr); + if (la_to_u_2_byte(disk_mbr.magic) != MBR_MAGIC) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Warning: boot image '%s' MBR is not a boot sector.\n", + de->whole_name); +#else + fprintf(stderr, + "Warning: boot image '%s' MBR is not a boot sector.\n", + de->whole_name); +#endif + } + /* find partition type */ + boot_desc_entry->sys_type[0] = PARTITION_UNUSED; + for (i = 0; i < PARTITION_COUNT; ++i) { + int s_cyl_sec; + int e_cyl_sec; + + s_cyl_sec = + la_to_u_2_byte(disk_mbr.partition[i].s_cyl_sec); + e_cyl_sec = + la_to_u_2_byte(disk_mbr.partition[i].e_cyl_sec); + + if (disk_mbr.partition[i].type != PARTITION_UNUSED) { + if (boot_desc_entry->sys_type[0] != + PARTITION_UNUSED) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Boot image '%s' has multiple partitions.\n", + de->whole_name); +#else + fprintf(stderr, + "Boot image '%s' has multiple partitions.\n", + de->whole_name); + exit(1); +#endif + } + boot_desc_entry->sys_type[0] = + disk_mbr.partition[i].type; + + /* a few simple sanity warnings */ + if (!boot_entry->not_bootable && + disk_mbr.partition[i].status != + PARTITION_ACTIVE) { + fprintf(stderr, + "Warning: partition not marked active.\n"); + } + if (MBR_CYLINDER(s_cyl_sec) != 0 || + disk_mbr.partition[i].s_head != 1 || + MBR_SECTOR(s_cyl_sec != 1)) { + fprintf(stderr, + "Warning: partition does not start at 0/1/1.\n"); + } + geosec = (MBR_CYLINDER(e_cyl_sec) + 1) * + (disk_mbr.partition[i].e_head + 1) * + MBR_SECTOR(e_cyl_sec); + if (geosec != nsectors) { + fprintf(stderr, + "Warning: image size does not match geometry (%d)\n", + geosec); + } +#ifdef DEBUG_TORITO + fprintf(stderr, "Partition start %u/%u/%u\n", + MBR_CYLINDER(s_cyl_sec), + disk_mbr.partition[i].s_head, + MBR_SECTOR(s_cyl_sec)); + fprintf(stderr, "Partition end %u/%u/%u\n", + MBR_CYLINDER(e_cyl_sec), + disk_mbr.partition[i].e_head, + MBR_SECTOR(e_cyl_sec)); +#endif + } + } + if (boot_desc_entry->sys_type[0] == PARTITION_UNUSED) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Boot image '%s' has no partitions.\n", + de->whole_name); +#else + fprintf(stderr, + "Boot image '%s' has no partitions.\n", + de->whole_name); + exit(1); +#endif + } +#ifdef DEBUG_TORITO + fprintf(stderr, "Partition type %u\n", + boot_desc_entry->sys_type[0]); +#endif + /* load single boot sector, in this case the MBR */ + nsectors = 1; + + } else if (boot_entry->no_emul_boot) { + /* + * no emulation is a simple image boot of all the sectors + * in the boot image + */ + boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_NOEMUL; + if (verbose > 0) + fprintf(stderr, "No emulation\n"); + + } else { + /* choose size of emulated floppy based on boot image size */ + if (nsectors == 2880) { + boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_144FLOP; + if (verbose > 0) + fprintf(stderr, "Emulating a 1440 kB floppy\n"); + + } else if (nsectors == 5760) { + boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_288FLOP; + if (verbose > 0) + fprintf(stderr, "Emulating a 2880 kB floppy\n"); + + } else if (nsectors == 2400) { + boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_12FLOP; + if (verbose > 0) + fprintf(stderr, "Emulating a 1200 kB floppy\n"); + + } else { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Error - boot image '%s' has not an allowable size.\n", + de->whole_name); +#else + fprintf(stderr, + "Error - boot image '%s' has not an allowable size.\n", + de->whole_name); + exit(1); +#endif + } + + /* load single boot sector for floppies */ + nsectors = 1; + } + + /* fill in boot image details */ +#ifdef DEBUG_TORITO + fprintf(stderr, "Boot %u sectors\n", nsectors); + fprintf(stderr, "Extent of boot images is %d\n", + get_733(de->isorec.extent)); +#endif + set_721(boot_desc_entry->nsect, (unsigned int) nsectors); + set_731(boot_desc_entry->bootoff, + (unsigned int) get_733(de->isorec.extent)); + + + /* If the user has asked for it, patch the boot image */ + if (boot_entry->boot_info_table) { + int bootimage; + unsigned int bi_checksum; + unsigned int total_len; + static char csum_buffer[SECTOR_SIZE]; + int len; + struct genisoimage_boot_info bi_table; + bootimage = open(de->whole_name, O_RDWR | O_BINARY); + if (bootimage == -1) { +#ifdef USE_LIBSCHILY + comerr( + "Error opening boot image file '%s' for update.\n", + de->whole_name); +#else + fprintf(stderr, + "Error opening boot image file '%s' for update.\n", + de->whole_name); + perror(""); + exit(1); +#endif + } + /* Compute checksum of boot image, sans 64 bytes */ + total_len = 0; + bi_checksum = 0; + while ((len = read(bootimage, csum_buffer, SECTOR_SIZE)) > 0) { + if (total_len & 3) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Odd alignment at non-end-of-file in boot image '%s'.\n", + de->whole_name); +#else + fprintf(stderr, + "Odd alignment at non-end-of-file in boot image '%s'.\n", + de->whole_name); + exit(1); +#endif + } + if (total_len < 64) + memset(csum_buffer, 0, 64 - total_len); + if (len < SECTOR_SIZE) + memset(csum_buffer + len, 0, SECTOR_SIZE-len); + for (i = 0; i < SECTOR_SIZE; i += 4) + bi_checksum += get_731(&csum_buffer[i]); + total_len += len; + } + + if (total_len != de->size) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Boot image file '%s' changed underneath us!\n", + de->whole_name); +#else + fprintf(stderr, + "Boot image file '%s' changed underneath us!\n", + de->whole_name); + exit(1); +#endif + } + /* End of file, set position to byte 8 */ + lseek(bootimage, (off_t)8, SEEK_SET); + memset(&bi_table, 0, sizeof (bi_table)); + /* Is it always safe to assume PVD is at session_start+16? */ + set_731(bi_table.bi_pvd, session_start + 16); + set_731(bi_table.bi_file, de->starting_block); + set_731(bi_table.bi_length, de->size); + set_731(bi_table.bi_csum, bi_checksum); + + write(bootimage, &bi_table, sizeof (bi_table)); /* FIXME: check return value */ + close(bootimage); + } +}/* fill_boot_desc(... */ + +void +get_boot_entry() +{ + if (current_boot_entry) + return; + + current_boot_entry = (struct eltorito_boot_entry_info *) + e_malloc(sizeof (struct eltorito_boot_entry_info)); + memset(current_boot_entry, 0, sizeof (*current_boot_entry)); + + if (!first_boot_entry) { + first_boot_entry = current_boot_entry; + last_boot_entry = current_boot_entry; + } else { + last_boot_entry->next = current_boot_entry; + last_boot_entry = current_boot_entry; + } +} + +void +new_boot_entry() +{ + current_boot_entry = NULL; +} + +/* + * Function to write the EVD for the disc. + */ +static int +tvd_write(FILE *outfile) +{ + /* check the boot image is not NULL */ + if (!boot_image) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "No boot image specified.\n"); +#else + fprintf(stderr, "No boot image specified.\n"); + exit(1); +#endif + } + /* Next we write out the boot volume descriptor for the disc */ + get_torito_desc(&gboot_desc); + jtwrite(&gboot_desc, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(&gboot_desc, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + return (0); +} + +struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write, "Eltorito Volume Descriptor"}; diff --git a/genisoimage/endian.c b/genisoimage/endian.c new file mode 100644 index 0000000..461e65c --- /dev/null +++ b/genisoimage/endian.c @@ -0,0 +1,177 @@ +/* + * endian.c + * + * Copyright (c) 2004-2006 Steve McIntyre <steve@einval.com> + * + * Simple helper routines for marshalling data + * + * GNU GPL v2 + */ + +#include <mconfig.h> +#include "endianconv.h" + +/* Write a 64-bit quantity out into memory in BIG ENDIAN order */ +void write_be64(unsigned long long in, unsigned char *out) +{ + out[0] = (in >> 56) & 0xFF; + out[1] = (in >> 48) & 0xFF; + out[2] = (in >> 40) & 0xFF; + out[3] = (in >> 32) & 0xFF; + out[4] = (in >> 24) & 0xFF; + out[5] = (in >> 16) & 0xFF; + out[6] = (in >> 8) & 0xFF; + out[7] = in & 0xFF; +} + +/* Read in a 64-bit BIG ENDIAN quantity */ +unsigned long long read_be64(unsigned char *in) +{ + unsigned long long result = 0; + + result |= (unsigned long long)in[0] << 56; + result |= (unsigned long long)in[1] << 48; + result |= (unsigned long long)in[2] << 40; + result |= (unsigned long long)in[3] << 32; + result |= (unsigned long long)in[4] << 24; + result |= (unsigned long long)in[5] << 16; + result |= (unsigned long long)in[6] << 8; + result |= (unsigned long long)in[7]; + + return result; +} + +/* Write a 64-bit quantity out into memory in LITTLE ENDIAN order */ +void write_le64(unsigned long long in, unsigned char *out) +{ + out[0] = in & 0xFF; + out[1] = (in >> 8) & 0xFF; + out[2] = (in >> 16) & 0xFF; + out[3] = (in >> 24) & 0xFF; + out[4] = (in >> 32) & 0xFF; + out[5] = (in >> 40) & 0xFF; + out[6] = (in >> 48) & 0xFF; + out[7] = (in >> 56) & 0xFF; +} + +/* Read in a 64-bit LITTLE ENDIAN quantity */ +unsigned long long read_le64(unsigned char *in) +{ + unsigned long long result = 0; + + result |= (unsigned long long)in[0]; + result |= (unsigned long long)in[1] << 8; + result |= (unsigned long long)in[2] << 16; + result |= (unsigned long long)in[3] << 24; + result |= (unsigned long long)in[4] << 32; + result |= (unsigned long long)in[5] << 40; + result |= (unsigned long long)in[6] << 48; + result |= (unsigned long long)in[7] << 56; + + return result; +} + +/* Write a 48-bit quantity out into memory in LITTLE ENDIAN order */ +void write_le48(unsigned long long in, unsigned char *out) +{ + out[0] = in & 0xFF; + out[1] = (in >> 8) & 0xFF; + out[2] = (in >> 16) & 0xFF; + out[3] = (in >> 24) & 0xFF; + out[4] = (in >> 32) & 0xFF; + out[5] = (in >> 40) & 0xFF; +} + +/* Read in a 48-bit LITTLE ENDIAN quantity */ +unsigned long long read_le48(unsigned char *in) +{ + unsigned long long result = 0; + + result |= (unsigned long long)in[0]; + result |= (unsigned long long)in[1] << 8; + result |= (unsigned long long)in[2] << 16; + result |= (unsigned long long)in[3] << 24; + result |= (unsigned long long)in[4] << 32; + result |= (unsigned long long)in[5] << 40; + + return result; +} + +/* Write a 32-bit quantity out into memory in BIG ENDIAN order */ +void write_be32(unsigned long in, unsigned char *out) +{ + out[0] = (in >> 24) & 0xFF; + out[1] = (in >> 16) & 0xFF; + out[2] = (in >> 8) & 0xFF; + out[3] = in & 0xFF; +} + +/* Read in a 32-bit BIG ENDIAN quantity */ +unsigned long read_be32(unsigned char *in) +{ + unsigned long result = 0; + + result |= (unsigned long)in[0] << 24; + result |= (unsigned long)in[1] << 16; + result |= (unsigned long)in[2] << 8; + result |= (unsigned long)in[3]; + + return result; +} + +/* Write a 32-bit quantity out into memory in LITTLE ENDIAN order */ +void write_le32(unsigned long in, unsigned char *out) +{ + out[0] = in & 0xFF; + out[1] = (in >> 8) & 0xFF; + out[2] = (in >> 16) & 0xFF; + out[3] = (in >> 24) & 0xFF; +} + +/* Read in a 32-bit LITTLE ENDIAN quantity */ +unsigned long read_le32(unsigned char *in) +{ + unsigned long result = 0; + + result |= (unsigned long)in[0]; + result |= (unsigned long)in[1] << 8; + result |= (unsigned long)in[2] << 16; + result |= (unsigned long)in[3] << 24; + + return result; +} + +/* Write a 16-bit quantity out into memory in BIG ENDIAN order */ +void write_be16(unsigned short in, unsigned char *out) +{ + out[0] = (in >> 8) & 0xFF; + out[1] = in & 0xFF; +} + +/* Read in a 16-bit BIG ENDIAN quantity */ +unsigned short read_be16(unsigned char *in) +{ + unsigned short result = 0; + + result |= (unsigned short)in[0] << 8; + result |= (unsigned short)in[1]; + return result; +} + +/* Write a 16-bit quantity out into memory in LITTLE ENDIAN order */ +void write_le16(unsigned short in, unsigned char *out) +{ + out[0] = in & 0xFF; + out[1] = in & 0xFF >> 8; +} + +/* Read in a 16-bit LITTLE ENDIAN quantity */ +unsigned short read_le16(unsigned char *in) +{ + unsigned short result = 0; + + result |= (unsigned short)in[0]; + result |= (unsigned short)in[1] << 8; + return result; +} + diff --git a/genisoimage/endianconv.h b/genisoimage/endianconv.h new file mode 100644 index 0000000..2337cf9 --- /dev/null +++ b/genisoimage/endianconv.h @@ -0,0 +1,27 @@ +/* + * endian_conv.h + * + * Copyright (c) 2004-2006 Steve McIntyre <steve@einval.com> + * + * Simple helper routines for marshalling data - prototypes + * + * GNU GPL v2 + */ + +void write_be64(unsigned long long in, unsigned char *out); +unsigned long long read_be64(unsigned char *in); +void write_le64(unsigned long long in, unsigned char *out); +unsigned long long read_le64(unsigned char *in); + +void write_le48(unsigned long long in, unsigned char *out); +unsigned long long read_le48(unsigned char *in); + +void write_be32(unsigned long in, unsigned char *out); +unsigned long read_be32(unsigned char *in); +void write_le32(unsigned long in, unsigned char *out); +unsigned long read_le32(unsigned char *in); + +void write_be16(unsigned short in, unsigned char *out); +unsigned short read_be16(unsigned char *in); +void write_le16(unsigned short in, unsigned char *out); +unsigned short read_le16(unsigned char *in); diff --git a/genisoimage/exclude.c b/genisoimage/exclude.c new file mode 100644 index 0000000..759bf35 --- /dev/null +++ b/genisoimage/exclude.c @@ -0,0 +1,78 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)exclude.c 1.9 04/03/04 joerg */ +/* + * 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 <mconfig.h> +#include <stdio.h> +#include <stdxlib.h> +#include <strdefs.h> +#include <standard.h> +#include <schily.h> + + +/* this allows for 1000 entries to be excluded ... */ +#define MAXEXCL 1000 + +static char *excl[MAXEXCL]; + +void exclude(char *fn); +int is_excluded(char *fn); + + +void +exclude(char *fn) +{ + register int i; + + for (i = 0; excl[i] && i < MAXEXCL; i++) + ; + + if (i == MAXEXCL) { + fprintf(stderr, + "Can't exclude '%s' - too many entries in table\n", + fn); + return; + } + excl[i] = (char *) malloc(strlen(fn) + 1); + if (excl[i] == NULL) { +#ifdef USE_LIBSCHILY + errmsg("Can't allocate memory for excluded filename\n"); +#else + fprintf(stderr, + "Can't allocate memory for excluded filename\n"); +#endif + return; + } + strcpy(excl[i], fn); +} + +int +is_excluded(char *fn) +{ + register int i; + + /* + * very dumb search method ... + */ + for (i = 0; excl[i] && i < MAXEXCL; i++) { + if (strcmp(excl[i], fn) == 0) { + return (1); /* found -> excluded filenmae */ + } + } + return (0); /* not found -> not excluded */ +} diff --git a/genisoimage/exclude.h b/genisoimage/exclude.h new file mode 100644 index 0000000..ca20879 --- /dev/null +++ b/genisoimage/exclude.h @@ -0,0 +1,21 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)exclude.h 1.3 04/03/02 eric */ +/* + * 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(char * fn); +int is_excluded(char * fn); diff --git a/genisoimage/files.c b/genisoimage/files.c new file mode 100644 index 0000000..d17a2c7 --- /dev/null +++ b/genisoimage/files.c @@ -0,0 +1,398 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)files.c 1.12 04/03/04 joerg */ +/* + * File files.c - Handle ADD_FILES related stuff. + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ + +#include <mconfig.h> +#include "genisoimage.h" +#include <errno.h> +#include <schily.h> +#include <ctype.h> + +#ifdef ADD_FILES + +void add_one_file(char *addpath, char *path); +void add_file_list(int argc, char **argv, int ind); +void add_file(char *filename); +char *look_up_addition(char **newpath, char *path, struct dirent **de); +void nuke_duplicates(char *path, struct dirent **de); +struct dirent *readdir_add_files(char **pathp, char *path, DIR *dir); + +struct file_adds { + char *name; + struct file_adds *child; + struct file_adds *next; + int add_count; + int used; + union diru { + /* + * XXX Struct dirent is not guaranteed to be any size on a POSIX + * XXX compliant system. + * XXX We need to allocate enough space here, to allow the hacky + * XXX code in tree.c made by Ross Biro biro@yggdrasil.com + * XXX to work on operating systems other than Linux :-( + * XXX Changes made by Joerg Schilling + * XXX joerg@schily.isdn.cs.tu-berlin.de + * XXX to prevent core dumps on Solaris. + * XXX Space allocated: + * XXX 1024 bytes == NAME_MAX + * XXX + 2 bytes for directory record length + * XXX + 2*8 bytes for inode number & offset (64 for future exp) + */ + struct dirent de; + char dspace[NAME_MAX + 2 + 2 * 8]; + } du; + struct { + char *path; + char *name; + } *adds; +}; +extern struct file_adds *root_file_adds; + +/* + * FIXME(eric) - the file adding code really doesn't work very well + * at all. We should differentiate between adding directories, and adding + * single files, as adding a full directory affects how we should be + * searching for things. Ideally what we should do is make two passes + * through the local filesystem - one to figure out what trees we need + * to scan (and merge in any additions at that point), and the second to + * actually fill out each structure with the appropriate contents. + */ + +struct file_adds *root_file_adds = NULL; + +void +add_one_file(char *addpath, char *path) +{ + char *cp; + char *name; + struct file_adds *f; + struct file_adds *tmp; + + f = root_file_adds; + tmp = NULL; + + name = strrchr(addpath, PATH_SEPARATOR); + if (name == NULL) { + name = addpath; + } else { + name++; + } + + cp = strtok(addpath, SPATH_SEPARATOR); + + while (cp != NULL && strcmp(name, cp)) { + if (f == NULL) { + root_file_adds = e_malloc(sizeof (*root_file_adds)); + f = root_file_adds; + f->name = NULL; + f->child = NULL; + f->next = NULL; + f->add_count = 0; + f->adds = NULL; + f->used = 0; + } + if (f->child) { + for (tmp = f->child; tmp->next != NULL; + tmp = tmp->next) { + if (strcmp(tmp->name, cp) == 0) { + f = tmp; + goto next; + } + } + if (strcmp(tmp->name, cp) == 0) { + f = tmp; + goto next; + } + /* add a new node. */ + tmp->next = e_malloc(sizeof (*tmp->next)); + f = tmp->next; + f->name = strdup(cp); + f->child = NULL; + f->next = NULL; + f->add_count = 0; + f->adds = NULL; + f->used = 0; + } else { + /* no children. */ + f->child = e_malloc(sizeof (*f->child)); + f = f->child; + f->name = strdup(cp); + f->child = NULL; + f->next = NULL; + f->add_count = 0; + f->adds = NULL; + f->used = 0; + + } +next: + cp = strtok(NULL, SPATH_SEPARATOR); + } + /* Now f if non-null points to where we should add things */ + if (f == NULL) { + root_file_adds = e_malloc(sizeof (*root_file_adds)); + f = root_file_adds; + f->name = NULL; + f->child = NULL; + f->next = NULL; + f->add_count = 0; + f->adds = NULL; + } + /* Now f really points to where we should add this name. */ + f->add_count++; + f->adds = realloc(f->adds, sizeof (*f->adds) * f->add_count); + f->adds[f->add_count - 1].path = strdup(path); + f->adds[f->add_count - 1].name = strdup(name); +} + +/* + * Function: add_file_list + * + * Purpose: Register an add-in file. + * + * Arguments: + */ +void +add_file_list(int argc, char **argv, int ind) +{ + char *ptr; + char *dup_arg; + + while (ind < argc) { + dup_arg = strdup(argv[ind]); + ptr = strchr(dup_arg, '='); + if (ptr == NULL) { + free(dup_arg); + return; + } + *ptr = 0; + ptr++; + add_one_file(dup_arg, ptr); + free(dup_arg); + ind++; + } +} + +void +add_file(char *filename) +{ + char buff[PATH_MAX]; + FILE *f; + char *ptr; + char *p2; + int count = 0; + + if (strcmp(filename, "-") == 0) { + f = stdin; + } else { + f = fopen(filename, "r"); + if (f == NULL) { +#ifdef USE_LIBSCHILY + comerr("Cannot open '%s'.\n", filename); +#else + perror("fopen"); + exit(1); +#endif + } + } + while (fgets(buff, sizeof (buff), f)) { + count++; + ptr = buff; + while (isspace(*ptr)) + ptr++; + if (*ptr == 0) + continue; + if (*ptr == '#') + continue; + + if (ptr[strlen(ptr) - 1] == '\n') + ptr[strlen(ptr) - 1] = 0; + p2 = strchr(ptr, '='); + if (p2 == NULL) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Error in file '%s' line %d: %s\n", + filename, count, buff); +#else + fprintf(stderr, "Error in file '%s' line %d: %s\n", + filename, count, buff); + exit(1); +#endif + } + *p2 = 0; + p2++; + add_one_file(ptr, p2); + } + if (f != stdin) + fclose(f); +} + +/* This function looks up additions. */ +char * +look_up_addition(char **newpath, char *path, struct dirent **de) +{ + char *dup_path; + char *cp; + struct file_adds *f; + struct file_adds *tmp = NULL; + + f = root_file_adds; + if (!f) + return (NULL); + + /* I don't trust strtok */ + dup_path = strdup(path); + + cp = strtok(dup_path, SPATH_SEPARATOR); + while (cp != NULL) { + for (tmp = f->child; tmp != NULL; tmp = tmp->next) { + if (strcmp(tmp->name, cp) == 0) + break; + } + if (tmp == NULL) { + /* no match */ + free(dup_path); + return (NULL); + } + f = tmp; + cp = strtok(NULL, SPATH_SEPARATOR); + } + free(dup_path); + + /* If nothing, then return. */ + if (tmp == NULL) { + /* no match */ + return (NULL); + } + /* looks like we found something. */ + if (tmp->used >= tmp->add_count) + return (NULL); + + *newpath = tmp->adds[tmp->used].path; + tmp->used++; + *de = &(tmp->du.de); + return (tmp->adds[tmp->used - 1].name); + +} + +/* This function looks up additions. */ +void +nuke_duplicates(char *path, struct dirent **de) +{ + char *dup_path; + char *cp; + struct file_adds *f; + struct file_adds *tmp; + + f = root_file_adds; + if (!f) + return; + + /* I don't trust strtok */ + dup_path = strdup(path); + + cp = strtok(dup_path, SPATH_SEPARATOR); + while (cp != NULL) { + for (tmp = f->child; tmp != NULL; tmp = tmp->next) { + if (strcmp(tmp->name, cp) == 0) + break; + } + if (tmp == NULL) { + /* no match */ + free(dup_path); + return; + } + f = tmp; + cp = strtok(NULL, SPATH_SEPARATOR); + } + free(dup_path); + +#if 0 + /* looks like we found something. */ + if (tmp->used >= tmp->add_count) + return; + + *newpath = tmp->adds[tmp->used].path; + tmp->used++; + *de = &(tmp->du.de); + return (tmp->adds[tmp->used - 1].name); +#endif +} + +/* + * This function lets us add files from outside the standard file tree. + * It is useful if we want to duplicate a cd, but add/replace things. + * We should note that the real path will be used for exclusions. + */ + +struct dirent * +readdir_add_files(char **pathp, char **path, DIR *dir) +{ + struct dirent *de; + + char *addpath; + char *name; + + de = readdir(dir); + if (de) { + nuke_duplicates(path, &de); + return (de); + } + name = look_up_addition(&addpath, path, &de); + + if (!name) { + return (NULL); + } + *pathp = addpath; + + /* + * Now we must create the directory entry. + * fortuneately only the name seems to matter. + */ +/* de->d_ino = -1; de->d_off = 0; de->d_reclen = strlen (name); */ + strncpy(de->d_name, name, NAME_MAX); + de->d_name[NAME_MAX] = 0; + nuke_duplicates(path, &de); + return (de); + +} + +#else +struct dirent * +readdir_add_files(char **pathp, char *path, DIR *dir) +{ + return (readdir(dir)); +} + +#endif diff --git a/genisoimage/fnmatch.c b/genisoimage/fnmatch.c new file mode 100644 index 0000000..d30de89 --- /dev/null +++ b/genisoimage/fnmatch.c @@ -0,0 +1,239 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)fnmatch.c 1.4 02/02/10 eric */ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + +NOTE: The canonical source of this file is maintained with the GNU C Library. +Bugs can be reported to bug-glibc@prep.ai.mit.edu. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <utypes.h> +#include "fnmatch.h" + +#ifndef __STDC__ +#define const +#endif + +#ifndef FNM_FILE_NAME +#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +#endif + +#ifndef FNM_LEADING_DIR +#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ +#endif + +#ifndef FNM_CASEFOLD +#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +#endif + + +#include <ctype.h> + +#if defined (STDC_HEADERS) || !defined (isascii) +#define ISASCII(c) 1 +#else +#define ISASCII(c) isascii(c) +#endif + +#define ISUPPER(c) (ISASCII (c) && isupper (c)) + + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) +extern int errno; +#endif + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +int +fnmatch (const char *pattern, const char *string, int flags) +{ + register const char *p = pattern, *n = string; + register char c; + +/* Note that this evalutes C many times. */ +#define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) + + while ((c = *p++) != '\0') + { + c = FOLD ((Uchar)c); + + switch (c) + { + case '?': + if (*n == '\0') + return FNM_NOMATCH; + else if ((flags & FNM_FILE_NAME) && *n == '/') + return FNM_NOMATCH; + else if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + c = FOLD ((Uchar )c); + } + if (FOLD ((Uchar )*n) != c) + return FNM_NOMATCH; + break; + + case '*': + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) + if (((flags & FNM_FILE_NAME) && *n == '/') || + (c == '?' && *n == '\0')) + return FNM_NOMATCH; + + if (c == '\0') + return 0; + + { + char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; + c1 = FOLD ((Uchar )c1); + for (--p; *n != '\0'; ++n) + if ((c == '[' || FOLD ((Uchar )*n) == c1) && + fnmatch (p, n, flags & ~FNM_PERIOD) == 0) + return 0; + return FNM_NOMATCH; + } + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + register int not; + + if (*n == '\0') + return FNM_NOMATCH; + + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + not = (*p == '!' || *p == '^'); + if (not) + ++p; + + c = *p++; + for (;;) + { + register char cstart = c, cend = c; + + if (!(flags & FNM_NOESCAPE) && c == '\\') + cstart = cend = *p++; + + cstart = cend = FOLD ((Uchar)cstart); + + if (c == '\0') + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + c = FOLD ((Uchar)c); + + if ((flags & FNM_FILE_NAME) && c == '/') + /* [/] can never match. */ + return FNM_NOMATCH; + + if (c == '-' && *p != ']') + { + cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return FNM_NOMATCH; + cend = FOLD ((Uchar)cend); + + c = *p++; + } + + if ((Uchar)FOLD((Uchar)*n) >= (Uchar)cstart && (Uchar)FOLD((Uchar)*n) <= (Uchar)cend) + goto matched; + + if (c == ']') + break; + } + if (!not) + return FNM_NOMATCH; + break; + + matched:; + /* Skip the rest of the [...] that already matched. */ + while (c != ']') + { + if (c == '\0') + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + if (!(flags & FNM_NOESCAPE) && c == '\\') + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + if (not) + return FNM_NOMATCH; + } + break; + + default: + if (c != FOLD ((Uchar)*n)) + return FNM_NOMATCH; + } + + ++n; + } + + if (*n == '\0') + return 0; + + if ((flags & FNM_LEADING_DIR) && *n == '/') + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/genisoimage/fnmatch.h b/genisoimage/fnmatch.h new file mode 100644 index 0000000..ef2bbd9 --- /dev/null +++ b/genisoimage/fnmatch.h @@ -0,0 +1,101 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)fnmatch.h 1.4 04/03/02 eric */ +/* + * Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + * + * NOTE: The canonical source of this file is maintained with the GNU C Library. + * Bugs can be reported to bug-glibc@prep.ai.mit.edu. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _FNMATCH_H + +#define _FNMATCH_H 1 + +#ifndef _PROTOTYP_H +#include <prototyp.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)*/ +#ifdef PROTOTYPES +#undef __P +#define __P(protos) protos +#else /* Not C++ or ANSI C. */ +#undef __P +#define __P(protos) () +/* + * We can get away without defining `const' here only because in this file + * it is used only inside the prototype for `fnmatch', which is elided in + * non-ANSI C where `const' is problematical. + */ +#endif /* C++ or ANSI C. */ + + +/* + * We #undef these before defining them because some losing systems + * (HP-UX A.08.07 for example) define these in <unistd.h>. + */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD + +/* Bits set in the FLAGS argument to `fnmatch'. */ +#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ +#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ +#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ + +#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined(_GNU_SOURCE) +#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ +#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +#endif + +#ifndef FNM_FILE_NAME +/* + * Apparently GNU libc doesn't define this thing. + */ +#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +#endif + +/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +/* + * Match STRING against the filename pattern PATTERN, + * returning zero if it matches, FNM_NOMATCH if not. + */ +extern int fnmatch(const char *__pattern, const char *__string, int __flags); + +#ifdef __cplusplus +} +#endif + +#endif /* fnmatch.h */ diff --git a/genisoimage/genisoimage.1 b/genisoimage/genisoimage.1 new file mode 100644 index 0000000..d05b24a --- /dev/null +++ b/genisoimage/genisoimage.1 @@ -0,0 +1,2823 @@ +'\" t +.\" genisoimage.1 -*- nroff -*- To render, first run through tbl +.\" Copyright 1993-1998 by Yggdrasil Computing +.\" Copyright 1996-1997 by Robert Leslie +.\" Copyright 1997-2001 by James Pearson +.\" Copyright 1999-2006 by Joerg Schilling +.\" Copyright 2002-2003 by Jungshik Shin +.\" Copyright 2003 by Jaakko Heinonen +.\" Copyright 2006 by the Cdrkit maintainers +.\" +.TH GENISOIMAGE 1 "13 Dec 2006" +.\" ---------------------------------------- +.SH NAME +genisoimage \- create ISO9660/Joliet/HFS filesystem with optional Rock Ridge attributes +.\" ---------------------------------------- +.SH SYNOPSIS +.B genisoimage +.RI [ options ] +.RB [ \-o +.IR filename ] +.IR pathspec " [" "pathspec ..." ] +.\" ---------------------------------------- +.SH DESCRIPTION +.B genisoimage +is a pre-mastering program to generate ISO9660/Joliet/HFS hybrid +filesystems. +.PP +.B genisoimage +is capable of generating the +.B System Use Sharing Protocol records (SUSP) +specified by the +.BR "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 long filenames, UID/GID, POSIX permissions, symbolic links, and +block and character device files. +.PP +If Joliet or HFS hybrid command line options are specified, +.B genisoimage +will create the additional filesystem metadata needed for Joliet or HFS. +Otherwise +.B genisoimage +will generate a pure ISO9660 filesystem. +.PP +.B genisoimage +can generate a +.I true +(or +.IR shared ) +HFS hybrid filesystem. The same files are seen as HFS files when +accessed from a Macintosh and as ISO9660 files when accessed from other +machines. HFS stands for +.I Hierarchical File System +and is the native filesystem used on Macintosh computers. +.PP +As an alternative, +.B genisoimage +can generate the +.I Apple Extensions to ISO9660 +for each file. These extensions provide each file with CREATOR, TYPE and +certain Finder flags when accessed from a Macintosh. See the +.B HFS MACINTOSH FILE FORMATS +section below. +.PP +.B genisoimage +takes a snapshot of a given directory tree, and generates a +binary image which will correspond to an ISO9660 and/or HFS filesystem when +written to a block device. +.PP +Each file written to the ISO9660 filesystem must have a filename in the 8.3 +format (up to 8 characters, period, up to 3 characters, all uppercase), 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 genisoimage +generally tries to form correct names by forcing the Unix filename to +uppercase and truncating as required, but often this yields unsatisfactory +results when the truncated names are not all unique. +.B genisoimage +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 include a +3-digit number (guaranteed to be unique). For example, the two files +.I foo.bar +and +.I foo.bar.~1~ +could be rendered as +.I FOO.BAR;1 +and +.IR FOO000.BAR;1 . +.PP +When used with various HFS options, +.B genisoimage +will attempt to recognise files stored in a number of Apple/Unix file formats +and will copy the data and resource forks as well as any +relevant Finder information. See the +.B HFS MACINTOSH FILE FORMATS +section below for more about formats +.B genisoimage +supports. +.PP +Note that +.B genisoimage +is not designed to communicate with the writer directly. Most writers +have proprietary command sets which vary from one manufacturer to +another, and you need a specialized tool to actually burn the disc. +.B wodim +is one such tool. The latest version of +.B wodim +is available from +.IR http://www.cdrkit.org/ . +.PP +.B pathspec +is the path of the directory tree to be copied into the ISO9660 filesystem. +Multiple paths can be specified, and +.B genisoimage +will merge the files found in all of the specified path components to +form the filesystem image. +.PP +If the option +.B \-graft\-points +has been specified, it is possible to graft the paths at points other +than the root directory, and it is possible to graft files or +directories onto the cdrom image with names different than what they +have in the source filesystem. This is easiest to illustrate with a +couple of examples. Let's start by assuming that a local file +.I ../old.lis +exists, and you wish to include it in the cdrom image. +.IP +foo/bar/=../old.lis +.PP +will include +.I old.lis +in the cdrom image at +.IR /foo/bar/old.lis , +while +.IP +foo/bar/xxx=../old.lis +.PP +will include +.I old.lis +in the cdrom image at +.IR /foo/bar/xxx . +The same sort of syntax can be used with directories as well. +.B genisoimage +will create any directories required such that the graft +points exist on the cdrom image \(em the directories do not need to +appear in one of the paths. By default, any directories that are created on +the fly like this will have permissions 0555 and appear to be owned by the +person running +.BR genisoimage . +If you wish other permissions or owners of +the intermediate directories, see +.BR \-uid ", " \-gid ", " \-dir\-mode ", " \-file\-mode " and " \-new\-dir\-mode . +.PP +.B genisoimage +will also run on Windows machines when compiled with Cygnus' cygwin +(available from +.IR http://www.cygwin.com/ ). +Therefore most references in this man page to +.I Unix +can be replaced with +.IR Win32 . +.\" ---------------------------------------- +.SH OPTIONS +.PP +Several options can be specified as defaults in a +.I .genisoimagerc +configuration file, as well as on the command line. If a parameter is +specified in both places, the setting from the command line is used. +For details on the format and possible locations of this file, see +.BR genisoimagerc (5). +.TP +.BI \-abstract " file" +Specifies the abstract filename. There is space for 37 characters. +Equivalent to +.B ABST +in the +.I .genisoimagerc +file. +.TP +.BI \-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 for 128 characters. Equivalent to +.B APPI +in the +.I .genisoimagerc +file. +.TP +.B \-allow\-limited\-size +When processing files larger than 2GiB which cannot be easily represented in +ISO9660, add them with a shrunk visible file size to ISO9660 and with the +correct visible file size to the UDF system. The result is an inconsistent +filesystem and users need to make sure that they really use UDF rather than +ISO9660 driver to read a such disk. Implies enabling +.BR \-udf. +.TP +.B \-allow\-leading\-dots +.TP +.B \-ldots +Allow ISO9660 filenames to begin with a period. Usually, a leading dot is +replaced with an underscore in order to maintain MS-DOS compatibility. +.br +This violates the ISO9660 standard, but it happens to work on many systems. +Use with caution. +.TP +.B \-allow\-lowercase +This options allows lowercase characters to appear in ISO9660 filenames. +.br +This violates the ISO9660 standard, but it happens to work on some systems. +Use with caution. +.TP +.B \-allow\-multidot +This options allows more than one dot to appear in ISO9660 filenames. +A leading dot is not affected by this option, it +may be allowed separately using +.BR \-allow\-leading\-dots . +.br +This violates the ISO9660 standard, but it happens to work on many systems. +Use with caution. +.TP +.BI \-biblio " file" +Specifies the bibliographic filename. There is space for 37 characters. +Equivalent to +.B BIBL +in the +.I .genisoimagerc +file. +.TP +.B \-cache\-inodes +.TP +.B \-no\-cache\-inodes +Enable or disable caching inode and device numbers to find hard links +to files. If +.B genisoimage +finds a hard link (a file with multiple names), the file will also be +hard-linked on the CD, so the file contents only appear once. This +helps to save space. +.B \-cache\-inodes +is default on Unix-like operating systems, but +.B \-no\-cache\-inodes +is default on some other systems such as Cygwin, because it is not safe +to assume that inode numbers are unique on those systems. (Some +versions of Cygwin create fake inode numbers using a weak hashing +algorithm, which may produce duplicates.) If two files have the same +inode number but are not hard links to the same file, +.B genisoimage \-cache\-inodes +will not behave correctly. +.B \-no\-cache\-inodes +is safe in all situations, but in that case +.B genisoimage +cannot detect hard links, so the resulting CD image may be larger +than necessary. +.TP +.BI \-alpha\-boot " alpha_boot_image" +Specifies the path and filename of the boot image to be used when +making an Alpha/SRM bootable CD. The pathname must be relative to the +source path specified to +.BR genisoimage . +.TP +.BI \-hppa\-bootloader " hppa_bootloader_image" +Specifies the path and filename of the boot image to be used when +making an HPPA bootable CD. The pathname must be relative to the +source path specified to +.BR genisoimage . +Other options are required, at the very least a kernel filename and +a boot command line. See the +.B HPPA NOTES +section below for more information. +.TP +.BI \-hppa\-cmdline " hppa_boot_command_line" +Specifies the command line to be passed to the HPPA boot loader when +making a bootable CD. Separate the parameters with spaces or +commas. More options must be passed to +.B genisoimage, +at the very least a kernel filename and the boot loader filename. +See the +.B HPPA NOTES +section below for more information. +.TP +.BI \-hppa\-kernel\-32 " hppa_kernel_32" +.TP +.BI \-hppa\-kernel\-64 " hppa_kernel_64" +Specifies the path and filename of the 32-bit and/or 64-bit kernel images +to be used when making an HPPA bootable CD. The pathnames must be +relative to the source path specified to +.BR genisoimage . +Other options are required, at the very least the boot loader filename +and the boot command line. See the +.B HPPA NOTES +section below for more information. +.TP +.BI \-hppa\-ramdisk " hppa_ramdisk_image" +Specifies the path and filename of the ramdisk image to be used when +making an HPPA bootable CD. The pathname must be relative to the +source path specified to +.BR genisoimage . +This parameter is optional. Other options are required, at the very +least a kernel filename and the boot command line. See the +.B HPPA NOTES +section below for more information. +.TP +.BI \-mips\-boot " mips_boot_image" +Specifies the path and filename of the boot image to be used when +making an SGI/big-endian MIPS bootable CD. The pathname must be +relative to the source path specified to +.BR genisoimage . +This option may be specified several times, to store up to 15 boot +images. +.TP +.BI \-mipsel\-boot " mipsel_boot_image" +Specifies the path and filename of the boot image to be used when +making an DEC/little-endian MIPS bootable CD. The pathname must be +relative to the source path specified to +.BR genisoimage . +.TP +.BI \-B " img_sun4,img_sun4c,img_sun4m,img_sun4d,img_sun4e" +.TP +.BI \-sparc\-boot " img_sun4,img_sun4c,img_sun4m,img_sun4d,img_sun4e" +Specifies a comma-separated list of boot images that are needed to make +a bootable CD for SPARC systems. +Partition 0 is used for the ISO9660 image, the first image file is mapped +to partition 1. +The comma-separated list may have up to 7 fields, including empty fields. +This option is required to make a bootable CD for Sun SPARC systems. +If +.B \-B +or +.B \-sparc\-boot +has been specified, the first sector of the resulting image will +contain a Sun disk label. This disk label specifies slice 0 for the +ISO9660 image and slices 1 to 7 for the boot images that +have been specified with this option. Byte offsets 512 to 8191 +within each of the additional boot images must contain a primary boot +that works for the appropriate SPARC architecture. The rest of each +of the images usually contains a UFS filesystem used for the primary +kernel boot stage. +.IP +The implemented boot method is the one found with SunOS 4.x and SunOS 5.x. +However, it does not depend on SunOS internals but only on properties of +the Open Boot prom, so it should be usable for any OS for SPARC systems. +For more information also see the +.B NOTES +section below. +.IP +If the special filename +.B ... +is used, the actual and all following boot partitions are mapped to the +previous partition. If +.B genisoimage +is called with +.BI \-G " image " \-B " ..." +all boot partitions are mapped to the partition that contains the ISO9660 +filesystem image and the generic boot image that is located in the first +16 sectors of the disc is used for all architectures. +.TP +.BI \-G " generic_boot_image" +Specifies the path and filename of the generic boot image to be used when making +a generic bootable CD. The boot image will be placed on the first 16 +sectors of the CD, before the ISO9660 primary volume descriptor. +If this option is used together with +.BR \-sparc\-boot , +the Sun disk label will overlay the first 512 bytes of the generic +boot image. +.TP +.BI \-b " eltorito_boot_image" +Specifies the path and filename of the boot image to be used when making +an El Torito bootable CD for x86 PCs. The pathname must be relative to +the source path specified to +.BR genisoimage . +This option is required to make an El Torito bootable CD. +The boot image must be exactly 1200 kB, 1440 kB or 2880 kB, and +.B genisoimage +will use this size when creating the output ISO9660 filesystem. The PC +BIOS will use the image to emulate a floppy disk, so the first 512-byte +sector should contain PC boot code. This will work, for example, if +the boot image is a LILO-based boot floppy. +.IP +If the boot image is not an image of a floppy, you need to add either +.BR \-hard\-disk\-boot " or " \-no\-emul\-boot . +If the system should not boot off the emulated disk, use +.BR \-no\-boot . +.IP +If +.B \-sort +has not been specified, the boot images are sorted +with low priority (+2) to the beginning of the medium. +If you don't like this, you need to specify a sort weight of 0 for the boot images. +.TP +.B \-eltorito\-alt\-boot +Start with a new set of El Torito boot parameters. Up to 63 El Torito +boot entries may be stored on a single CD. +.TP +.BI \-hard\-disk\-boot +Specifies that the boot image used to create El Torito bootable CDs is +a hard disk image. The image must begin with a master boot +record that contains a single partition. +.TP +.BI \-no\-emul\-boot +Specifies that the boot image used to create El Torito bootable CDs is +a "no emulation" image. The system will load and execute this image without +performing any disk emulation. +.TP +.BI \-no\-boot +Specifies that the created El Torito CD should be marked as not bootable. The +system will provide an emulated drive for the image, but will boot off +a standard boot device. +.TP +.BI \-boot\-load\-seg " segment_address" +Specifies the load segment address of the boot image for no-emulation +El Torito CDs. +.TP +.BI \-boot\-load\-size " load_sectors" +Specifies the number of "virtual" (512-byte) sectors to load in +no-emulation mode. The default is to load the entire boot file. Some +BIOSes may have problems if this is not a multiple of 4. +.TP +.B \-boot\-info\-table +Specifies that a 56-byte table with information of the CD-ROM layout +will be patched in at offset 8 in the boot file. If this option is +given, the boot file is +.IR "modified in the source filesystem" , +so make a copy of this file if it cannot be easily regenerated! +See the +.B EL TORITO BOOT INFO TABLE +section for a description of this table. +.TP +.BI \-C " last_sess_start,next_sess_start" +This option is needed to create a CD Extra or the image of a second +session or a higher-level session for a multisession disc. +.B \-C +takes two numbers separated by a comma. The first is the first sector +in the last session of the disc that should be appended to. +The second number is the starting sector number of the new session. +The correct numbers may be retrieved by calling +.B wodim \-msinfo ... +If +.B \-C +is used in conjunction with +.BR \-M , +.B genisoimage +will create a filesystem image that is intended to be a continuation +of the previous session. +If +.B \-C +is used without +.BR \-M , +.B genisoimage +will create a filesystem image that is intended to be used for a second +session on a CD Extra. This is a multisession CD that holds audio data +in the first session and an ISO9660 filesystem in the second session. +.TP +.BI \-c " boot_catalog" +Specifies the path and filename of the boot catalog, which is required +for an El Torito bootable CD. The pathname must be relative to the source +path specified to +.BR genisoimage . +This file will be inserted into the output tree and not created +in the source filesystem, so be +sure the specified filename does not conflict with an existing file, or +it will be excluded. Usually a name like +.I boot.catalog +is chosen. +.IP +If +.B \-sort +has not been specified, the boot catalog sorted +with low priority (+1) to the beginning of the medium. +If you don't like this, you need to specify a sort weight of 0 for the boot catalog. +.TP +.B \-check\-oldnames +Check all filenames imported from the old session for compliance with +the ISO9660 file naming rules. +Without this option, only names longer than 31 characters are checked, +as these files are a serious violation of the ISO9660 standard. +.TP +.BI \-check\-session " file" +Check all old sessions for compliance with actual +.B genisoimage +ISO9660 file naming rules. +This is a high-level option that combines +.B \-M +.I file +.BR "\-C 0,0 \-check\-oldnames" . +For the parameter +.IR file , +see the description of +.BR \-M . +.TP +.BI \-copyright " file" +Specifies copyright information, typically a filename on the disc. +There is space for 37 characters. Equivalent to +.B COPY +in the +.I .genisoimagerc +file. +.TP +.B \-d +Do not append a period to files that do not have one. +.br +This violates the ISO9660 standard, but it happens to work on many systems. +Use with caution. +.TP +.B \-D +Do not use deep directory relocation, and instead just pack them in the +way we see them. +.br +If ISO9660:1999 has not been selected, +this violates the ISO9660 standard, but it happens to work on many systems. +Use with caution. +.TP +.BI \-dir\-mode " mode" +Overrides the mode of directories used to create the image to +.IR mode , +specified as 4 digits of permission bits as in +.BR chmod (1). +This option automatically enables Rock Ridge extensions. +.TP +.B \-dvd\-video +Generate a DVD-Video compliant UDF filesystem. This is done by sorting the +order of the content of the appropriate files and by adding padding +between the files if needed. +Note that the sorting only works if the DVD-Video filenames include uppercase +characters only. +.IP +Note that in order to get a DVD-Video compliant filesystem image, you +need to prepare a DVD-Video compliant directory tree. This requires a +directory +.B VIDEO_TS +(all caps) in the root directory of the resulting DVD, and usually +another directory +.BR AUDIO_TS . +.B VIDEO_TS +needs to include all needed files (filenames must be all caps) for a +compliant DVD-Video filesystem. +.TP +.B \-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 +they will be ignored. +.TP +.BI \-file\-mode " mode" +Overrides the mode of regular files used to create the image to +.IR mode , +specified as 4 digits of permission bits as in +.BR chmod (1). +This option automatically enables Rock Ridge extensions. +.TP +.BI \-gid " gid" +Overrides the group ID read from the source files to the value of +.IR gid . +Specifying this option automatically enables Rock Ridge extensions. +.TP +.B \-gui +Switch the behaviour for a GUI. This currently makes the output more verbose +but may have other effects in the future. +.TP +.B \-graft\-points +Allow use of graft points for filenames. If this option is used, all +filenames are checked for graft points. The filename is divided at the +first unescaped equal sign. All occurrences of `\(rs' and `=' characters +must be escaped with `\(rs' if +.B \-graft\-points +has been specified. +.TP +.BI \-hide " glob" +Hide any files matching +.IR glob , +a shell wildcard pattern, from being seen in the ISO9660 or Rock Ridge +directory. +.I glob +may match any part of the filename or path. If +.I glob +matches a directory, the contents of that directory will be hidden. +In order to match a directory name, make sure the pathname does not include +a trailing `/' character. +All the hidden files will still be written to the output CD image file. +See also +.BR \-hide\-joliet , +and +.IR README.hide . +This option may be used multiple times. +.TP +.BI \-hide\-list " file" +A file containing a list of shell wildcards to be hidden. See +.BR \-hide . +.TP +.BI \-hidden " glob" +Add the hidden (existence) ISO9660 directory attribute for files and +directories matching +.IR glob , +a shell wildcard pattern. This attribute will prevent the files from +being shown by some MS-DOS and Windows commands. +.I glob +may match any part of the filename or path. +In order to match a directory name, make sure the pathname does not include +a trailing `/' character. +This option may be used multiple times. +.TP +.BI \-hidden\-list " file" +A file containing a list of shell wildcards to get the hidden +attribute. See +.BR \-hidden . +.TP +.BI \-hide\-joliet " glob" +Hide files and directories matching +.IR glob , +a shell wildcard pattern, from being seen in the Joliet directory. +.I glob +may match any part of the filename or path. If +.I glob +matches a directory, the contents of that directory will be hidden. +In order to match a directory name, make sure the pathname does not include +a trailing `/' character. +All the hidden files will still be written to the output CD image file. +This option is usually used with +.BR \-hide . +See also +.IR README.hide . +This option may be used multiple times. +.TP +.BI \-hide\-joliet\-list " file" +A file containing a list of shell wildcards to be hidden from the +Joliet tree. See +.BR \-hide\-joliet . +.TP +.B \-hide\-joliet\-trans\-tbl +Hide the +.I TRANS.TBL +files from the Joliet tree. +These files usually don't make sense in the Joliet world as they list +the real name and the ISO9660 name which may both be different from the +Joliet name. +.TP +.B \-hide\-rr\-moved +Rename the directory +.I RR_MOVED +to +.I .rr_moved +in the Rock Ridge tree. +It seems to be impossible to completely hide the +.I RR_MOVED +directory from the Rock Ridge tree. +This option only makes the visible tree less confusing for +people who don't know what this directory is for. +If you need to have no +.I RR_MOVED +directory at all, you should use +.BR \-D . +Note that if +.B \-D +has been specified, the resulting filesystem is not ISO9660 +level-1 compliant and will not be readable on MS-DOS. +See also the +.B NOTES +section. +.TP +.BI \-input\-charset " charset" +Input charset that defines the characters used in local filenames. +To get a list of valid charset names, call +.BR "genisoimage \-input\-charset help" . +To get a 1:1 mapping, you may use +.B default +as charset name. The default initial values are +.I cp437 +on DOS-based systems and +.I iso8859-1 +on all other systems. See the +.B CHARACTER SETS +section below for more details. +.TP +.BI \-output\-charset " charset" +Output charset that defines the characters that will be used in Rock Ridge +filenames. Defaults to the input charset. See +.B CHARACTER SETS +section below for more details. +.TP +.BI \-iso\-level " level" +Set the ISO9660 conformance level. Valid numbers are 1 to 4. +.IP +With level 1, files may only consist of one section and filenames are +restricted to 8.3 characters. +.IP +With level 2, files may only consist of one section. +.IP +With level 3, no restrictions (other than ISO-9660:1988) do apply. +.IP +With all ISO9660 levels from 1 to 3, all filenames are restricted to +uppercase letters, numbers and underscores (_). Filenames are +limited to 31 characters, directory nesting is limited to 8 +levels, and pathnames are limited to 255 characters. +.IP +Level 4 officially does not exist but +.B genisoimage +maps it to ISO-9660:1999, which is ISO9660 version 2. +.IP +With level 4, an enhanced volume descriptor with version number +and file structure version number set to 2 is emitted. +Directory nesting is not limited to 8 levels, +there is no need for a file to contain a dot and the dot has no +special meaning, filenames do not have version numbers, +.\" (f XXX ??? The character used for filling byte positions which are +.\" specified to be characters is subject to agreement between the +.\" originator and the recipient of the volume), +and filenames can be up to 207 characters long, or 197 characters if +Rock Ridge is used. +.IP +When creating Version 2 images, +.B genisoimage +emits an enhanced volume descriptor, similar but not identical to a +primary volume descriptor. Be careful not to use broken software +to make ISO9660 images bootable by assuming a second PVD copy and patching +this putative PVD copy into an El Torito VD. +.TP +.B \-J +Generate Joliet directory records in addition to regular ISO9660 +filenames. This is primarily useful when the discs are to be used on +Windows machines. Joliet filenames are specified in Unicode and each +path component can be up to 64 Unicode characters long. +Note that Joliet is not a standard \(em only Microsoft Windows and Linux +systems can read Joliet extensions. For greater portability, consider +using both Joliet and Rock Ridge extensions. +.TP +.B \-joliet\-long +Allow Joliet filenames to be up to 103 Unicode characters, instead of +64. This breaks the Joliet specification, but appears to work. Use +with caution. +.\" The number 103 is derived from: the maximum Directory Record Length +.\" (254), minus the length of Directory Record (33), minus CD-ROM XA +.\" System Use Extension Information (14), divided by the UTF-16 +.\" character size (2). +.TP +.BI \-jcharset " charset" +A combination of +.B \-J \-input\-charset +.IR charset . +See the +.B CHARACTER SETS +section below for more details. +.TP +.B \-l +Allow full 31-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 31 characters. If you use this option, the disc may +be difficult to use on a MS-DOS system, but will work on most other systems. +Use with caution. +.TP +.B \-L +Outdated option; use +.B \-allow\-leading\-dots +instead. +.TP +.BI \-jigdo\-jigdo " jigdo_file" +Produce a +.B jigdo +.I .jigdo +metadata file as well as the filesystem image. See the +.B JIGDO NOTES +section below for more information. +.TP +.BI \-jigdo\-template " template_file" +Produce a +.B jigdo +.I .template +file as well as the filesystem image. See the +.B JIGDO NOTES +section below for more information. +.TP +.BI \-jigdo\-min\-file\-size " size" +Specify the minimum size for a file to be listed in the +.I .jigdo +file. Default (and minimum allowed) is 1KB. See the +.B JIGDO NOTES +section below for more information. +.TP +.BI \-jigdo\-force\-md5 " path" +Specify a file pattern where files +.I must +be contained in the externally-supplied MD5 list as supplied by +.BR \-md5\-list . +See the +.B JIGDO NOTES +section below for more information. +.TP +.BI \-jigdo\-exclude " path" +Specify a file pattern where files will not be listed in the +.I .jigdo +file. See the +.B JIGDO NOTES +section below for more information. +.TP +.BI \-jigdo\-map " path" +Specify a pattern mapping for the jigdo file +(e.g. +.IR Debian=/mirror/debian ). +See the +.B JIGDO NOTES +section below for more information. +.TP +.BI \-md5\-list " md5_file" +Specify a file containing the MD5sums, sizes and pathnames of the +files to be included in the +.I .jigdo +file. See the +.B JIGDO NOTES +section below for more information. +.TP +.BI \-jigdo\-template\-compress " algorithm +Specify a compression algorithm to use for template date. gzip and +bzip2 are currently supported, and gzip is the default. See the +.B JIGDO NOTES +section below for more information. +.TP +.BI \-log\-file " log_file" +Redirect all error, warning and informational messages to +.I log_file +instead of the standard error. +.TP +.BI \-m " glob" +Exclude files matching +.IR glob , +a shell wildcard pattern, from being written to CD-ROM. +.I glob +may match either the filename component or the full pathname. +This option may be used multiple times. For example: +.sp + genisoimage \-o rom \-m \(aq*.o\(aq \-m core \-m foobar +.sp +would exclude all files ending in `.o', or called +.IR core " or " foobar +from the image. Note that if you had a directory called +.IR foobar , +it too (and of course all its descendants) would be excluded. +.TP +.BI \-exclude\-list " file" +A file containing a list of shell wildcards to be excluded. See +.BR \-m . +.TP +.B \-max\-iso9660\-filenames +Allow ISO9660 filenames to be up to 37 characters long. +This option enables +.B \-N +as the extra name space is taken from the space reserved for +file version numbers. +.br +This violates the ISO9660 standard, but it happens to work on many systems. +Although a conforming application needs to provide a buffer space of at +least 37 characters, discs created with this option may cause a buffer +overflow in the reading operating system. Use with extreme care. +.TP +.BI \-M " path" +.TP +.BI \-M " device" +.TP +.BI \-dev " device" +Specifies path to existing ISO9660 image to be merged. The alternate form +takes a SCSI device specifier that uses the same syntax as the +.B dev= +parameter of +.BR wodim . +The output of +.B genisoimage +will be a new session which should get written to the end of the +image specified in +.BR \-M . +Typically this requires multisession capability for the CD recorder +used to write the image. This option may only be used in conjunction +with +.BR \-C . +.TP +.B \-N +Omit version numbers from ISO9660 filenames. +.br +This violates the ISO9660 standard, but no one really uses the +version numbers anyway. Use with caution. +.TP +.BI \-new\-dir\-mode " mode" +Specify the mode, a 4-digit number as used in +.BR chmod (1), +to use when creating new directories in the filesystem image. The +default is 0555. +.TP +.B \-nobak +.TP +.B \-no\-bak +Exclude backup files files on the ISO9660 filesystem; that is, +filenames that contain the characters `~' or `#' or end in +.IR .bak . +These are typically backup files for Unix text editors. +.TP +.B \-force\-rr +Do not use the automatic Rock Ridge attributes recognition for previous sessions. +This can work around problems with images created by, e.g., NERO Burning ROM. +.TP +.B \-no\-rr +Do not use the Rock Ridge attributes from previous sessions. +This may help to avoid problems when +.B genisoimage +finds illegal Rock Ridge signatures on an old session. +.TP +.B \-no\-split\-symlink\-components +Don't split the symlink components, but begin a new Continuation Area (CE) +instead. This may waste some space, but the SunOS 4.1.4 cdrom driver +has a bug in reading split symlink components. +.IP +It is questionable whether this option is useful nowadays. +.TP +.B \-no\-split\-symlink\-fields +Don't split the symlink fields, but begin a new Continuation Area (CE) +instead. This may waste some space, but the SunOS 4.1.4 and +Solaris 2.5.1 cdrom driver have a bug in reading split symlink fields +(a `/' can be dropped). +.IP +It is questionable whether this option is useful nowadays. +.TP +.BI \-o " filename" +Specify the output file for the the ISO9660 filesystem image. +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 device for a regular +disk partition, in which case the ISO9660 filesystem can be mounted +normally to verify that it was generated correctly. +.TP +.B \-pad +Pad the end of the whole image by 150 sectors (300 kB). This option is +enabled by default. If used in combination with +.BR \-B , +padding is inserted between the ISO9660 partition and the boot +partitions, such that the first boot partition starts +on a sector number that is a multiple of 16. +.IP +The padding is needed as many operating systems (e.g. Linux) +implement read-ahead bugs in their filesystem I/O. These bugs result in read +errors on files that are located near the end of a track, particularly +if the disc is written in Track At Once mode, or where a CD audio track +follows the data track. +.\" XXX: Someone should check to see if the Linux readahead bug is +.\" XXX: still present, and update this comment accordingly. +.TP +.B \-no\-pad +Do not pad the end by 150 sectors (300 kB) and do not make the the boot partitions +start on a multiple of 16 sectors. +.TP +.BI \-path\-list " file" +A file containing a list of +.I pathspec +directories and filenames to be added to the ISO9660 filesystem. This list +of pathspecs are processed after any that appear on the command line. If the +argument is +.IR \- , +the list is read from the standard input. +.TP +.B \-P +Outdated option; use +.B \-publisher +instead. +.TP +.BI \-publisher " publisher_id" +Specifies a text string that will be written into the volume header. +This should describe the publisher of the CD-ROM, usually with a +mailing address and phone number. There is space for 128 characters. +Equivalent to +.B PUBL +in the +.I .genisoimagerc +file. +.TP +.BI \-p " preparer_id" +Specifies a text string that will be written into the volume header. +This should describe the preparer of the CD-ROM, usually with a mailing +address and phone number. There is space for 128 characters. +Equivalent to +.B PREP +in the +.I .genisoimagerc +file. +.TP +.B \-print\-size +Print estimated filesystem size in multiples of the sector size (2048 bytes) +and exit. This option is needed for +Disk At Once mode and with some CD-R drives when piping directly into +.BR wodim , +cases where +.B wodim +needs to know the size of the filesystem image in advance. +Old versions of +.B mkisofs +wrote this information (among other information) to +.IR stderr . +As this turns out to be hard to parse, the number without any other information +is now printed on +.I stdout +too. +If you like to write a simple shell script, redirect +.I stderr +and catch the number from +.IR stdout . +This may be done with: +.sp + cdblocks=\` genisoimage \-print\-size \-quiet .\|.\|. \` +.br + genisoimage .\|.\|. | wodim .\|.\|. tsize=${cdblocks}s \- +.TP +.B \-quiet +This makes +.B genisoimage +even less verbose. No progress output will be provided. +.TP +.B \-R +Generate SUSP and RR records using the Rock Ridge protocol to further describe +the files on the ISO9660 filesystem. +.TP +.B \-r +This is like the \-R option, but file ownership and modes are set to +more useful values. The uid and gid are set to zero, because they are +usually only useful on the author's system, and not useful to the +client. All the file read bits are set true, so that files and +directories are globally readable on the client. If any execute bit is +set for a file, set all of the execute bits, so that executables are +globally executable on the client. If any search bit is set for a +directory, set all of the search bits, so that directories are globally +searchable on the client. All write bits are cleared, because the +filesystem will be mounted read-only in any case. If any of the special +mode bits are set, clear them, because file locks are not useful on a +read-only filesystem, and set-id bits are not desirable for uid 0 or +gid 0. +When used on Win32, the execute bit is set on +.I all +files. This is a result of the lack of file permissions on Win32 and the +Cygwin POSIX emulation layer. See also +.BR \-uid ", " \-gid , +.BR \-dir\-mode ", " \-file\-mode +and +.BR \-new\-dir\-mode . +.TP +.B \-relaxed\-filenames +Allows ISO9660 filenames to include all 7-bit ASCII characters except +lowercase letters. +.br +This violates the ISO9660 standard, but it happens to work on many systems. +Use with caution. +.TP +.BI \-root " dir" +Moves all files and directories into +.I dir +in the image. This is essentially the +same as using +.B \-graft\-points +and adding +.I dir +in front of every pathspec, but is easier to use. +.I dir +may actually be several levels deep. It is +created with the same permissions as other graft points. +.TP +.BI \-old-root " dir" +This option is necessary when writing a multisession +image and the previous (or even older) session was written with +.B -root +.IR dir . +Using a directory name not found in the previous session +causes +.B genisoimage +to abort with an error. +Without this option, +.B genisoimage +would not be able to find unmodified files and would +be forced to write their data into the image once more. +.B \-root +and +.B \-old-root +are meant to be used together to do incremental backups. +The initial session would e.g. use: +.B genisoimage \-root backup_1 +.IR dirs . +The next incremental backup with +.B genisoimage \-root backup_2 \-old-root backup_1 +.I dirs +would take another snapshot of these directories. The first +snapshot would be found in +.BR backup_1 , +the second one in +.BR backup_2 , +but only modified or new files need to be written +into the second session. +Without these options, new files would be added and old ones would be +preserved. But old ones would be overwritten if the file was +modified. Recovering the files by copying the whole directory back +from CD would also restore files that were deleted +intentionally. Accessing several older versions of a file requires +support by the operating system to choose which sessions are to be +mounted. +.TP +.BI \-sort " sort_file" +Sort file locations on the media. Sorting is controlled by a file that +contains pairs of filenames and sorting offset weighting. +If the weighting is higher, the file will be located closer to the +beginning of the media, if the weighting is lower, the file will be located +closer to the end of the media. There must be only one space or tabs +character between the filename and the +weight and the weight must be the last characters on a line. The filename +is taken to include all the characters up to, but not including the last +space or tab character on a line. This is to allow for space characters to +be in, or at the end of a filename. +This option does +.B not +sort the order of the filenames that appear +in the ISO9660 directory. It sorts the order in which the file data is +written to the CD image, which is useful in order to optimize the +data layout on a CD. See +.B README.sort +for more details. +.TP +.BI \-sparc\-boot " img_sun4,img_sun4c,img_sun4m,img_sun4d,img_sun4e" +See +.B \-B +above. +.TP +.BI \-sparc\-label " label" +Set the Sun disk label name for the Sun disk label that is created with +.BR \-sparc-boot . +.TP +.B \-split\-output +Split the output image into several files of approximately 1 GB each. +This helps to create DVD-sized ISO9660 images on operating systems without +large file support. +.B wodim +will concatenate more than one file into a single track if writing to a DVD. +To make +.B \-split\-output +work, +.BI \-o " filename" +must be specified. The resulting output images will be named: +.IR filename_00 ", " filename_01 ", " filename_02 .... +.TP +.BI \-stream\-media\-size " #" +Select streaming operation and set the media size to # sectors. +This allows you to pipe the output of the +.BR tar (1) +program into +.B genisoimage +and to create an ISO9660 filesystem without the need of an intermediate +tar archive file. +If this option has been specified, +.B genisoimage +reads from +.I stdin +and creates a file with the name +.IR STREAM.IMG . +The maximum size of the file (with padding) is 200 sectors less than the +specified media size. If +.B \-no\-pad +has been specified, the file size is 50 sectors less than the specified media size. +If the file is smaller, +.B genisoimage +will write padding. This may take awhile. +.IP +The option +.B \-stream\-media\-size +creates simple ISO9660 filesystems only and may not used together with multisession +or hybrid filesystem options. +.TP +.BI \-stream\-file\-name " name" +Reserved for future use. +.TP +.BI \-sunx86\-boot " UFS_img,,,AUX1_img" +Specifies a comma-separated list of filesystem images that are needed to make +a bootable CD for Solaris x86 systems. +.IP +Note that partition 1 is used for the ISO9660 image and that partition 2 is +the whole disk, so partition 1 and 2 may not be used by external partition data. +The first image file is mapped to partition 0. +There may be empty fields in the comma-separated list, +and list entries for partition 1 and 2 must be empty. +The maximum number of supported partitions is 8 (although the Solaris x86 +partition table could support up to 16 partitions), so it is impossible +to specify more than 6 partition images. +This option is required to make a bootable CD for Solaris x86 systems. +.IP +If +.B \-sunx86\-boot +has been specified, the first sector of the resulting image will +contain a PC fdisk label with a Solaris type 0x82 fdisk partition that +starts at offset 512 and spans the whole CD. +In addition, for the Solaris type 0x82 fdisk partition, there is a +SVr4 disk label at offset 1024 in the first sector of the CD. +This disk label specifies slice 0 for the first (usually UFS type) +filesystem image that is used to boot the PC and slice 1 for +the ISO9660 image. +Slice 2 spans the whole CD slice 3 .\|.\|. slice 7 may be used for additional +filesystem images that have been specified with this option. +.IP +A Solaris x86 boot CD uses a 1024 byte sized primary boot that uses the +.B El-Torito no-emulation +boot mode and a secondary generic boot that is in CD sectors 1\|.\|.15. +For this reason, both +.BI "-b " bootimage " \-no\-emul\-boot" +and +.BI \-G " genboot" +must be specified. +.TP +.BI \-sunx86\-label " label" +Set the SVr4 disk label name for the SVr4 disk label that is created with +.BR \-sunx86-boot . +.TP +.BI \-sysid " ID" +Specifies the system ID. There is space for 32 characters. +Equivalent to +.B SYSI +in the +.I .genisoimagerc +file. +.TP +.B \-T +Generate a file +.I TRANS.TBL +in each directory on the CD-ROM, which can be used +on non-Rock\ Ridge-capable systems to help establish the correct filenames. +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 +.BI \-table\-name " table_name" +Alternative translation table filename (see above). Implies +.BR \-T . +If you are creating a multisession image you must use the same name +as in the previous session. +.TP +.BI \-ucs\-level " level" +Set Unicode conformance level in the Joliet SVD. The default level is 3. +It may be set to 1..3 using this option. +.TP +.B \-udf +Include UDF filesystem support in the generated filesystem image. UDF +support is currently in alpha status and for this reason, it is not +possible to create UDF-only images. UDF data structures are currently +coupled to the Joliet structures, so there are many pitfalls with the +current implementation. There is no UID/GID support, there is no POSIX +permission support, there is no support for symlinks. Note that UDF +wastes the space from sector ~20 to sector 256 at the beginning of the +disc in addition to the space needed for real UDF data structures. +.TP +.BI \-uid " uid" +Overrides the uid read from the source files to the value of +.IR uid . +Specifying this option automatically enables Rock Ridge extensions. +.TP +.B \-use\-fileversion +The option +.B \-use\-fileversion +allows +.B genisoimage +to use file version numbers from the filesystem. +If the option is not specified, +.B genisoimage +creates a version number of 1 for all files. +File versions are strings in the range +.I ;1 +to +.I ;32767 +This option is the default on VMS. +.TP +.B \-U +Allows "untranslated" filenames, completely violating the ISO9660 standards +described above. Enables the following flags: +.B \-d \-l \-N \-allow\-leading\-dots \-relaxed\-filenames +.BR "\-allow\-lowercase \-allow\-multidot \-no\-iso\-translate" . +Allows more than one `.' character in the filename, as well as +mixed-case filenames. This is useful on HP-UX, where the built-in +.I cdfs +filesystem does not recognize any extensions. Use with extreme caution. +.TP +.B \-no\-iso\-translate +Do not translate the characters `#' and `~' which are invalid for ISO9660 filenames. +Although invalid, these characters are often used by Microsoft systems. +.br +This violates the ISO9660 standard, but it happens to work on many systems. +Use with caution. +.TP +.BI \-V " volid" +Specifies the volume ID (volume name or label) to be written into the +master block. There is space for 32 characters. Equivalent to +.B VOLI +in the +.I .genisoimagerc +file. The volume ID is used as the mount point by the Solaris volume +manager and as a label assigned to a disc on various other platforms +such as Windows and Apple Mac OS. +.TP +.BI \-volset " ID" +Specifies the volume set ID. There is space for 128 characters. +Equivalent to +.B VOLS +in the +.I .genisoimagerc +file. +.TP +.BI \-volset\-size " #" +Sets the volume set size to #. +The volume set size is the number of CDs that are in a CD volume set. +A volume set is a collection of one or more volumes, on which a set of +files is recorded. +.IP +Volume Sets are not intended to be used to create a set numbered CDs +that are part of e.g. a Operation System installation set of CDs. +Volume Sets are rather used to record a big directory tree that would not +fit on a single volume. +Each volume of a Volume Set contains a description of all the directories +and files that are recorded on the volumes where the sequence numbers +are less than, or equal to, the assigned Volume Set Size of the current +volume. +.IP +.B genisoimage +currently does not support a +.B \-volset\-size +that is larger than 1. +.IP +The option +.B \-volset\-size +must be specified before +.B \-volset\-seqno +on each command line. +.TP +.BI \-volset\-seqno " #" +Sets the volume set sequence number to #. +The volume set sequence number is the index number of the current +CD in a CD set. +The option +.B \-volset\-size +must be specified before +.B \-volset\-seqno +on each command line. +.TP +.B \-v +Verbose execution. If given twice on the command line, extra debug information +will be printed. +.TP +.BI \-x " glob" +Identical to +.B \-m +.IR glob . +.TP +.B \-z +Generate special +.I RRIP +records for transparently compressed files. +This is only of use and interest for hosts that support transparent +decompression, such as Linux 2.4.14 or later. You must specify +.BR \-R " or " \-r +to enable Rock Ridge, and generate compressed files using the +.B mkzftree +utility before running +.BR genisoimage . +Note that transparent compression is a nonstandard Rock Ridge extension. +The resulting disks are only transparently readable if used on Linux. +On other operating systems you will need to call +.B mkzftree +by hand to decompress the files. +.\" ---------------------------------------- +.SH "HFS OPTIONS" +.TP +.B \-hfs +Create an ISO9660/HFS hybrid CD. This option should be used in conjunction +with the +.BR \-map , +.B \-magic +and/or the various +.I double dash +options given below. +.TP +.B \-apple +Create an ISO9660 CD with Apple's extensions. Similar to +.BR \-hfs , +except that the Apple Extensions to ISO9660 are added instead of +creating an HFS hybrid volume. +Former +.B genisoimage +versions did include Rock Ridge attributes by default if +.B \-apple +was specified. This versions of +.B genisoimage +does not do this anymore. If you like to have Rock Ridge attributes, +you need to specify this separately. +.TP +.BI \-map " mapping_file" +Use the +.I mapping_file +to set the CREATOR and TYPE information for a file based on the +filename's extension. A filename is +mapped only if it is not one of the know Apple/Unix file formats. See the +.B HFS CREATOR/TYPE +section below. +.TP +.BI \-magic " magic_file" +The CREATOR and TYPE information is set by using a file's +.I magic number +(usually the first few bytes of a file). The +.I magic_file +is only used if a file is not one of the known Apple/Unix file formats, or +the filename extension has not been mapped using +.BR \-map . +See the +.B HFS CREATOR/TYPE +section below for more details. +.TP +.BI \-hfs\-creator " creator" +Set the default CREATOR for all files. Must be exactly 4 characters. See the +.B HFS CREATOR/TYPE +section below for more details. +.TP +.BI \-hfs\-type " type" +Set the default TYPE for all files. Must be exactly 4 characters. See the +.B HFS CREATOR/TYPE +section below for more details. +.TP +.B \-probe +Search the contents of files for all the known Apple/Unix file formats. +See the +.B HFS MACINTOSH FILE FORMATS +section below for more about these formats. +However, the only way to check for +.I MacBinary +and +.I AppleSingle +files is to open and read them, so this option may +increase processing time. It is better to use one or more +.I double dash +options given below if the Apple/Unix formats in use are known. +.TP +.B \-no\-desktop +Do not create (empty) Desktop files. New HFS Desktop files will be created +when the CD is used on a Macintosh (and stored in the System Folder). +By default, empty Desktop files are added to the HFS volume. +.TP +.B \-mac\-name +Use the HFS filename as the starting point for the ISO9660, Joliet and +Rock Ridge filenames. See the +.B HFS MACINTOSH FILENAMES +section below for more information. +.TP +.BI \-boot\-hfs\-file " driver_file" +Installs the +.I driver_file +that +.I may +make the CD bootable on a Macintosh. See the +.B HFS BOOT DRIVER +section below. (Alpha). +.TP +.B \-part +Generate an HFS partition table. By default, no partition table is generated, +but some older Macintosh CD-ROM drivers need an HFS partition table on the +CD-ROM to be able to recognize a hybrid CD-ROM. +.TP +.BI \-auto " AutoStart_file" +Make the HFS CD use the QuickTime 2.0 Autostart feature to launch an +application or document. The given filename must be the name of a document or +application located at the top level of the CD. The filename must be less +than 12 characters. (Alpha). +.TP +.BI \-cluster\-size " size" +Set the size in bytes of the cluster or allocation units of PC Exchange +files. Implies +.BR \-\-exchange . +See the +.B HFS MACINTOSH FILE FORMATS +section below. +.TP +.BI \-hide\-hfs " glob" +Hide +.IR glob , +a shell wildcard pattern, from the HFS volume. The file or directory +will still exist in the ISO9660 and/or Joliet directory. +.I glob +may match any part of the filename. Multiple globs may be excluded. +Example: +.sp + genisoimage \-o rom \-hfs \-hide\-hfs \(aq*.o\(aq \-hide\-hfs foobar +.sp +would exclude all files ending in `.o' or called +.I foobar +from the HFS volume. Note that if you had a directory called +.IR foobar , +it too (and of course all its descendants) would be excluded. The +.I glob +can also be a path name relative to the source directories given on the +command line. Example: +.sp + genisoimage \-o rom \-hfs \-hide\-hfs src/html src +.sp +would exclude just the file or directory called +.I html +from the +.I src +directory. Any other file or directory called +.I html +in the tree will not be excluded. Should be used with +.B \-hide +and/or +.BR \-hide\-joliet . +In order to match a directory name, make sure the pattern does not +include a trailing `/' character. See +.I README.hide +for more details. +.TP +.BI \-hide\-hfs\-list " file" +Specify a file containing a list of wildcard patterns to be hidden as in +.BR \-hide\-hfs . +.TP +.BI \-hfs\-volid " hfs_volid" +Volume name for the HFS partition. This is the name that is +assigned to the disc on a Macintosh and replaces the +.I volid +used with +.BR \-V . +.TP +.B \-icon\-position +Use the icon position information, if it exists, from the Apple/Unix file. +The icons will appear in the same position as they would on a Macintosh +desktop. Folder location and size on screen, its scroll positions, folder +View (view as Icons, Small Icons, etc.) are also preserved. +.\" This option may become set by default in the future. +(Alpha). +.TP +.BI \-root\-info " file" +Set the location, size on screen, scroll positions, folder View etc. for the +root folder of an HFS volume. See +.I README.rootinfo +for more information. (Alpha) +.TP +.BI \-prep\-boot " file" +PReP boot image file. Up to 4 are allowed. See +.I README.prep_boot +for more information. (Alpha) +.TP +.BI \-chrp\-boot +Add CHRP boot header. +.TP +.BI \-input\-hfs\-charset " charset" +Input charset that defines the characters used in HFS filenames when +used with +.BR \-mac\-name . +The default charset is +.I cp10000 +(Mac Roman). See the +.B CHARACTER SETS +and +.B HFS MACINTOSH FILENAMES +sections below for more details. +.TP +.BI \-output\-hfs\-charset " charset" +Output charset that defines the characters that will be used in the HFS +filenames. Defaults to the input charset. See the +.B CHARACTER SETS +section below for more details. +.TP +.B \-hfs\-unlock +By default, +.B genisoimage +will create an HFS volume that is locked. +This option leaves the volume unlocked so that other applications (e.g. +.BR hfsutils ) +can modify the volume. See the +.B HFS PROBLEMS/LIMITATIONS +section below for warnings about using this option. +.TP +.BI \-hfs\-bless " folder_name" +"Bless" the given directory (folder). This is usually the +.I System Folder +and is used in creating HFS bootable CDs. The name of the directory must +be the whole path name as +.B genisoimage +sees it. E.g., if the given pathspec is +.I ./cddata +and the required folder is called +.IR "System Folder" , +the whole path name is +.I \(dq/cddata/System Folder\(dq +(remember to use quotes if the name contains spaces). +.TP +.BI \-hfs\-parms " parameters" +Override certain parameters used to create the HFS filesystem. Unlikely to +be used in normal circumstances. See the +.I libhfs_iso/hybrid.h +source file for details. +.TP +.B \-\-cap +Look for AUFS CAP Macintosh files. Search for CAP Apple/Unix file formats +only. Searching for the other possible Apple/Unix file formats is disabled, +unless other +.I double dash +options are given. +.TP +.B \-\-netatalk +Look for NETATALK Macintosh files +.TP +.B \-\-double +Look for AppleDouble Macintosh files +.TP +.B \-\-ethershare +Look for Helios EtherShare Macintosh files +.TP +.B \-\-ushare +Look for IPT UShare Macintosh files +.TP +.B \-\-exchange +Look for PC Exchange Macintosh files +.TP +.B \-\-sgi +Look for SGI Macintosh files +.TP +.B \-\-xinet +Look for XINET Macintosh files +.TP +.B \-\-macbin +Look for MacBinary Macintosh files +.TP +.B \-\-single +Look for AppleSingle Macintosh files +.TP +.B \-\-dave +Look for Thursby Software Systems DAVE Macintosh files +.TP +.B \-\-sfm +Look for Microsoft's Services for Macintosh files (NT only) (Alpha) +.TP +.B \-\-osx\-double +Look for Mac OS X AppleDouble Macintosh files +.TP +.B \-\-osx\-hfs +Look for Mac OS X HFS Macintosh files +.\" ---------------------------------------- +.SH "CHARACTER SETS" +.B genisoimage +processes filenames in a POSIX-compliant way as strings of 8-bit characters. +To represent all codings for all languages, 8-bit characters are not +sufficient. Unicode or ISO-10646 +define character codings that need at least 21 bits to represent all +known languages. They may be represented with +.IR UTF-32 ", " UTF-16 " or " UTF-8 +coding. UTF-32 uses a plain 32-bit coding but seems to be uncommon. +UTF-16 is used by Microsoft with Win32 with the disadvantage that +16-bit characters are not compliant with the POSIX filesystem +interface. +.PP +Modern Unix operating systems may use UTF-8 coding for filenames. +Each 32-bit character is represented by one or more 8-bit characters. +If a character is coded in +.I ISO-8859-1 +(used in Central Europe and North America) is maps 1:1 to a +UTF-32 or UTF-16 coded Unicode character. +If a character is coded in +.I 7-Bit ASCII +(used in USA and other countries with limited character set) +is maps 1:1 to a UTF-32, UTF-16 or UTF-8 coded Unicode character. +Character codes that cannot be represented as a single byte in UTF-8 +(if the value is > 0x7F) use escape sequences that map to more than +one 8-bit character. +.PP +If all operating systems used UTF-8, +.B genisoimage +would not need to recode characters in filenames. +Unfortunately, Apple uses completely nonstandard codings and Microsoft +uses a Unicode coding that is not compatible with the POSIX filename +interface. +.PP +For all non-UTF-8-coded operating systems, the actual character +that each byte represents depends on the +.I character set +or +.I codepage +(the name used by Microsoft) +used by the local operating system \(em the characters in a character +set will reflect the region or natural language set by the user. +.PP +Usually character codes 0x00-0x1f are control characters, codes 0x20-0x7f +are the 7-bit ASCII characters and (on PCs and Macs) 0x80-0xff are used +for other characters. +.PP +As there are a lot more than 256 characters/symbols in use, only a small +subset are represented in a character set. Therefore the same character code +may represent a different character in different character sets. So a filename +generated, say in central Europe, may not display the same character +when viewed on a machine in, say eastern Europe. +.PP +To make matters more complicated, different operating systems use +different character sets for the region or language. For example, the +character code for `\('e' (small e with acute accent) +may be character code 0x82 on a PC, +code 0x8e on a Macintosh, code 0xe9 on a Unix system in western Europe, +and code 0x000e9 in Unicode. +.PP +As long as not all operating systems and applications use the same +character set as the basis for filenames, it may be +necessary to specify which character set your filenames use in and which +character set the filenames should appear on the CD. +.PP +There are four options to specify the character sets you want to use: +.TP +.B \-input\-charset +Defines the local character set you are using on your host machine. +Any character set conversions that take place will use this character +set as the starting point. The default input character sets are +.I cp437 +on MS-DOS-based systems and +.I iso8859-1 +on all other systems. If +.B \-J +is given, the Unicode equivalents of the input character set +will be used in the Joliet directory. +.B \-jcharset +is the same as +.BR "\-input\-charset \-J" . +.TP +.B \-output\-charset +Defines the character set that will be used with for the Rock Ridge names +on the CD. Defaults to the input character set. +.TP +.B \-input\-hfs\-charset +Defines the HFS character set used for HFS filenames decoded from +any of the various Apple/Unix file formats. Only useful when used with +.BR \-mac\-name . +See the +.B HFS MACINTOSH FILENAMES +for more information. Defaults to +.I cp10000 +(Mac Roman). +.TP +.B \-output\-hfs\-charset +Defines the HFS character set used to create HFS filenames from the input +character set in use. In most cases this will be from the character set +given with +.BR \-input\-charset . +Defaults to the input HFS character set. +.PP +There are a number of character sets built in to +.BR genisoimage . +To get a listing, use +.BR "\-input\-charset help" . +This list doesn't include the charset derived from the current locale, +if +.B genisoimage +is built with +.I iconv +support. +.PP +Additional character sets can be read from file for any of the character +set options by giving a filename as the argument to the options. The given +file will only be read if its name does not match one of the built-in +character sets. +.PP +The format of the character set files is the same as the mapping files +available from +.IR http://www.unicode.org/Public/MAPPINGS . +This format is: +.IP +Column #1 is the input byte code (in hex as 0xXX) +.br +Column #2 is the Unicode (in hex as 0xXXXX) +.br +The rest of the line is ignored. +.PP +Any blank line, line without two (or more) columns in the above format +or comments lines (starting with the # character) are ignored without any +warnings. Any missing input code is mapped to Unicode character 0x0000. +.PP +Note that, while UTF-8 is supported, other Unicode encodings such as +UCS-2/UTF-16 and UCS-4/UTF-32 are not, as POSIX operating systems +cannot handle them natively. +.PP +A 1:1 character set mapping can be defined by using the keyword +.I default +as the argument to any of the character set options. This is the behaviour +of old versions of +.BR mkisofs . +.PP +The ISO9660 filenames generated from the input filenames are not converted +from the input character set. The ISO9660 character set is a very limited +subset of the ASCII characters, so any conversion would be pointless. +.PP +Any character that +.B genisoimage +cannot convert will be replaced with a `_' character. +.\" ---------------------------------------- +.SH "HFS CREATOR/TYPE" +A Macintosh file has two properties associated with it which define +which application created the file, the +.I CREATOR +and what data the file contains, the +.IR TYPE . +Both are (exactly) 4 letter strings. Usually this +allows a Macintosh user to double-click on a file and launch the correct +application etc. The CREATOR and TYPE of a particular file can be found by +using something like ResEdit (or similar) on a Macintosh. +.PP +The CREATOR and TYPE information is stored in all the various Apple/Unix +encoded files. +For other files it is possible to base the CREATOR and TYPE on the +filename's extension using a +.I mapping +file (with +.BR \-map ) +and/or using the +.I magic number +(usually a +.I signature +in the first few bytes) of a file (with +.BR \-magic ). +If both these options are given, their order on the command +line is significant. If +.B \-map +is given first, a filename extension match is attempted +before a magic number match. However, if +.B \-magic +is given first, a magic number match is attempted before a +filename extension match. +.PP +If a mapping or magic file is not used, or no match is found, the default +CREATOR and TYPE for all regular files can be set by using entries in the +.I .genisoimagerc +file or using +.B \-hfs\-creator +and/or +.BR \-hfs\-type , +otherwise the default CREATOR and TYPE are +.IR Unix " and " TEXT . +.PP +The format of the +.I mapping +file is the same +.I afpfile +format as used by +.BR aufs . +This file has five columns for the +.IR extension , +.IR "file translation" , +.IR CREATOR , +.IR TYPE " and" +.IR Comment . +Lines starting with the `#' character are +comment lines and are ignored. An example file would be like: +.PP +.TS +tab (/); +l s s s s +l s s s s +l l l l l . +# Example filename mapping file +# +# EXTN/XLate/CREATOR/TYPE/Comment +\&.tif/Raw/\(aq8BIM\(aq/\(aqTIFF\(aq/\(dqPhotoshop TIFF image\(dq +\&.hqx/Ascii/\(aqBnHq\(aq/\(aqTEXT\(aq/\(dqBinHex file\(dq +\&.doc/Raw/\(aqMSWD\(aq/\(aqWDBN\(aq/\(dqWord file\(dq +\&.mov/Raw/\(aqTVOD\(aq/\(aqMooV\(aq/\(dqQuickTime Movie\(dq +*/Ascii/\(aqttxt\(aq/\(aqTEXT\(aq/\(dqText file\(dq +.TE +.PP +Where: +.IP +The first column +.I EXTN +defines the Unix filename extension to be +mapped. The default mapping for any filename extension that doesn't +match is defined with the `*' character. +.IP +The +.I Xlate +column defines the type of text translation between the Unix and +Macintosh file it is ignored by +.BR genisoimage , +but is kept to be compatible with +.BR aufs (1). +Although +.B genisoimage +does not alter the contents of a file, if a binary file has its TYPE +set as +.IR TEXT ", it " may +be read incorrectly on a Macintosh. Therefore a better choice for the +default TYPE may be +.IR ???? . +.IP +The +.I CREATOR +and +.I TYPE +keywords must be 4 characters long and enclosed in single quotes. +.IP +The comment field is enclosed in double quotes \(em it is ignored by +.BR genisoimage , +but is kept to be compatible with +.BR aufs . +.PP +The format of the +.I magic +file is almost identical to the +.BR magic (5) +file used by the +.BR file (1) +command. +.PP +This file has four tab-separated columns for the +.IR "byte offset" , +.IR type , +.I test +and +.IR message . +Lines starting with the `#' character are +comment lines and are ignored. An example file would be like: +.PP +.TS +tab (/); +l s s s +l s s s +l l l l . +# Example magic file +# +# off/type/test/message +0/string/GIF8/8BIM GIFf GIF image +0/beshort/0xffd8/8BIM JPEG image data +0/string/SIT!/SIT! SIT! StuffIt Archive +0/string/\(rs037\(rs235/LZIV ZIVU standard Unix compress +0/string/\(rs037\(rs213/GNUz ZIVU gzip compressed data +0/string/%!/ASPS TEXT Postscript +0/string/\(rs004%!/ASPS TEXT PC Postscript with a ^D to start +4/string/moov/txtt MooV QuickTime movie file (moov) +4/string/mdat/txtt MooV QuickTime movie file (mdat) +.TE +.PP +The format of the file is described in +.BR magic (5). +The only difference here is that for each entry in the magic file, the +.I message +for the initial offset must be be 4 characters for the CREATOR followed +by 4 characters for the TYPE \(em white space is +optional between them. Any other characters on this line are ignored. +Continuation lines (starting with a `>') are also ignored, i.e., only +the initial offset lines are used. +.PP +Using +.B \-magic +may significantly increase processing time as each file has to opened +and read to find its magic number. +.PP +In summary, for all files, the default CREATOR is +.I Unix +and the default TYPE is +.IR TEXT . +These can be changed by using entries in the +.I .genisoimagerc +file or by using +.B \-hfs\-creator +and/or +.BR \-hfs\-type . +.PP +If the a file is in one of the known Apple/Unix formats (and the format +has been selected), the CREATOR and TYPE are taken from the values +stored in the Apple/Unix file. +.PP +Other files can have their CREATOR and TYPE set from their filename +extension (with +.BR \-map ), +or their magic number (with +.BR \-magic ). +If the default match is used in the +.I mapping +file, these values override the default CREATOR and TYPE. +.PP +A full CREATOR/TYPE database can be found at +.IR http://www.angelfire.com/il/szekely/ . +.\" ---------------------------------------- +.SH "HFS MACINTOSH FILE FORMATS" +Macintosh files have two parts called the +.I Data +and +.IR "Resource fork" . +Either may be empty. Unix (and many other OSs) can only +cope with files having one part (or fork). To add to this, Macintosh files +have a number of attributes associated with them \(em probably the most +important are the TYPE and CREATOR. Again, Unix has no concept of these +types of attributes. +.PP +E.g., a Macintosh file may be a JPEG image where the image is stored in the +Data fork and a desktop thumbnail stored in the Resource fork. It is usually +the information in the data fork that is useful across platforms. +.PP +Therefore to store a Macintosh file on a Unix filesystem, a way has to be +found to cope with the two forks and the extra attributes (which are +referred to as the +.IR "Finder info" ). +Unfortunately, it seems that every software package that stores Macintosh +files on Unix has chosen a completely different storage method. +.PP +The Apple/Unix formats that +.B genisoimage +(partially) supports are: +.IP "CAP AUFS format" +Data fork stored in a file. Resource fork in subdirectory +.I .resource +with same filename as data fork. Finder info in subdirectory +.I .finderinfo +with same filename. +.IP "AppleDouble/Netatalk" +Data fork stored in a file. Resource fork stored in a file with +same name prefixed with `%'. Finder info also stored in same +`%' file. Netatalk uses the same format, but the resource +fork/Finder info stored in subdirectory +.I .AppleDouble +with same filename as data fork. +.IP AppleSingle +Data structures similar to above, except both forks and Finder +info are stored in one file. +.IP "Helios EtherShare" +Data fork stored in a file. Resource fork and Finder info together in +subdirectory +.I .rsrc +with same filename as data fork. +.IP "IPT UShare" +Like the EtherShare format, but the Finder info +is stored slightly differently. +.IP MacBinary +Both forks and Finder info stored in one file. +.IP "Apple PC Exchange" +Used by Macintoshes to store Apple files on DOS (FAT) disks. +Data fork stored in a file. Resource fork in subdirectory +.IR resource.frk " (or " RESOURCE.FRK ). +Finder info as one record in file +.IR finder.dat " (or " FINDER.DAT ). +Separate +.I finder.dat +for each data fork directory. +.IP +Note: +.B genisoimage +needs to know the native FAT cluster size of the disk that the PC Exchange +files are on (or have been copied from). This size is given by +.BR \-cluster\-size . +The cluster or allocation size can be found by using the DOS utility +.BR chkdsk . +.IP +May not work with PC Exchange v2.2 or higher files (available with MacOS 8.1). +DOS media containing PC Exchange files should be mounted as type +.I msdos +(not +.IR vfat ) +when using Linux. +.IP SGI/XINET +Used by SGI machines when they mount HFS disks. Data fork stored +in a file. Resource fork in subdirectory +.I .HSResource +with same filename. Finder info as one record in file +.IR .HSancillary ". Separate " .HSancillary +for each data fork directory. +.IP "Thursby Software Systems DAVE" +Allows Macintoshes to store Apple files on SMB servers. +Data fork stored in a file. Resource fork in subdirectory +.IR resource.frk . +Uses the AppleDouble format to store resource fork. +.IP "Services for Macintosh" +Format of files stored by NT Servers on NTFS filesystems. Data fork is +stored as +.IR filename . +Resource fork stored as a NTFS stream called +.IR filename:AFP_Resource . +The Finder info is stored as a NTFS stream called +.IR filename:Afp_AfpInfo . +NTFS streams are normally invisible to the user. +.IP +Warning: +.B genisoimage +only partially supports the SFM format. If an HFS file +or folder stored on the NT server contains an illegal +NT character in its name, NT converts these characters to +.I Private Use Unicode +characters. The characters are: \(dq * / < > ? \(rs | and a space or +period if it is the last character of the filename, character codes 0x01 +to 0x1f (control characters) and Apple's apple logo. +.IP +Unfortunately, these private Unicode characters are not readable by the +.B genisoimage +NT executable. Therefore any file or directory +name containing these characters will be ignored \(em including the contents of +any such directory. +.IP "Mac OS X AppleDouble" +When HFS/HFS+ files are copied or saved by Mac OS X on to a non-HFS +filesystem (e.g. UFS, NFS etc.), the files are stored in AppleDouble format. +Data fork stored in a file. Resource fork stored in a file with +same name prefixed with `._'. Finder info also stored in same `._' file. +.IP "Mac OS X HFS (Alpha)" +Not really an Apple/Unix encoding, but actual HFS/HFS+ files on a Mac\ OS\ X +system. Data fork stored in a file. Resource fork stored in a pseudo file +with the same name with the suffix +.IR /rsrc . +The Finder info is only available via a Mac OS X library call. +.IP +See also +.IR README.macosx . +.IP +Only works when used on Mac OS X. +.IP +If a file is found with a zero +length resource fork and empty finderinfo, it is assumed not to have +any Apple/Unix encoding \(em therefore a TYPE and CREATOR can be set using +other methods. +.PP +.B genisoimage +will attempt to set the CREATOR, TYPE, date and possibly other flags from +the finder info. Additionally, if it exists, the Macintosh filename is set +from the finder info, otherwise the Macintosh name is based on the Unix +filename \(em see the +.B HFS MACINTOSH FILENAMES +section below. +.PP +When using +.BR \-apple , +the TYPE and CREATOR are stored in the optional System Use or +.I SUSP +field +in the ISO9660 Directory Record \(em in much the same way as the Rock Ridge +attributes are. In fact to make life easy, the Apple extensions are added +at the beginning of the existing Rock Ridge attributes (i.e., to get the Apple +extensions you get the Rock Ridge extensions as well). +.PP +The Apple extensions require the resource fork to be stored as an ISO9660 +.I associated +file. This is just like any normal file stored in the ISO9660 filesystem +except that the associated file flag is set in the Directory Record (bit +2). This file has the same name as the data fork (the file seen by +non-Apple machines). Associated files are normally ignored by other OSs +.PP +When using +.BR \-hfs , +the TYPE and CREATOR plus other finder info, are stored in a separate +HFS directory, not visible on the ISO9660 volume. The HFS directory references +the same data and resource fork files described above. +.PP +In most cases, it is better to use +.B \-hfs +instead of +.BR \-apple , +as the latter imposes the limited ISO9660 characters allowed in +filenames. However, the Apple extensions do give the advantage that the +files are packed on the disk more efficiently and it may be possible to fit +more files on a CD. +.\" ---------------------------------------- +.SH "HFS MACINTOSH FILENAMES" +Where possible, the HFS filename that is stored with an Apple/Unix file +is used for the HFS part of the CD. However, not all the Apple/Unix +encodings store the HFS filename with the finderinfo. In these cases, +the Unix filename is used \(em with escaped special characters. Special +characters include `/' and characters with codes over 127. +.PP +AUFS escapes these characters by using `:' followed by the character code +as two hex digits. Netatalk and EtherShare have a similar scheme, but uses +`%' instead of a `:'. +.PP +If +.B genisoimage +cannot find an HFS filename, it uses the Unix name, with any +.IR %xx " or " :xx +characters +.RI ( xx +are two hex digits) converted to a single character code. If +.I xx +are not hex digits ([0-9a-fA-F]), they are +left alone \(em although any remaining `:' is converted to `%', as `:' +is the HFS directory separator. Care must be taken, as an ordinary Unix +file with +.I %xx +or +.I :xx +will also be converted. e.g. +.PP +.TS +l l +l s +l l +l s +l l . +This:2fFile converted to This/File + +This:File converted to This%File + +This:t7File converted to This%t7File +.TE +.PP +Although HFS filenames appear to support uppercase and lowercase letters, +the filesystem is case-insensitive, i.e., the filenames +.IR aBc " and " AbC +are the same. If a file is found in a directory with the same HFS name, +.B genisoimage +will attempt to make a unique name by adding `_' characters +to one of the filenames. +.PP +If an HFS filename exists for a file, +.B genisoimage +can use this name as the starting point for the ISO9660, Joliet and +Rock Ridge filenames using +.BR \-mac\-name . +Normal Unix files without an HFS name will still use their Unix name. +e.g. +.PP +If a MacBinary (or PC Exchange) file is stored as +.I someimage.gif.bin +on the Unix filesystem, but contains a HFS file called +.IR someimage.gif , +this is the name that would appear on the HFS part of the CD. However, as +.B genisoimage +uses the Unix name as the starting point for the other names, +the ISO9660 name generated will probably be +.I SOMEIMAG.BIN +and the Joliet/Rock Ridge would be +.IR someimage.gif.bin . +This option will use +the HFS filename as the starting point and the ISO9660 name will probably be +.I SOMEIMAG.GIF +and the Joliet/Rock Ridge would be +.IR someimage.gif . +.PP +.B \-mac\-name +will not currently work with +.B \-T +\(em the Unix name will be used in the +.I TRANS.TBL +file, not the Macintosh name. +.PP +The character set used to convert any HFS filename to a Joliet/Rock Ridge +filename defaults to +.I cp10000 +(Mac Roman). +The character set used can be specified using +.BR \-input\-hfs\-charset . +Other built-in HFS character sets are: +.I cp10006 +(MacGreek), +.I cp10007 +(MacCyrillic), +.I cp10029 +(MacLatin2), +.I cp10079 +(MacIcelandandic) and +.I cp10081 +(MacTurkish). +.PP +Note: the character codes used by HFS filenames taken from the various +Apple/Unix formats will not be converted as they are assumed to be in the +correct Apple character set. Only the Joliet/Rock Ridge names derived from +the HFS filenames will be converted. +.PP +The existing +.B genisoimage +code will filter out any illegal characters for the ISO9660 and Joliet +filenames, but as +.B genisoimage +expects to be dealing directly with Unix names, it leaves the Rock +Ridge names as is. But as `/' is a legal HFS filename character, +.B \-mac\-name +converts `/' to a `_' in Rock Ridge filenames. +.PP +If the Apple extensions are used, only the ISO9660 filenames will +appear on the Macintosh. However, as the Macintosh ISO9660 drivers can use +.I Level 2 +filenames, you can use options like +.B \-allow\-multidot +without problems on +a Macintosh \(em still take care over the names, for example +.I this.file.name +will be converted to +.I THIS.FILE +i.e. only have one `.', also filename +.I abcdefgh +will be seen as +.I ABCDEFGH +but +.I abcdefghi +will be seen as +.I ABCDEFGHI. +i.e. with a `.' at the end \(em don't know if this is a Macintosh +problem or a +.BR genisoimage / mkhybrid +problem. All filenames will be in uppercase +when viewed on a Macintosh. Of course, DOS/Win3.X machines will not be able +to see Level 2 filenames... +.\" ---------------------------------------- +.SH "HFS CUSTOM VOLUME/FOLDER ICONS" +To give a HFS CD a custom icon, make sure the root (top level) folder includes +a standard Macintosh volume icon file. To give a volume a custom icon on +a Macintosh, an icon has to be pasted over the volume's icon in the "Get Info" +box of the volume. This creates an invisible file called +.I Icon\(rsr +(`\(rsr' is the carriage return character) in the root folder. +.P +A custom folder icon is very similar \(em an invisible file called +.I Icon\(rsr +exists in the folder itself. +.P +Probably the easiest way to create a custom icon that +.B genisoimage +can use is to format a blank HFS floppy disk on a Mac and paste an icon +to its "Get Info" box. If using Linux with the HFS module installed, +mount the floppy: +.IP +mount \-t hfs /dev/fd0 /mnt/floppy +.PP +The floppy will be mounted as a CAP filesystem by default. Then run +.B genisoimage +using something like: +.IP +genisoimage \-\-cap \-o output source_dir /mnt/floppy +.PP +If you are not using Linux, you can use +.B hfsutils +to copy the icon file from the floppy. However, care has to be taken, +as the icon file contains a control character. For example: +.IP +hmount /dev/fd0 +.br +hdir \-a +.br +hcopy \-m Icon^V^M icon_dir/icon +.PP +Where `^V^M' is control-V followed by control-M. Then run +.B genisoimage +by using something like: +.IP +genisoimage \-\-macbin \-o output source_dir icon_dir +.PP +The procedure for creating/using custom folder icons is very similar \(em paste +an icon to folder's "Get Info" box and transfer the resulting +.I Icon\(rsr +file to the relevant directory in the +.B genisoimage +source tree. +.PP +You may want to hide the icon files from the ISO9660 and Joliet trees. +.PP +To give a custom icon to a Joliet CD, follow the instructions found at +.IR http://www.cdrfaq.org/faq03.html#S3-21-1 . +.\" ---------------------------------------- +.SH "HFS BOOT DRIVER" +It +.I may +be possible to make the hybrid CD bootable on a Macintosh. +.PP +A bootable HFS CD requires an Apple CD-ROM (or compatible) driver, a bootable +HFS partition and the necessary System, Finder, etc. files. +.PP +A driver can be obtained from any other Macintosh bootable CD-ROM using the +.B apple_driver +utility. This file can then be used with +.BR \-boot\-hfs\-file . +.PP +The HFS partition (i.e. the hybrid disk in our case) must contain a +suitable System Folder, again from another CD-ROM or disk. +.PP +For a partition to be bootable, it must have its +.I boot block +set. The boot +block is in the first two blocks of a partition. For a non-bootable partition +the boot block is full of zeros. Normally, when a System file is copied to +partition on a Macintosh disk, the boot block is filled with a number of +required settings \(em unfortunately I don't know the full spec for the boot +block, so I'm guessing that the following will work. +.PP +Therefore, the utility +.B apple_driver +also extracts the boot block from the +first HFS partition it finds on the given CD-ROM and this is used for the +HFS partition created by +.BR genisoimage . +.PP +.I Please note: +By using a driver from an Apple CD and copying Apple software to your CD, +you become liable to obey Apple Computer, Inc. Software License Agreements. +.\" ---------------------------------------- +.SH "EL TORITO BOOT INFORMATION TABLE" +When +.B \-boot\-info\-table +is given, +.B genisoimage +will modify the boot file specified by +.B \-b +by inserting a 56-byte +.I boot information table +at offset 8 in +the file. This modification is done in the source filesystem, so make +sure you use a copy if this file is not easily recreated! This file +contains pointers which may not be easily or reliably obtained at boot +time. +.PP +The format of this table is as follows; all integers are in +section 7.3.1 ("little endian") format. +.sp +.RS +.2i +.ta 1.0i 2.5i 3.5i +.nf +Offset Name Size Meaning + 8 bi_pvd 4 bytes LBA of primary volume descriptor +12 bi_file 4 bytes LBA of boot file +16 bi_length 4 bytes Boot file length in bytes +20 bi_csum 4 bytes 32-bit checksum +24 bi_reserved 40 bytes Reserved +.fi +.RE +.IP +The 32-bit checksum is the sum of all the 32-bit words in the boot +file starting at byte offset 64. All linear block addresses (LBAs) +are given in CD sectors (normally 2048 bytes). +.\" ---------------------------------------- +.SH "HPPA NOTES" +To make a bootable CD for HPPA, at the very least a boot loader file +.RB ( \-hppa\-bootloader ), +a kernel image file (32-bit, 64-bit, or both, depending on hardware) +and a boot command line +.RB ( \-hppa\-cmdline ) +must be specified. Some systems can boot either a 32- or a 64-bit +kernel, and the firmware will choose one if both are present. +Optionally, a ramdisk can be used for the root filesystem using +.BR \-hppa\-cmdline . +.\" ---------------------------------------- +.SH "JIGDO NOTES" +Jigdo is a tool to help in the distribution of large files like CD and +DVD images; see +.I http://atterer.org/jigdo/ +for more details. Debian CDs and DVD ISO +images are published on the web in jigdo format to allow end users to download +them more efficiently. +.PP +To create jigdo and template files alongside the ISO image from +.BR genisoimage , +you must first generate a list of the files that will be +used, in the following format: +.sp +.RS +.2i +.ta 2.0i 2.0i 5.0i +.nf +MD5sum File size Path +32 chars 12 chars to end of line +.fi +.RE +.IP +.PP +The MD5sum must be written in standard hexadecimal notation, the +file size must list the size of the file in bytes, and the path +must list the absolute path to the file. For example: +.sp +.nf +00006dcd58ff0756c36d2efae21be376 14736 /mirror/debian/file1 +000635c69b254a1be8badcec3a8d05c1 211822 /mirror/debian/file2 +00083436a3899a09633fc1026ef1e66e 22762 /mirror/debian/file3 +.fi +.PP +Once you have this file, call +.B genisoimage +with all of your normal command-line parameters. Specify the output +filenames for the jigdo and template files using +.BR \-jigdo\-jigdo " and " \-jigdo\-template , +and pass in the location of your MD5 list with +.BR \-md5\-list . +.PP +If there are files that you do NOT want to be added into the jigdo +file (e.g. if they are likely to change often), specify them using +\-jigdo\-exclude. If you want to verify some of the files as they are +written into the image, specify them using \-jigdo\-force\-md5. If any +files don't match, +.B genisoimage +will then abort. Both of these options take +regular expressions as input. It is possible to restrict the set of +files that will be used further based on size \(em use the +\-jigdo\-min\-file\-size option. +.PP +Finally, the jigdo code needs to know how to map the files it is given +onto a mirror-style configuration. Specify how to map paths using +.BR \-jigdo\-map . +Using +.I Debian=/mirror/debian +will cause all +paths starting with +.I /mirror/debian +to be mapped to +.I Debian:<file> +in the output jigdo file. +.\" ---------------------------------------- +.SH EXAMPLES +.PP +To create a vanilla ISO9660 filesystem image in the file +.IR cd.iso , +where the directory +.I cd_dir +will become the root directory of the CD, call: +.IP +% genisoimage \-o cd.iso cd_dir +.PP +To create a CD with Rock Ridge extensions of +the source directory +.IR cd_dir : +.IP +% genisoimage \-o cd.iso \-R cd_dir +.PP +To create a CD with Rock Ridge extensions of +the source directory +.I cd_dir +where all files have at least read permission and all files +are owned by +.IR root , +call: +.IP +% genisoimage \-o cd.iso \-r cd_dir +.PP +To write a tar archive directly to a CD that will later contain a simple +ISO9660 filesystem with the tar archive call: +.IP +% tar cf \- . | genisoimage \-stream\-media\-size 333000 | \(rs +.br + wodim dev=b,t,l \-dao tsize=333000s \- +.PP +To create a HFS hybrid CD with the Joliet and Rock Ridge extensions of +the source directory +.IR cd_dir : +.IP +% genisoimage \-o cd.iso \-R \-J \-hfs cd_dir +.PP +To create a HFS hybrid CD from the source directory +.I cd_dir +that contains +Netatalk Apple/Unix files: +.IP +% genisoimage \-o cd.iso \-\-netatalk cd_dir +.PP +To create a HFS hybrid CD from the source directory +.IR cd_dir , +giving all files +CREATOR and TYPES based on just their filename extensions listed in the file +"mapping".: +.IP +% genisoimage \-o cd.iso \-map mapping cd_dir +.PP +To create a CD with the Apple Extensions to ISO9660, from the source +directories +.I cd_dir +and +.IR another_dir . +Files in all the known Apple/Unix format +are decoded and any other files are given CREATOR and TYPE based on their +magic number given in the file +.IR magic : +.IP +% genisoimage \-o cd.iso \-apple \-magic magic \-probe \(rs +.br + cd_dir another_dir +.PP +The following example puts different files on the CD that all have +the name README, but have different contents when seen as a +ISO9660/Rock Ridge, Joliet or HFS CD. +.PP +Current directory contains: +.IP +% ls \-F +.br +README.hfs README.joliet README.Unix cd_dir/ +.PP +The following command puts the contents of the directory +.I cd_dir +on the +CD along with the three README files \(em but only one will be seen from +each of the three filesystems: +.IP +% genisoimage \-o cd.iso \-hfs \-J \-r \-graft\-points \(rs +.br + \-hide README.hfs \-hide README.joliet \(rs +.br + \-hide\-joliet README.hfs \-hide\-joliet README.Unix \(rs +.br + \-hide\-hfs README.joliet \-hide\-hfs README.Unix \(rs +.br + README=README.hfs README=README.joliet \(rs +.br + README=README.Unix cd_dir +.PP +i.e. the file README.hfs will be seen as README on the HFS CD and the +other two README files will be hidden. Similarly for the Joliet and +ISO9660/Rock Ridge CD. +.PP +There are probably all sorts of strange results possible with +combinations of the hide options ... +.\" ---------------------------------------- +.SH NOTES +.PP +.B genisoimage +may safely be installed suid root. This may be needed to allow +.B genisoimage +to read the previous session when creating a multisession image. +.PP +If +.B genisoimage +is creating a filesystem image with Rock Ridge attributes and the +directory nesting level of the source directory tree is too much +for ISO9660, +.B genisoimage +will do deep directory relocation. +This results in a directory called +.B RR_MOVED +in the root directory of the CD. You cannot avoid this directory. +.PP +Many boot code options for different platforms are mutualy exclusive because +the boot blocks cannot coexist, ie. different platforms share the same data +locations in the image. See +http://lists.debian.org/debian-cd/2006/12/msg00109.html for details. +.\" ---------------------------------------- +.SH BUGS +.PP +Any files that have hard links to files not in the tree being copied to the +ISO9660 filesystem will have an incorrect file reference count. +.PP +Does not check for SUSP record(s) in `.' entry of the +root directory to verify the existence of Rock Ridge +enhancements. +This problem is present when reading old sessions while +adding data in multisession mode. +.PP +Does not properly read relocated directories in multisession +mode when adding data. +Any relocated deep directory is lost if the new session does not +include the deep directory. +.\" Repeat by: create first session with deep directory relocation +.\" then add new session with a single dir that differs from the +.\" old deep path. +.PP +Does not re-use +.I RR_MOVED +when doing multisession from +.IR TRANS.TBL . +.PP +Does not create whole_name entry for +.I RR_MOVED +in multisession mode. +.PP +There may be other bugs. Please, report them to the maintainers. +.\" ---------------------------------------- +.SH "HFS PROBLEMS/LIMITATIONS" +I have had to make several assumptions on how I expect the modified +libhfs routines to work, however there may be situations that either +I haven't thought of, or come across when these assumptions fail. +Therefore I can't guarantee that +.B genisoimage +will work as expected +(although I haven't had a major problem yet). Most of the HFS features work +fine, but some are not fully tested. These are marked as +.I Alpha +above. +.PP +Although HFS filenames appear to support uppercase and lowercase letters, +the filesystem is case-insensitive, i.e., the filenames +.IR aBc " and "AbC +are the same. If a file is found in a directory with the same HFS name, +.B genisoimage +will attempt to make a unique name by adding `_' characters +to one of the filenames. +.PP +HFS file/directory names that share the first 31 characters have +`_N' (a decimal number) substituted for the last few characters +to generate unique names. +.PP +Care must be taken when "grafting" Apple/Unix files or directories (see +above for the method and syntax involved). It is not possible to use a +new name for an Apple/Unix encoded file/directory. e.g. If a Apple/Unix +encoded file called +.I oldname +is to added to the CD, you cannot use the command line: +.IP +genisoimage \-o output.raw \-hfs \-graft\-points newname=oldname cd_dir +.PP +.B genisoimage +will be unable to decode +.IR oldname . +However, you can graft +Apple/Unix encoded files or directories as long as you do not attempt to +give them new names as above. +.PP +When creating an HFS volume with the multisession options, +.B \-M +and +.BR \-C , +only files in the last session will be in the HFS volume. i.e. +.B genisoimage +cannot +.I add +existing files from previous sessions to the HFS volume. +.PP +However, if each session is created with +.BR \-part , +each session will appear as +separate volumes when mounted on a Mac. In this case, it is worth using +.BR \-V " or " \-hfs\-volid +to give each session a unique volume name, +otherwise each "volume" will appear on the Desktop with the same name. +.PP +Symbolic links (as with all other non-regular files) are not added to +the HFS directory. +.PP +Hybrid volumes may be larger than pure ISO9660 volumes +containing the same data. In some cases (e.g. DVD sized volumes) the +difference can be significant. As an HFS volume gets bigger, so does the +allocation block size (the smallest amount of space a file can occupy). +For a 650MB CD, the allocation block is 10kB, for a 4.7GB DVD it will be +about 70kB. +.PP +The maximum number of files in an HFS volume is about 65500 \(em although +the real limit will be somewhat less than this. +.PP +The resulting hybrid volume can be accessed on a Unix machine by using +the hfsutils routines. However, no changes can be made to the volume as it +is set as +.B locked. +The option +.B \-hfs\-unlock +will create an output image that is unlocked \(em however no changes should be +made to the contents of the volume (unless you really know what you are +doing) as it's not a "real" HFS volume. +.PP +.B \-mac\-name +will not currently work with +.B \-T +\(em the Unix name will be used in the +.I TRANS.TBL +file, not the Macintosh name. +.PP +Although +.B genisoimage +does not alter the contents of a file, if a binary file has its TYPE +set as +.IR TEXT ", it " may +be read incorrectly on a Macintosh. Therefore a better choice for the +default TYPE may be +.IR ???? . +.PP +.B \-mac\-boot\-file +may not work at all... +.PP +May not work with PC Exchange v2.2 or higher files (available with MacOS 8.1). +DOS media containing PC Exchange files should be mounted as type +.B msdos +(not +.BR vfat ) +when using Linux. +.PP +The SFM format is only partially supported \(em see +.B HFS MACINTOSH FILE FORMATS +section above. +.PP +It is not possible to use +.BR \-sparc\-boot " or " \-generic\-boot " with" +.BR \-boot\-hfs\-file " or " \-prep\-boot . +.PP +.B genisoimage +should be able to create HFS hybrid images over 4Gb, although this has not +been fully tested. +.\" ---------------------------------------- +.SH "SEE ALSO" +.BR genisoimagerc (5), +.BR wodim (1), +.BR mkzftree (8), +.BR magic (5). +.\" ---------------------------------------- +.SH AUTHORS +.B genisoimage +is derived from +.B mkisofs +from the +.B cdrtools 2.01.01a08 +package from May 2006 (with few updates extracted from cdrtools 2.01.01a24 from +March 2007) from .IR http://cdrecord.berlios.de/ , +but is now part of the +.B cdrkit +suite, maintained by Joerg Jaspert, Eduard Bloch, Steve McIntyre, Peter +Samuelson, Christian Fromme, Ben Hutchings, and other contributors. +The maintainers can be contacted at +.IR debburn-devel@lists.alioth.debian.org , +or see the +.B cdrkit +project web site at +.IR http://www.cdrkit.org/ . +.PP +Eric Youngdale wrote the first versions (1993\(en1998) of +.BR mkisofs . +J\(:org Schilling wrote the SCSI transport library and its +interface, and has maintained +.B mkisofs +since 1999. James Pearson wrote the HFS hybrid code, using +.I libhfs +by Robert Leslie. Pearson, Schilling, Jungshik Shin and Jaakko +Heinonen contributed to the character set conversion code. The +.B cdrkit +maintainers have maintained +.B genisoimage +since 2006. +.PP +.nf +Copyright 1993-1998 by Yggdrasil Computing, Inc. +Copyright 1996-1997 by Robert Leslie +Copyright 1997-2001 by James Pearson +Copyright 1999-2006 by J\(:org Schilling +Copyright 2007 by J\(:org Schilling (originating few updates) +Copyright 2002-2003 by Jungshik Shin +Copyright 2003 by Jaakko Heinonen +Copyright 2006 by the Cdrkit maintainers +.fi +.PP +If you want to take part in the development of +.BR genisoimage , +you may join the +.B cdrkit +developer mailing list by following the instructions on +.IR http://alioth.debian.org/mail/?group_id=31006 . +The email address of the list is +.IR debburn-devel@lists.alioth.debian.org . +This is also the address for user support questions. Note that +.BR cdrkit " and " cdrtools +are not affiliated. +.PP +.\" ---------------------------------------- +.SH ACKNOWLEDGEMENTS +UNIX is a registered trademark of The Open Group in the US and other countries. diff --git a/genisoimage/genisoimage.c b/genisoimage/genisoimage.c new file mode 100644 index 0000000..46f0cb7 --- /dev/null +++ b/genisoimage/genisoimage.c @@ -0,0 +1,3831 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* + * + * Patched version with stuff from the Debian's cdrtools. + * Replaced various warnings/disclaimers with more simple ones. + * + * Eduard Bloch <blade@debian.org> +*/ +/* @(#)mkisofs.c 1.167 06/01/30 joerg */ +/* Parts from @(#)mkisofs.c 1.206 07/02/26 joerg */ +/* + * Program genisoimage.c - generate iso9660 filesystem based upon directory + * tree on hard disk. + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * Copyright (c) 1999,2000-2004 J. Schilling + * + * 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. + */ + +/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 22/2/2000 */ + +#include <mconfig.h> +#include "genisoimage.h" +#include <errno.h> +#include <timedefs.h> +#include <fctldefs.h> +#include <ctype.h> +#include "match.h" +#include "exclude.h" +#include <unls.h> /* For UNICODE translation */ +#include <schily.h> +#ifdef UDF +#include "udf.h" +#endif + +#ifdef NEED_O_BINARY +#include <io.h> /* for setmode() prototype */ +#endif + +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +#include "getopt.h" +extern int optind; +extern char *optarg; +#endif + +#ifdef VMS +#include "vms.h" +#endif + +#ifdef no_more_needed +#ifdef __NetBSD__ +#include <sys/resource.h> +#endif +#endif /* no_more_needed */ + +#ifdef USE_ICONV +#include <locale.h> +#include <langinfo.h> +#endif + +struct directory *root = NULL; +int path_ind; + +char version_string[] = "genisoimage " CDRKIT_VERSION; + +char *outfile; +FILE *discimage; +unsigned int next_extent = 0; +unsigned int last_extent = 0; +unsigned int session_start = 0; +unsigned int path_table_size = 0; +unsigned int path_table[4] = {0, }; +unsigned int path_blocks = 0; + + +unsigned int jpath_table_size = 0; +unsigned int jpath_table[4] = {0, }; +unsigned int jpath_blocks = 0; + +struct iso_directory_record root_record; +struct iso_directory_record jroot_record; + +char *extension_record = NULL; +int extension_record_extent = 0; +int extension_record_size = 0; + +/* These variables are associated with command line options */ +int check_oldnames = 0; +int check_session = 0; +int use_eltorito = 0; +int hard_disk_boot = 0; +int not_bootable = 0; +int no_emul_boot = 0; +int load_addr = 0; +int load_size = 0; +int boot_info_table = 0; +int use_alphaboot = 0; +int use_sparcboot = 0; +int use_hppaboot = 0; +int use_mipsboot = 0; +int use_mipselboot = 0; +int use_sunx86boot = 0; +int use_genboot = 0; +int use_RockRidge = 0; +int use_XA = 0; +int osecsize = 0; /* Output-sector size, 0 means default secsize 2048 */ +int use_Joliet = 0; +int jlen = JMAX; /* maximum Joliet file name length */ +int verbose = 1; +int debug = 0; +int gui = 0; +int all_files = 1; /* New default is to include all files */ +int follow_links = 0; +#ifdef IS_CYGWIN +int cache_inodes = 0; /* Do not cache inodes on Cygwin by default */ +#else +int cache_inodes = 1; /* Cache inodes if OS has unique inodes */ +#endif +int rationalize = 0; +int rationalize_uid = 0; +int rationalize_gid = 0; +int rationalize_filemode = 0; +int rationalize_dirmode = 0; +uid_t uid_to_use = 0; /* when rationalizing uid */ +gid_t gid_to_use = 0; /* when rationalizing gid */ +int filemode_to_use = 0; /* if non-zero, when rationalizing file mode */ +int dirmode_to_use = 0; /* if non-zero, when rationalizing dir mode */ +int new_dir_mode = 0555; +int generate_tables = 0; +int dopad = 1; /* Now default to do padding */ +int print_size = 0; +int split_output = 0; +char *icharset = NULL; /* input charset to convert to UNICODE */ +char *ocharset = NULL; /* output charset to convert from UNICODE */ +char *preparer = PREPARER_DEFAULT; +char *publisher = PUBLISHER_DEFAULT; +char *appid = APPID_DEFAULT; +char *copyright = COPYRIGHT_DEFAULT; +char *biblio = BIBLIO_DEFAULT; +char *abstract = ABSTRACT_DEFAULT; +char *volset_id = VOLSET_ID_DEFAULT; +char *volume_id = VOLUME_ID_DEFAULT; +char *system_id = SYSTEM_ID_DEFAULT; +char *boot_catalog = BOOT_CATALOG_DEFAULT; +char *boot_image = BOOT_IMAGE_DEFAULT; +char *genboot_image = BOOT_IMAGE_DEFAULT; +int ucs_level = 3; /* We now have Unicode tables so use level 3 */ +int volume_set_size = 1; +int volume_sequence_number = 1; + +struct eltorito_boot_entry_info *first_boot_entry = NULL; +struct eltorito_boot_entry_info *last_boot_entry = NULL; +struct eltorito_boot_entry_info *current_boot_entry = NULL; + +int use_graft_ptrs; /* Use graft points */ +int jhide_trans_tbl; /* Hide TRANS.TBL from Joliet tree */ +int hide_rr_moved; /* Name RR_MOVED .rr_moved in Rock Ridge tree */ +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 no_rr = 0; /* Do not use RR attributes from old session */ +int force_rr = 0; /* Force to use RR attributes from old session */ +Uint RR_relocation_depth = 6; /* Violates iso9660, but most systems work */ +int iso9660_level = 1; +int iso9660_namelen = LEN_ISONAME; /* 31 characters, may be set to 37 */ +int full_iso9660_filenames = 0; /* Full 31 character iso9660 filenames */ +int relaxed_filenames = 0; /* For Amiga. Disc will not work with DOS */ +int allow_lowercase = 0; /* Allow lower case letters */ +int allow_multidot = 0; /* Allow more than on dot in filename */ +int iso_translate = 1; /* 1 == enables '#', '-' and '~' removal */ +int allow_leading_dots = 0; /* DOS cannot read names with leading dots */ +int allow_limited_size = 0; /* Let the user to allow the trick explicitely */ +#ifdef VMS +int use_fileversion = 1; /* Use file version # from filesystem */ +#else +int use_fileversion = 0; /* Use file version # from filesystem */ +#endif +int split_SL_component = 1; /* circumvent a bug in the SunOS driver */ +int split_SL_field = 1; /* circumvent a bug in the SunOS */ +char *trans_tbl = "TRANS.TBL"; /* default name for translation table */ +int stream_media_size = 0; /* # of blocks on the media */ +char *stream_filename = NULL; /* Stream file, 0 to use default STREAM.IMG */ + +#ifdef APPLE_HYB +int apple_hyb = 0; /* create HFS hybrid flag */ +int apple_ext = 0; /* create HFS extensions flag */ +int apple_both = 0; /* common flag (for above) */ +int hfs_extra = 0; /* extra HFS blocks added to end of ISO vol */ +int use_mac_name = 0; /* use Mac name for ISO/Joliet/RR flag */ +hce_mem *hce; /* libhfs/genisoimage extras */ +char *hfs_boot_file = 0; /* name of HFS boot file */ +int gen_pt = 0; /* generate HFS partition table */ +char *autoname = 0; /* AutoStart filename */ +char *magic_filename = 0; /* name of magic file */ +int probe = 0; /* search files for HFS/Unix type */ +int nomacfiles = 0; /* don't look for Mac/Unix files */ +int hfs_select = 0; /* Mac/Unix types to select */ +int create_dt = 1; /* create the Desktp files */ +int afe_size = 0; /* Apple File Exchange block size */ +int hfs_last = MAG_LAST; /* process magic file after map file */ +char *deftype = APPLE_TYPE_DEFAULT; /* default Apple TYPE */ +char *defcreator = APPLE_CREATOR_DEFAULT; /* default Apple CREATOR */ +char *hfs_volume_id = NULL; /* HFS volume ID */ +int icon_pos = 0; /* Keep icon position */ +char *hfs_icharset = NULL; /* input HFS charset name */ +char *hfs_ocharset = NULL; /* output HFS charset name */ +int hfs_lock = 1; /* lock HFS volume (read-only) */ +char *hfs_bless = NULL; /* name of folder to 'bless' (System Folder) */ +char *hfs_parms = NULL; /* low level HFS parameters */ + +#ifdef PREP_BOOT +char *prep_boot_image[4]; +int use_prep_boot = 0; +int use_chrp_boot = 0; +#endif /* PREP_BOOT */ +#endif /* APPLE_HYB */ + +#ifdef UDF +int use_udf = 0; +#endif + +#ifdef DVD_VIDEO +int dvd_video = 0; +#endif + +#ifdef SORTING +int do_sort = 0; /* sort file data */ +#endif /* SORTING */ + +#ifdef USE_ICONV +int iconv_possible; +#endif + +struct unls_table *in_nls = NULL; /* input UNICODE conversion table */ +struct unls_table *out_nls = NULL; /* output UNICODE conversion table */ +#ifdef APPLE_HYB +struct unls_table *hfs_inls = NULL; /* input HFS UNICODE conversion table */ +struct unls_table *hfs_onls = NULL; /* output HFS UNICODE conversion table */ +#endif /* APPLE_HYB */ + +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}, +#ifdef APPLE_HYB + {"HFS_TYPE", &deftype}, + {"HFS_CREATOR", &defcreator}, +#endif /* APPLE_HYB */ + {NULL, NULL} +}; + +char *merge_warn_msg=0; /* use as pointer and boolean */ + +/* + * In case it isn't obvious, the option handling code was ripped off + * from GNU-ld. + */ +struct ld_option { + /* The long option information. */ + struct option opt; + /* The short option with the same meaning ('\0' if none). */ + char shortopt; + /* The name of the argument (NULL if none). */ + const char *arg; + /* + * The documentation string. If this is NULL, this is a synonym for + * the previous option. + */ + const char *doc; + enum { + /* Use one dash before long option name. */ + ONE_DASH, + /* Use two dashes before long option name. */ + TWO_DASHES, + /* Don't mention this option in --help output. */ + NO_HELP + } control; +}; + +/* + * Codes used for the long options with no short synonyms. Note that all these + * values must not be ASCII or EBCDIC. + */ +#define OPTION_HELP 1000 +#define OPTION_QUIET 1001 +#define OPTION_NOSPLIT_SL_COMPONENT 1002 +#define OPTION_NOSPLIT_SL_FIELD 1003 +#define OPTION_PRINT_SIZE 1004 +#define OPTION_SPLIT_OUTPUT 1005 +#define OPTION_ABSTRACT 1006 +#define OPTION_BIBLIO 1007 +#define OPTION_COPYRIGHT 1008 +#define OPTION_SYSID 1009 +#define OPTION_VOLSET 1010 +#define OPTION_VOLSET_SIZE 1011 +#define OPTION_VOLSET_SEQ_NUM 1012 +#define OPTION_I_HIDE 1013 +#define OPTION_J_HIDE 1014 +#define OPTION_LOG_FILE 1015 +#define OPTION_PVERSION 1016 +#define OPTION_NOBAK 1017 +#define OPTION_SPARCLABEL 1018 +#define OPTION_HARD_DISK_BOOT 1019 +#define OPTION_NO_EMUL_BOOT 1020 +#define OPTION_NO_BOOT 1021 +#define OPTION_BOOT_LOAD_ADDR 1022 +#define OPTION_BOOT_LOAD_SIZE 1023 +#define OPTION_BOOT_INFO_TABLE 1024 +#define OPTION_HIDE_TRANS_TBL 1025 +#define OPTION_HIDE_RR_MOVED 1026 +#define OPTION_GUI 1027 +#define OPTION_TRANS_TBL 1028 +#define OPTION_P_LIST 1029 +#define OPTION_I_LIST 1030 +#define OPTION_J_LIST 1031 +#define OPTION_X_LIST 1032 +#define OPTION_NO_RR 1033 +#define OPTION_JCHARSET 1034 +#define OPTION_PAD 1035 +#define OPTION_H_HIDE 1036 +#define OPTION_H_LIST 1037 +#define OPTION_CHECK_OLDNAMES 1038 + +#ifdef SORTING +#define OPTION_SORT 1039 +#endif /* SORTING */ +#define OPTION_UCS_LEVEL 1040 +#define OPTION_ISO_TRANSLATE 1041 +#define OPTION_ISO_LEVEL 1042 +#define OPTION_RELAXED_FILENAMES 1043 +#define OPTION_ALLOW_LOWERCASE 1044 +#define OPTION_ALLOW_MULTIDOT 1045 +#define OPTION_USE_FILEVERSION 1046 +#define OPTION_MAX_FILENAMES 1047 +#define OPTION_ALT_BOOT 1048 +#define OPTION_USE_GRAFT 1049 + +#define OPTION_INPUT_CHARSET 1050 +#define OPTION_OUTPUT_CHARSET 1051 + +#define OPTION_NOPAD 1052 +#define OPTION_UID 1053 +#define OPTION_GID 1054 +#define OPTION_FILEMODE 1055 +#define OPTION_DIRMODE 1056 +#define OPTION_NEW_DIR_MODE 1057 +#define OPTION_CACHE_INODES 1058 +#define OPTION_NOCACHE_INODES 1059 + +#define OPTION_CHECK_SESSION 1060 +#define OPTION_FORCE_RR 1061 + +#define OPTION_DEBUG 1062 + +#define OPTION_JLONG 1063 + +#define OPTION_STREAM_FILE_NAME 1064 +#define OPTION_STREAM_CD_SIZE 1065 + +#define OPTION_XA 1066 +#define OPTION_XA_RATIONALIZED 1067 + +#define OPTION_SUNX86BOOT 1068 +#define OPTION_SUNX86LABEL 1069 + +#define OPTION_ALLOW_LEADING_DOTS 1070 +#define OPTION_PUBLISHER 1071 + +#ifdef JIGDO_TEMPLATE +#define OPTION_JTT_OUTPUT 1101 +#define OPTION_JTJ_OUTPUT 1102 +#define OPTION_JT_MIN_SIZE 1103 +#define OPTION_JT_PATH_MAP 1104 +#define OPTION_JT_MD5_LIST 1105 +#define OPTION_JT_INCLUDE 1106 +#define OPTION_JT_EXCLUDE 1107 +#define OPTION_JT_COMPRESS_ALGO 1108 + +#define OPTION_JT_CHECKSUM_ALGO_ISO 1120 +#define OPTION_JT_CHECKSUM_ALGO_TMPL 1121 +#endif + +#define OPTION_BOOTALPHA 1200 + +#define OPTION_HPPA_CMDLINE 1210 +#define OPTION_HPPA_KERNEL_32 1211 +#define OPTION_HPPA_KERNEL_64 1212 +#define OPTION_HPPA_BOOTLOADER 1213 +#define OPTION_HPPA_RAMDISK 1214 + +#define OPTION_BOOTMIPS 1220 + +#define OPTION_BOOTMIPSEL 1230 + +#ifdef UDF +#define OPTION_UDF 1500 +#endif +#ifdef DVD_VIDEO +#define OPTION_DVD 1501 +#endif + +#ifdef APPLE_HYB +#define OPTION_CAP 2000 +#define OPTION_NETA 2001 +#define OPTION_DBL 2002 +#define OPTION_ESH 2003 +#define OPTION_FE 2004 +#define OPTION_SGI 2005 +#define OPTION_MBIN 2006 +#define OPTION_SGL 2007 +/* aliases */ +#define OPTION_USH 2008 +#define OPTION_XIN 2009 + +#define OPTION_DAVE 2010 +#define OPTION_SFM 2011 +#define OPTION_XDBL 2012 +#define OPTION_XHFS 2013 + +#define OPTION_PROBE 2020 +#define OPTION_MACNAME 2021 +#define OPTION_NOMACFILES 2022 +#define OPTION_BOOT_HFS_FILE 2023 +#define OPTION_MAGIC_FILE 2024 + +#define OPTION_HFS_LIST 2025 + +#define OPTION_GEN_PT 2026 + +#define OPTION_CREATE_DT 2027 +#define OPTION_HFS_HIDE 2028 + +#define OPTION_AUTOSTART 2029 +#define OPTION_BSIZE 2030 +#define OPTION_HFS_VOLID 2031 +#define OPTION_PREP_BOOT 2032 +#define OPTION_ICON_POS 2033 + +#define OPTION_HFS_TYPE 2034 +#define OPTION_HFS_CREATOR 2035 + +#define OPTION_ROOT_INFO 2036 + +#define OPTION_HFS_INPUT_CHARSET 2037 +#define OPTION_HFS_OUTPUT_CHARSET 2038 + +#define OPTION_HFS_UNLOCK 2039 +#define OPTION_HFS_BLESS 2040 +#define OPTION_HFS_PARMS 2041 + +#define OPTION_CHRP_BOOT 2042 + +#define OPTION_RELOC_ROOT 2043 +#define OPTION_RELOC_OLD_ROOT 2044 + +#define OPTION_MAP_FILE 2045 + +#define OPTION_ALLOW_LIMITED_SIZE 2046 + +#endif /* APPLE_HYB */ + +static int save_pname = 0; + +static const struct ld_option ld_options[] = +{ + {{"nobak", no_argument, NULL, OPTION_NOBAK}, + '\0', NULL, "Do not include backup files", ONE_DASH}, + {{"no-bak", no_argument, NULL, OPTION_NOBAK}, + '\0', NULL, "Do not include backup files", ONE_DASH}, + {{"abstract", required_argument, NULL, OPTION_ABSTRACT}, + '\0', "FILE", "Set Abstract filename", ONE_DASH}, + {{"appid", required_argument, NULL, 'A'}, + 'A', "ID", "Set Application ID", ONE_DASH}, + {{"biblio", required_argument, NULL, OPTION_BIBLIO}, + '\0', "FILE", "Set Bibliographic filename", ONE_DASH}, + {{"cache-inodes", no_argument, NULL, OPTION_CACHE_INODES}, + '\0', NULL, "Cache inodes (needed to detect hard links)", ONE_DASH}, + {{"no-cache-inodes", no_argument, NULL, OPTION_NOCACHE_INODES}, + '\0', NULL, "Do not cache inodes (if filesystem has no unique unides)", ONE_DASH}, + {{"check-oldnames", no_argument, NULL, OPTION_CHECK_OLDNAMES}, + '\0', NULL, "Check all imported ISO9660 names from old session", ONE_DASH}, + {{"check-session", required_argument, NULL, OPTION_CHECK_SESSION}, + '\0', "FILE", "Check all ISO9660 names from previous session", ONE_DASH}, + {{"copyright", required_argument, NULL, OPTION_COPYRIGHT}, + '\0', "FILE", "Set Copyright filename", ONE_DASH}, + {{"debug", no_argument, NULL, OPTION_DEBUG}, + '\0', NULL, "Set debug flag", ONE_DASH}, + {{"eltorito-boot", required_argument, NULL, 'b'}, + 'b', "FILE", "Set El Torito boot image name", ONE_DASH}, + {{"eltorito-alt-boot", no_argument, NULL, OPTION_ALT_BOOT}, + '\0', NULL, "Start specifying alternative El Torito boot parameters", ONE_DASH}, + {{"sparc-boot", required_argument, NULL, 'B'}, + 'B', "FILES", "Set sparc boot image names", ONE_DASH}, + {{"sunx86-boot", required_argument, NULL, OPTION_SUNX86BOOT}, + '\0', "FILES", "Set sunx86 boot image names", ONE_DASH}, + {{"generic-boot", required_argument, NULL, 'G'}, + 'G', "FILE", "Set generic boot image name", ONE_DASH}, + {{"sparc-label", required_argument, NULL, OPTION_SPARCLABEL}, + '\0', "label text", "Set sparc boot disk label", ONE_DASH}, + {{"sunx86-label", required_argument, NULL, OPTION_SUNX86LABEL}, + '\0', "label text", "Set sunx86 boot disk label", ONE_DASH}, + {{"eltorito-catalog", required_argument, NULL, 'c'}, + 'c', "FILE", "Set El Torito boot catalog name", ONE_DASH}, + {{"cdrecord-params", required_argument, NULL, 'C'}, + 'C', "PARAMS", "Magic paramters from cdrecord", ONE_DASH}, + {{"omit-period", no_argument, NULL, 'd'}, + 'd', NULL, "Omit trailing periods from filenames (violates ISO9660)", ONE_DASH}, + {{"dir-mode", required_argument, NULL, OPTION_DIRMODE}, + '\0', "mode", "Make the mode of all directories this mode.", ONE_DASH}, + {{"disable-deep-relocation", no_argument, NULL, 'D'}, + 'D', NULL, "Disable deep directory relocation (violates ISO9660)", ONE_DASH}, + {{"file-mode", required_argument, NULL, OPTION_FILEMODE}, + '\0', "mode", "Make the mode of all plain files this mode.", ONE_DASH}, + {{"follow-links", no_argument, NULL, 'f'}, + 'f', NULL, "Follow symbolic links", ONE_DASH}, + {{"gid", required_argument, NULL, OPTION_GID}, + '\0', "gid", "Make the group owner of all files this gid.", + ONE_DASH}, + {{"graft-points", no_argument, NULL, OPTION_USE_GRAFT}, + '\0', NULL, "Allow to use graft points for filenames", ONE_DASH}, + {{"root", required_argument, NULL, OPTION_RELOC_ROOT}, + '\0', "DIR", "Set root directory for all new files and directories", ONE_DASH}, + {{"old-root", required_argument, NULL, OPTION_RELOC_OLD_ROOT}, + '\0', "DIR", "Set root directory in previous session that is searched for files", ONE_DASH}, + {{"help", no_argument, NULL, OPTION_HELP}, + '\0', NULL, "Print option help", ONE_DASH}, + {{"hide", required_argument, NULL, OPTION_I_HIDE}, + '\0', "GLOBFILE", "Hide ISO9660/RR file", ONE_DASH}, + {{"hide-list", required_argument, NULL, OPTION_I_LIST}, + '\0', "FILE", "File with list of ISO9660/RR files to hide", ONE_DASH}, + {{"hidden", required_argument, NULL, OPTION_H_HIDE}, + '\0', "GLOBFILE", "Set hidden attribute on ISO9660 file", ONE_DASH}, + {{"hidden-list", required_argument, NULL, OPTION_H_LIST}, + '\0', "FILE", "File with list of ISO9660 files with hidden attribute", ONE_DASH}, + {{"hide-joliet", required_argument, NULL, OPTION_J_HIDE}, + '\0', "GLOBFILE", "Hide Joliet file", ONE_DASH}, + {{"hide-joliet-list", required_argument, NULL, OPTION_J_LIST}, + '\0', "FILE", "File with list of Joliet files to hide", ONE_DASH}, + {{"hide-joliet-trans-tbl", no_argument, NULL, OPTION_HIDE_TRANS_TBL}, + '\0', NULL, "Hide TRANS.TBL from Joliet tree", ONE_DASH}, + {{"hide-rr-moved", no_argument, NULL, OPTION_HIDE_RR_MOVED}, + '\0', NULL, "Rename RR_MOVED to .rr_moved in Rock Ridge tree", ONE_DASH}, + {{"gui", no_argument, NULL, OPTION_GUI}, + '\0', NULL, "Switch behaviour for GUI", ONE_DASH}, + {{NULL, required_argument, NULL, 'i'}, + 'i', "ADD_FILES", "No longer supported", TWO_DASHES}, + {{"input-charset", required_argument, NULL, OPTION_INPUT_CHARSET}, + '\0', "CHARSET", "Local input charset for file name conversion", ONE_DASH}, + {{"output-charset", required_argument, NULL, OPTION_OUTPUT_CHARSET}, + '\0', "CHARSET", "Output charset for file name conversion", ONE_DASH}, + {{"iso-level", required_argument, NULL, OPTION_ISO_LEVEL}, + '\0', "LEVEL", "Set ISO9660 conformance level (1..3) or 4 for ISO9660 version 2", ONE_DASH}, + {{"joliet", no_argument, NULL, 'J'}, + 'J', NULL, "Generate Joliet directory information", ONE_DASH}, + {{"joliet-long", no_argument, NULL, OPTION_JLONG}, + '\0', NULL, "Allow Joliet file names to be 103 Unicode characters", ONE_DASH}, + {{"jcharset", required_argument, NULL, OPTION_JCHARSET}, + '\0', "CHARSET", "Local charset for Joliet directory information", ONE_DASH}, + {{"full-iso9660-filenames", no_argument, NULL, 'l'}, + 'l', NULL, "Allow full 31 character filenames for ISO9660 names", ONE_DASH}, + {{"max-iso9660-filenames", no_argument, NULL, OPTION_MAX_FILENAMES}, + '\0', NULL, "Allow 37 character filenames for ISO9660 names (violates ISO9660)", ONE_DASH}, + + {{"allow-limited-size", no_argument, NULL, OPTION_ALLOW_LIMITED_SIZE}, + '\0', NULL, "Allow different file sizes in ISO9660/UDF on large files", ONE_DASH}, + + {{"allow-leading-dots", no_argument, NULL, OPTION_ALLOW_LEADING_DOTS}, + '\0', NULL, "Allow ISO9660 filenames to start with '.' (violates ISO9660)", ONE_DASH}, + {{"ldots", no_argument, NULL, OPTION_ALLOW_LEADING_DOTS}, + '\0', NULL, "Allow ISO9660 filenames to start with '.' (violates ISO9660)", ONE_DASH}, + {{"allow-leading-dots", no_argument, NULL, 'L'}, + 'L', NULL, "Allow ISO9660 filenames to start with '.' (violates ISO9660)", ONE_DASH}, + + {{"log-file", required_argument, NULL, OPTION_LOG_FILE}, + '\0', "LOG_FILE", "Re-direct messages to LOG_FILE", ONE_DASH}, + {{"exclude", required_argument, NULL, 'm'}, + 'm', "GLOBFILE", "Exclude file name", ONE_DASH}, + {{"exclude-list", required_argument, NULL, OPTION_X_LIST}, + '\0', "FILE", "File with list of file names to exclude", ONE_DASH}, + {{"pad", no_argument, NULL, OPTION_PAD}, + 0, NULL, "Pad output to a multiple of 32k (default)", ONE_DASH}, + {{"no-pad", no_argument, NULL, OPTION_NOPAD}, + 0, NULL, "Do not pad output to a multiple of 32k", ONE_DASH}, + {{"prev-session", required_argument, NULL, 'M'}, + 'M', "FILE", "Set path to previous session to merge", ONE_DASH}, + {{"dev", required_argument, NULL, 'M'}, + '\0', "SCSIdev", "Set path to previous session to merge", ONE_DASH}, + {{"omit-version-number", no_argument, NULL, 'N'}, + 'N', NULL, "Omit version number from ISO9660 filename (violates ISO9660)", ONE_DASH}, + {{"new-dir-mode", required_argument, NULL, OPTION_NEW_DIR_MODE}, + '\0', "mode", "Mode used when creating new directories.", ONE_DASH}, + {{"force-rr", no_argument, NULL, OPTION_FORCE_RR}, + 0, NULL, "Inhibit automatic Rock Ridge detection for previous session", ONE_DASH}, + {{"no-rr", no_argument, NULL, OPTION_NO_RR}, + 0, NULL, "Inhibit reading of Rock Ridge attributes from previous session", ONE_DASH}, + {{"no-split-symlink-components", no_argument, NULL, OPTION_NOSPLIT_SL_COMPONENT}, + 0, NULL, "Inhibit splitting symlink components", ONE_DASH}, + {{"no-split-symlink-fields", no_argument, NULL, OPTION_NOSPLIT_SL_FIELD}, + 0, NULL, "Inhibit splitting symlink fields", ONE_DASH}, + {{"output", required_argument, NULL, 'o'}, + 'o', "FILE", "Set output file name", ONE_DASH}, + {{"path-list", required_argument, NULL, OPTION_P_LIST}, + '\0', "FILE", "File with list of pathnames to process", ONE_DASH}, + {{"preparer", required_argument, NULL, 'p'}, + 'p', "PREP", "Set Volume preparer", ONE_DASH}, + {{"print-size", no_argument, NULL, OPTION_PRINT_SIZE}, + '\0', NULL, "Print estimated filesystem size and exit", ONE_DASH}, + {{"publisher", required_argument, NULL, OPTION_PUBLISHER}, + '\0', "PUB", "Set Volume publisher", ONE_DASH}, + {{"publisher", required_argument, NULL, 'P'}, + 'P', "PUB", "Set Volume publisher", ONE_DASH}, + {{"quiet", no_argument, NULL, OPTION_QUIET}, + '\0', NULL, "Run quietly", ONE_DASH}, + {{"rational-rock", no_argument, NULL, 'r'}, + 'r', NULL, "Generate rationalized Rock Ridge directory information", ONE_DASH}, + {{"rock", no_argument, NULL, 'R'}, + 'R', NULL, "Generate Rock Ridge directory information", ONE_DASH}, + {{"sectype", required_argument, NULL, 's'}, + 's', "TYPE", "Set output sector type to e.g. data/xa1/raw", ONE_DASH}, + + {{"alpha-boot", required_argument, NULL, OPTION_BOOTALPHA}, + '\0', "FILE", "Set alpha boot image name (relative to image root)", ONE_DASH}, + + {{"hppa-cmdline", required_argument, NULL, OPTION_HPPA_CMDLINE}, + '\0', "CMDLINE", "Set hppa boot command line (relative to image root)", ONE_DASH}, + {{"hppa-kernel-32", required_argument, NULL, OPTION_HPPA_KERNEL_32}, + '\0', "FILE", "Set hppa 32-bit image name (relative to image root)", ONE_DASH}, + {{"hppa-kernel-64", required_argument, NULL, OPTION_HPPA_KERNEL_64}, + '\0', "FILE", "Set hppa 64-bit image name (relative to image root)", ONE_DASH}, + {{"hppa-bootloader", required_argument, NULL, OPTION_HPPA_BOOTLOADER}, + '\0', "FILE", "Set hppa boot loader file name (relative to image root)", ONE_DASH}, + {{"hppa-ramdisk", required_argument, NULL, OPTION_HPPA_RAMDISK}, + '\0', "FILE", "Set hppa ramdisk file name (relative to image root)", ONE_DASH}, + + {{"mips-boot", required_argument, NULL, OPTION_BOOTMIPS}, + '\0', "FILE", "Set mips boot image name (relative to image root)", ONE_DASH}, + + {{"mipsel-boot", required_argument, NULL, OPTION_BOOTMIPSEL}, + '\0', "FILE", "Set mipsel boot image name (relative to image root)", ONE_DASH}, + +#ifdef JIGDO_TEMPLATE + {{"jigdo-jigdo", required_argument, NULL, OPTION_JTJ_OUTPUT}, + '\0', "FILE", "Produce a jigdo .jigdo file as well as the .iso", ONE_DASH }, + {{"jigdo-template", required_argument, NULL, OPTION_JTT_OUTPUT}, + '\0', "FILE", "Produce a jigdo .template file as well as the .iso", ONE_DASH }, + {{"jigdo-min-file-size", required_argument, NULL, OPTION_JT_MIN_SIZE}, + '\0', "SIZE", "Minimum size for a file to be listed in the jigdo file", ONE_DASH }, + {{"jigdo-force-md5", required_argument, NULL, OPTION_JT_INCLUDE}, + '\0', "PATTERN", "Pattern(s) where files MUST match an externally-supplied MD5sum", ONE_DASH }, + {{"jigdo-exclude", required_argument, NULL, OPTION_JT_EXCLUDE}, + '\0', "PATTERN", "Pattern(s) to exclude from the jigdo file", ONE_DASH }, + {{"jigdo-map", required_argument, NULL, OPTION_JT_PATH_MAP}, + '\0', "PATTERN1=PATTERN2", "Pattern(s) to map paths (e.g. Debian=/mirror/debian)", ONE_DASH }, + {{"md5-list", required_argument, NULL, OPTION_JT_MD5_LIST}, + '\0', "FILE", "File containing MD5 sums of the files that should be checked", ONE_DASH }, + {{"jigdo-template-compress", required_argument, NULL, OPTION_JT_COMPRESS_ALGO}, + '\0', "ALGORITHM", "Choose to use gzip or bzip2 compression for template data; default is gzip", ONE_DASH }, + {{"checksum_algorithm_iso", required_argument, NULL, OPTION_JT_CHECKSUM_ALGO_ISO}, + '\0', "alg1,alg2,...", "Specify the checksum types desired for the output image", ONE_DASH}, + {{"checksum_algorithm_template", required_argument, NULL, OPTION_JT_CHECKSUM_ALGO_TMPL}, + '\0', "alg1,alg2,...", "Specify the checksum types desired for the output jigdo template", ONE_DASH}, +#endif + +#ifdef SORTING + { {"sort", required_argument, NULL, OPTION_SORT}, + '\0', "FILE", "Sort file content locations according to rules in FILE", ONE_DASH }, +#endif /* SORTING */ + + {{"split-output", no_argument, NULL, OPTION_SPLIT_OUTPUT}, + '\0', NULL, "Split output into files of approx. 1GB size", ONE_DASH}, + {{"stream-file-name", required_argument, NULL, OPTION_STREAM_FILE_NAME}, + '\0', "FILE_NAME", "Set the stream file ISO9660 name (incl. version)", ONE_DASH}, + {{"stream-media-size", required_argument, NULL, OPTION_STREAM_CD_SIZE}, + '\0', "#", "Set the size of your CD media in sectors", ONE_DASH}, + {{"sysid", required_argument, NULL, OPTION_SYSID}, + '\0', "ID", "Set System ID", ONE_DASH}, + {{"translation-table", no_argument, NULL, 'T'}, + 'T', NULL, "Generate translation tables for systems that don't understand long filenames", ONE_DASH}, + {{"table-name", required_argument, NULL, OPTION_TRANS_TBL}, + '\0', "TABLE_NAME", "Translation table file name", ONE_DASH}, + {{"ucs-level", required_argument, NULL, OPTION_UCS_LEVEL}, + '\0', "LEVEL", "Set Joliet UCS level (1..3)", ONE_DASH}, + +#ifdef UDF + {{"udf", no_argument, NULL, OPTION_UDF}, + '\0', NULL, "Generate UDF file system", ONE_DASH}, +#endif + +#ifdef DVD_VIDEO + {{"dvd-video", no_argument, NULL, OPTION_DVD}, + '\0', NULL, "Generate DVD-Video compliant UDF file system", ONE_DASH}, +#endif + + {{"uid", required_argument, NULL, OPTION_UID}, + '\0', "uid", "Make the owner of all files this uid.", + ONE_DASH}, + {{"untranslated-filenames", no_argument, NULL, 'U'}, + /* CSTYLED */ + 'U', NULL, "Allow Untranslated filenames (for HPUX & AIX - violates ISO9660). Forces -l, -d, -N, -allow-leading-dots, -relaxed-filenames, -allow-lowercase, -allow-multidot", ONE_DASH}, + {{"relaxed-filenames", no_argument, NULL, OPTION_RELAXED_FILENAMES}, + '\0', NULL, "Allow 7 bit ASCII except lower case characters (violates ISO9660)", ONE_DASH}, + {{"no-iso-translate", no_argument, NULL, OPTION_ISO_TRANSLATE}, + '\0', NULL, "Do not translate illegal ISO characters '~', '-' and '#' (violates ISO9660)", ONE_DASH}, + {{"allow-lowercase", no_argument, NULL, OPTION_ALLOW_LOWERCASE}, + '\0', NULL, "Allow lower case characters in addition to the current character set (violates ISO9660)", ONE_DASH}, + {{"allow-multidot", no_argument, NULL, OPTION_ALLOW_MULTIDOT}, + '\0', NULL, "Allow more than one dot in filenames (e.g. .tar.gz) (violates ISO9660)", ONE_DASH}, + {{"use-fileversion", no_argument, NULL, OPTION_USE_FILEVERSION}, + '\0', "LEVEL", "Use file version # from filesystem", ONE_DASH}, + {{"verbose", no_argument, NULL, 'v'}, + 'v', NULL, "Verbose", ONE_DASH}, + {{"version", no_argument, NULL, OPTION_PVERSION}, + '\0', NULL, "Print the current version", ONE_DASH}, + {{"volid", required_argument, NULL, 'V'}, + 'V', "ID", "Set Volume ID", ONE_DASH}, + {{"volset", required_argument, NULL, OPTION_VOLSET}, + '\0', "ID", "Set Volume set ID", ONE_DASH}, + {{"volset-size", required_argument, NULL, OPTION_VOLSET_SIZE}, + '\0', "#", "Set Volume set size", ONE_DASH}, + {{"volset-seqno", required_argument, NULL, OPTION_VOLSET_SEQ_NUM}, + '\0', "#", "Set Volume set sequence number", ONE_DASH}, + {{"old-exclude", required_argument, NULL, 'x'}, + 'x', "FILE", "Exclude file name(depreciated)", ONE_DASH}, + {{"hard-disk-boot", no_argument, NULL, OPTION_HARD_DISK_BOOT}, + '\0', NULL, "Boot image is a hard disk image", ONE_DASH}, + {{"no-emul-boot", no_argument, NULL, OPTION_NO_EMUL_BOOT}, + '\0', NULL, "Boot image is 'no emulation' image", ONE_DASH}, + {{"no-boot", no_argument, NULL, OPTION_NO_BOOT}, + '\0', NULL, "Boot image is not bootable", ONE_DASH}, + {{"boot-load-seg", required_argument, NULL, OPTION_BOOT_LOAD_ADDR}, + '\0', "#", "Set load segment for boot image", ONE_DASH}, + {{"boot-load-size", required_argument, NULL, OPTION_BOOT_LOAD_SIZE}, + '\0', "#", "Set numbers of load sectors", ONE_DASH}, + {{"boot-info-table", no_argument, NULL, OPTION_BOOT_INFO_TABLE}, + '\0', NULL, "Patch boot image with info table", ONE_DASH}, + {{"XA", no_argument, NULL, OPTION_XA}, + '\0', NULL, "Generate XA directory attruibutes", ONE_DASH}, + {{"xa", no_argument, NULL, OPTION_XA_RATIONALIZED}, + '\0', NULL, "Generate rationalized XA directory attruibutes", ONE_DASH}, + {{"transparent-compression", no_argument, NULL, 'z'}, + 'z', NULL, "Enable transparent compression of files", ONE_DASH}, + +#ifdef APPLE_HYB + {{"hfs-type", required_argument, NULL, OPTION_HFS_TYPE}, + '\0', "TYPE", "Set HFS default TYPE", ONE_DASH}, + {{"hfs-creator", required_argument, NULL, OPTION_HFS_CREATOR}, + '\0', "CREATOR", "Set HFS default CREATOR", ONE_DASH}, + {{"apple", no_argument, NULL, 'g'}, + 'g', NULL, "Add Apple ISO9660 extensions", ONE_DASH}, + {{"hfs", no_argument, NULL, 'h'}, + 'h', NULL, "Create ISO9660/HFS hybrid", ONE_DASH}, + {{"map", required_argument, NULL, OPTION_MAP_FILE}, + '\0', "MAPPING_FILE", "Map file extensions to HFS TYPE/CREATOR", ONE_DASH}, + {{"map", required_argument, NULL, 'H'}, + 'H', "MAPPING_FILE", "Map file extensions to HFS TYPE/CREATOR", ONE_DASH}, + {{"magic", required_argument, NULL, OPTION_MAGIC_FILE}, + '\0', "FILE", "Magic file for HFS TYPE/CREATOR", ONE_DASH}, + {{"probe", no_argument, NULL, OPTION_PROBE}, + '\0', NULL, "Probe all files for Apple/Unix file types", ONE_DASH}, + {{"mac-name", no_argument, NULL, OPTION_MACNAME}, + '\0', NULL, "Use Macintosh name for ISO9660/Joliet/RockRidge file name", + ONE_DASH}, + {{"no-mac-files", no_argument, NULL, OPTION_NOMACFILES}, + '\0', NULL, "Do not look for Unix/Mac files (depreciated)", ONE_DASH}, + {{"boot-hfs-file", required_argument, NULL, OPTION_BOOT_HFS_FILE}, + '\0', "FILE", "Set HFS boot image name", ONE_DASH}, + {{"part", no_argument, NULL, OPTION_GEN_PT}, + '\0', NULL, "Generate HFS partition table", ONE_DASH}, + {{"cluster-size", required_argument, NULL, OPTION_BSIZE}, + '\0', "SIZE", "Cluster size for PC Exchange Macintosh files", ONE_DASH}, + {{"auto", required_argument, NULL, OPTION_AUTOSTART}, + '\0', "FILE", "Set HFS AutoStart file name", ONE_DASH}, + {{"no-desktop", no_argument, NULL, OPTION_CREATE_DT}, + '\0', NULL, "Do not create the HFS (empty) Desktop files", ONE_DASH}, + {{"hide-hfs", required_argument, NULL, OPTION_HFS_HIDE}, + '\0', "GLOBFILE", "Hide HFS file", ONE_DASH}, + {{"hide-hfs-list", required_argument, NULL, OPTION_HFS_LIST}, + '\0', "FILE", "List of HFS files to hide", ONE_DASH}, + {{"hfs-volid", required_argument, NULL, OPTION_HFS_VOLID}, + '\0', "HFS_VOLID", "Volume name for the HFS partition", ONE_DASH}, + {{"icon-position", no_argument, NULL, OPTION_ICON_POS}, + '\0', NULL, "Keep HFS icon position", ONE_DASH}, + {{"root-info", required_argument, NULL, OPTION_ROOT_INFO}, + '\0', "FILE", "finderinfo for root folder", ONE_DASH}, + {{"input-hfs-charset", required_argument, NULL, OPTION_HFS_INPUT_CHARSET}, + '\0', "CHARSET", "Local input charset for HFS file name conversion", ONE_DASH}, + {{"output-hfs-charset", required_argument, NULL, OPTION_HFS_OUTPUT_CHARSET}, + '\0', "CHARSET", "Output charset for HFS file name conversion", ONE_DASH}, + {{"hfs-unlock", no_argument, NULL, OPTION_HFS_UNLOCK}, + '\0', NULL, "Leave HFS Volume unlocked", ONE_DASH}, + {{"hfs-bless", required_argument, NULL, OPTION_HFS_BLESS}, + '\0', "FOLDER_NAME", "Name of Folder to be blessed", ONE_DASH}, + {{"hfs-parms", required_argument, NULL, OPTION_HFS_PARMS}, + '\0', "PARAMETERS", "Comma separated list of HFS parameters", ONE_DASH}, +#ifdef PREP_BOOT + {{"prep-boot", required_argument, NULL, OPTION_PREP_BOOT}, + '\0', "FILE", "PReP boot image file -- up to 4 are allowed", ONE_DASH}, + {{"chrp-boot", no_argument, NULL, OPTION_CHRP_BOOT}, + '\0', NULL, "Add CHRP boot header", ONE_DASH}, +#endif /* PREP_BOOT */ + {{"cap", no_argument, NULL, OPTION_CAP}, + '\0', NULL, "Look for AUFS CAP Macintosh files", TWO_DASHES}, + {{"netatalk", no_argument, NULL, OPTION_NETA}, + '\0', NULL, "Look for NETATALK Macintosh files", TWO_DASHES}, + {{"double", no_argument, NULL, OPTION_DBL}, + '\0', NULL, "Look for AppleDouble Macintosh files", TWO_DASHES}, + {{"ethershare", no_argument, NULL, OPTION_ESH}, + '\0', NULL, "Look for Helios EtherShare Macintosh files", TWO_DASHES}, + {{"exchange", no_argument, NULL, OPTION_FE}, + '\0', NULL, "Look for PC Exchange Macintosh files", TWO_DASHES}, + {{"sgi", no_argument, NULL, OPTION_SGI}, + '\0', NULL, "Look for SGI Macintosh files", TWO_DASHES}, + {{"macbin", no_argument, NULL, OPTION_MBIN}, + '\0', NULL, "Look for MacBinary Macintosh files", TWO_DASHES}, + {{"single", no_argument, NULL, OPTION_SGL}, + '\0', NULL, "Look for AppleSingle Macintosh files", TWO_DASHES}, + {{"ushare", no_argument, NULL, OPTION_USH}, + '\0', NULL, "Look for IPT UShare Macintosh files", TWO_DASHES}, + {{"xinet", no_argument, NULL, OPTION_XIN}, + '\0', NULL, "Look for XINET Macintosh files", TWO_DASHES}, + {{"dave", no_argument, NULL, OPTION_DAVE}, + '\0', NULL, "Look for DAVE Macintosh files", TWO_DASHES}, + {{"sfm", no_argument, NULL, OPTION_SFM}, + '\0', NULL, "Look for SFM Macintosh files", TWO_DASHES}, + {{"osx-double", no_argument, NULL, OPTION_XDBL}, + '\0', NULL, "Look for MacOS X AppleDouble Macintosh files", TWO_DASHES}, + {{"osx-hfs", no_argument, NULL, OPTION_XHFS}, + '\0', NULL, "Look for MacOS X HFS Macintosh files", TWO_DASHES}, +#endif /* APPLE_HYB */ +}; + +#define OPTION_COUNT (sizeof ld_options / sizeof (ld_options[0])) + +static void read_rcfile(char *appname); +static void susage(int excode); +static void usage(int excode); +int iso9660_date(char *result, time_t crtime); +static void hide_reloc_dir(void); +static char *get_pnames(int argc, char **argv, int opt, char *pname, + int pnsize, FILE *fp); +char *findgequal(char *s); +static char *escstrcpy(char *to, char *from); +void *e_malloc(size_t size); + +static int +read_one_rcfile(char *filename) +{ + int linum = 0; + char linebuffer[256]; + FILE *fp; + + if (!filename) + return 0; + + fp = fopen(filename, "r"); + if (!fp) { + if (errno == ENOENT) + return 0; +#ifdef USE_LIBSCHILY + errmsg("Cannot open '%s'.\n", filename); +#else + perror(filename); +#endif + return 0; + } + if (verbose > 0) + fprintf(stderr, "Using \"%s\"\n", filename); + + while (fgets(linebuffer, sizeof(linebuffer), fp)) { + char *name, *p, *p1; + struct rcopts *rco; + + ++linum; + /* skip any leading white space */ + for (p = linebuffer; *p == ' ' || *p == '\t'; p++) + ; + /* Skip comments and blank lines */ + if (!*p || *p == '\n' || *p == '\r' || *p == '#') + continue; + /* + * The name should begin in the left margin. Make sure it is + * in upper case. Stop when we see white space or a comment. + */ + name = p; + while (*p && (isalpha((unsigned char) *p) || *p == '_')) + *p++ = toupper((unsigned char) *p); + + if (name == p) { + fprintf(stderr, "%s:%d: name required\n", filename, + linum); + continue; + } + + p1 = p; + /* Skip past white space after the name */ + while (*p == ' ' || *p == '\t') + p++; + /* silently ignore errors in the rc file. */ + if (*p != '=') { + fprintf(stderr, "%s:%d: equals sign required after '%.*s'\n", + filename, linum, + (int)(p1-name), name); + continue; + } + *p1 = 0; + + /* Skip pas the = sign, and any white space following it */ + p++; + while (*p == ' ' || *p == '\t') + p++; + + /* Get rid of trailing newline */ + for (p1 = p; *p1 && *p1 != '\n' && *p1 != '\r'; p1++) + ; + *p1 = 0; + + /* Figure out which option we have */ + for (rco = rcopt; rco->tag; rco++) + if (strcmp(rco->tag, name) == 0) { + /* memleak if we ever do this more than once */ + *rco->variable = strdup(p); + break; + } + + if (!rco->tag) { + fprintf(stderr, "%s:%d: field name '%s' unknown\n", + filename, linum, + name); + } + } + if (ferror(fp)) { +#ifdef USE_LIBSCHILY + errmsg("Read error on '%s'.\n", filename); +#else + perror(filename); +#endif + fclose(fp); + return 0; + } + fclose(fp); + return 1; +} + +#define ETCDIR "/etc" +#define RCFILENAME "genisoimagerc" +#define OLD_RCFILENAME "mkisofsrc" + +static void +read_rcfile(char *appname) +{ + char *p; + char filename[1000]; + + if (read_one_rcfile(getenv("GENISOIMAGERC"))) + return; + if (read_one_rcfile(getenv("MKISOFSRC"))) + return; + if (read_one_rcfile("." RCFILENAME)) + return; + if (read_one_rcfile("." OLD_RCFILENAME)) + return; + + p = getenv("HOME"); + if (p && strlen(p) + 1 + sizeof(RCFILENAME) < sizeof(filename)) { + strcpy(filename, p); + p = filename + strlen(filename); + *p++ = PATH_SEPARATOR; + strcpy(p, "." RCFILENAME); + if (read_one_rcfile(filename)) + return; + strcpy(p, "." OLD_RCFILENAME); + if (read_one_rcfile(filename)) + return; + } + + if (read_one_rcfile(ETCDIR SPATH_SEPARATOR RCFILENAME)) + return; + + if (appname && + strlen(appname) + 1 + sizeof(RCFILENAME) < sizeof(filename)) { + strcpy(filename, appname); + p = strrchr(filename, PATH_SEPARATOR); + if (p) { + strcpy(p + 1, RCFILENAME); + if (read_one_rcfile(filename)) + return; + } + } +} + +char *path_table_l = NULL; +char *path_table_m = NULL; + +char *jpath_table_l = NULL; +char *jpath_table_m = NULL; + +int goof = 0; + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static void +susage(int excode) +{ + const char *program_name = "genisoimage"; + + fprintf(stderr, "Usage: %s [options] -o file directory ...\n", program_name); + fprintf(stderr, "\nUse %s -help\n", program_name); + fprintf(stderr, "to get a list of valid options.\n"); + fprintf(stderr, "\nReport problems to debburn-devel@lists.alioth.debian.org.\n"); + + exit(excode); +} + +static void +usage(int excode) +{ + const char *program_name = "genisoimage"; + + int i; + +/* const char **targets, **pp;*/ + + fprintf(stderr, "Usage: %s [options] file...\n", program_name); + + fprintf(stderr, "Options:\n"); + for (i = 0; i < (int)OPTION_COUNT; i++) { + if (ld_options[i].doc != NULL) { + int comma; + int len; + int j; + + fprintf(stderr, " "); + + comma = FALSE; + len = 2; + + j = i; + do { + if (ld_options[j].shortopt != '\0' && + ld_options[j].control != NO_HELP) { + fprintf(stderr, "%s-%c", + comma ? ", " : "", + ld_options[j].shortopt); + len += (comma ? 2 : 0) + 2; + if (ld_options[j].arg != NULL) { + if (ld_options[j].opt.has_arg != optional_argument) { + fprintf(stderr, " "); + ++len; + } + fprintf(stderr, "%s", + ld_options[j].arg); + len += strlen(ld_options[j].arg); + } + comma = TRUE; + } + ++j; + } + while (j < (int)OPTION_COUNT && ld_options[j].doc == NULL); + + j = i; + do { + if (ld_options[j].opt.name != NULL && + ld_options[j].control != NO_HELP) { + fprintf(stderr, "%s-%s%s", + comma ? ", " : "", + ld_options[j].control == TWO_DASHES ? "-" : "", + ld_options[j].opt.name); + len += ((comma ? 2 : 0) + + 1 + + (ld_options[j].control == TWO_DASHES ? 1 : 0) + + strlen(ld_options[j].opt.name)); + if (ld_options[j].arg != NULL) { + fprintf(stderr, " %s", + ld_options[j].arg); + len += 1 + + strlen(ld_options[j].arg); + } + comma = TRUE; + } + ++j; + } + while (j < (int)OPTION_COUNT && ld_options[j].doc == NULL); + + if (len >= 30) { + fprintf(stderr, "\n"); + len = 0; + } + for (; len < 30; len++) + fputc(' ', stderr); + + fprintf(stderr, "%s\n", ld_options[i].doc); + } + } + fprintf(stderr, + "\nReport problems to debburn-devel@lists.alioth.debian.org.\n"); + exit(excode); +} + + +/* + * Fill in date in the iso9660 format + * + * The standards state that the timezone offset is in multiples of 15 + * minutes, and is what you add to GMT to get the localtime. The U.S. + * is always at a negative offset, from -5h to -8h (can vary a little + * with DST, I guess). The Linux iso9660 filesystem has had the sign + * of this wrong for ages (genisoimage had it wrong too for the longest time). + */ +int +iso9660_date(char *result, time_t crtime) +{ + struct tm *local; + + local = localtime(&crtime); + result[0] = local->tm_year; + result[1] = local->tm_mon + 1; + result[2] = local->tm_mday; + result[3] = local->tm_hour; + result[4] = local->tm_min; + result[5] = local->tm_sec; + + /* + * Must recalculate proper timezone offset each time, as some files use + * daylight savings time and some don't... + */ + result[6] = local->tm_yday; /* save yday 'cause gmtime zaps it */ + local = gmtime(&crtime); + local->tm_year -= result[0]; + local->tm_yday -= result[6]; + local->tm_hour -= result[3]; + local->tm_min -= result[4]; + if (local->tm_year < 0) { + local->tm_yday = -1; + } else { + if (local->tm_year > 0) + local->tm_yday = 1; + } + + result[6] = -(local->tm_min + 60 * + (local->tm_hour + 24 * local->tm_yday)) / 15; + + return (0); +} + +/* hide "./rr_moved" if all its contents are hidden */ +static void +hide_reloc_dir() +{ + struct directory_entry *s_entry; + + for (s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next) { + if (strcmp(s_entry->name, ".") == 0 || + strcmp(s_entry->name, "..") == 0) + continue; + + if ((s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0) + return; + } + + /* all entries are hidden, so hide this directory */ + reloc_dir->dir_flags |= INHIBIT_ISO9660_ENTRY; + reloc_dir->self->de_flags |= INHIBIT_ISO9660_ENTRY; +} + +/* + * get pathnames from the command line, and then from given file + */ +static char * +get_pnames(int argc, char **argv, int opt, char *pname, int pnsize, FILE *fp) +{ + int len; + + /* we may of already read the first line from the pathnames file */ + if (save_pname) { + save_pname = 0; + return (pname); + } + + if (opt < argc) + return (argv[opt]); + + if (fp == NULL) + return ((char *) 0); + + if (fgets(pname, pnsize, fp)) { + /* Discard newline */ + len = strlen(pname); + if (pname[len - 1] == '\n') { + pname[len - 1] = '\0'; + } + return (pname); + } + return ((char *) 0); +} + +extern char *cdrecord_data; + +int main(int argc, char *argv[]) +{ + struct directory_entry de; + +#ifdef HAVE_SBRK + unsigned long mem_start; + +#endif + struct stat statbuf; + char *merge_image = NULL; + char *reloc_root = NULL; + char *reloc_old_root = NULL; + struct iso_directory_record *mrootp = NULL; + struct output_fragment *opnt; + int longind; + char shortopts[OPTION_COUNT * 3 + 2]; + struct option longopts[OPTION_COUNT + 1]; + int c; + int n; + char *log_file = 0; + char *node = NULL; + char *pathnames = 0; + FILE *pfp = NULL; + char pname[2*PATH_MAX + 1 + 1]; /* may be too short */ + char *arg; /* if '\\' present */ + char nodename[PATH_MAX + 1]; + int no_path_names = 1; + int warn_violate = 0; + int have_cmd_line_pathspec = 0; + int rationalize_all = 0; + char *mkisofs_call = 0; /* use as pointer and boolean */ + +#ifdef APPLE_HYB + char *afpfile = ""; /* mapping file for TYPE/CREATOR */ + int hfs_ct = 0; + char *root_info = 0; +#endif /* APPLE_HYB */ + + /* abusing arg */ + mkisofs_call=strstr(argv[0], "mkisofs"); + if(mkisofs_call && '\0' == mkisofs_call[7]) /* lame cheater detected */ + argv[0]="genisoimage"; + +#ifdef __EMX__ + /* This gives wildcard expansion with Non-Posix shells with EMX */ + _wildcard(&argc, &argv); +#endif + save_args(argc, argv); + + if (argc < 2) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Missing pathspec.\n"); +#endif + susage(1); + } + /* Get the defaults from the .genisoimagerc file */ + read_rcfile(argv[0]); + + outfile = NULL; + + /* + * Copy long option initialization from GNU-ld. + */ + /* + * Starting the short option string with '-' is for programs that + * expect options and other ARGV-elements in any order and that care + * about the ordering of the two. We describe each non-option + * ARGV-element as if it were the argument of an option with + * character code 1. + */ + { + int i, + is, + il; + + shortopts[0] = '-'; + is = 1; + il = 0; + for (i = 0; i < (int)OPTION_COUNT; i++) { + if (ld_options[i].shortopt != '\0') { + shortopts[is] = ld_options[i].shortopt; + ++is; + if (ld_options[i].opt.has_arg == + required_argument || + ld_options[i].opt.has_arg == + optional_argument) { + shortopts[is] = ':'; + ++is; + if (ld_options[i].opt.has_arg == + optional_argument) { + shortopts[is] = ':'; + ++is; + } + } + } + if (ld_options[i].opt.name != NULL) { + longopts[il] = ld_options[i].opt; + ++il; + } + } + shortopts[is] = '\0'; + longopts[il].name = NULL; + } + + while ((c = getopt_long_only(argc, argv, shortopts, + longopts, &longind)) != EOF) + switch (c) { + case 1: + /* A filename that we take as input. */ + optind--; + have_cmd_line_pathspec = 1; + goto parse_input_files; + + case OPTION_USE_GRAFT: + use_graft_ptrs = 1; + break; + case 'C': + /* + * This is a temporary hack until cdrecord gets the + * proper hooks in it. + */ + cdrecord_data = optarg; + break; + case OPTION_GUI: + gui++; + break; + case 'i': +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "-i option no longer supported.\n"); +#else + fprintf(stderr, "-i option no longer supported.\n"); + exit(1); +#endif + break; + case OPTION_ISO_LEVEL: + iso9660_level = atoi(optarg); + + switch (iso9660_level) { + + case 1: + /* + * Only on file section + * 8.3 d or d1 characters for files + * 8 d or d1 characters for directories + */ + break; + case 2: + /* + * Only on file section + */ + break; + case 3: + /* + * No restrictions + */ + break; + case 4: + /* + * This is ISO-9660:1988 (ISO-9660 version 2) + */ + iso9660_namelen = MAX_ISONAME_V2; /* allow 207 chars */ + full_iso9660_filenames++; /* 31+ chars */ + omit_version_number++; + RR_relocation_depth = 32767; + + /* + * From -U ... + */ + omit_period++; /* trailing dot */ + allow_leading_dots++; + relaxed_filenames++; /* all chars */ + allow_lowercase++; /* even lowcase */ + allow_multidot++; /* > 1 dots */ + break; + + default: + comerrno(EX_BAD, "Illegal iso9660 Level %d, use 1..3 or 4.\n", + iso9660_level); + } + break; + case 'J': + use_Joliet++; + break; + case OPTION_JLONG: + use_Joliet++; + jlen = JLONGMAX; + break; + case OPTION_JCHARSET: + use_Joliet++; + /* FALLTHROUGH */ + case OPTION_INPUT_CHARSET: + icharset = optarg; + break; + case OPTION_OUTPUT_CHARSET: + ocharset = optarg; + break; +#ifdef JIGDO_TEMPLATE + case OPTION_JTT_OUTPUT: + jtemplate_out = optarg; + break; + case OPTION_JTJ_OUTPUT: + jjigdo_out = optarg; + break; + case OPTION_JT_MD5_LIST: + jmd5_list = optarg; + break; + case OPTION_JT_MIN_SIZE: + jte_min_size = atoi(optarg); + if (jte_min_size < MIN_JIGDO_FILE_SIZE) { + fprintf(stderr, "Jigdo min size %d too small; using default %d instead\n", jte_min_size, MIN_JIGDO_FILE_SIZE); + jte_min_size = MIN_JIGDO_FILE_SIZE; + } + break; + case OPTION_JT_INCLUDE: + if (jte_add_include(optarg)) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Failed to build jigdo-include list\n"); +#else + fprintf(stderr, + "Failed to build jigdo-include list\n"); + exit(1); +#endif + } + break; + case OPTION_JT_EXCLUDE: + if (jte_add_exclude(optarg)) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Failed to build jigdo-exclude list\n"); +#else + fprintf(stderr, + "Failed to build jigdo-exclude list\n"); + exit(1); +#endif + } + break; + case OPTION_JT_PATH_MAP: + if (jte_add_mapping(optarg)) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Failed to build jigdo mapping list\n"); +#else + fprintf(stderr, + "Failed to build jigdo mapping list\n"); + exit(1); +#endif + } + break; + case OPTION_JT_COMPRESS_ALGO: + if (!strcasecmp(optarg, "gzip")) + jte_template_compression = JTE_TEMP_GZIP; + else if (!strcasecmp(optarg, "bzip2")) + jte_template_compression = JTE_TEMP_BZIP2; + else + { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Compression algorithm %s unknown\n", optarg); +#else + fprintf(stderr, "Compression algorithm %s unknown\n", optarg); + exit(1); +#endif + } + break; + + case OPTION_JT_CHECKSUM_ALGO_ISO: + if (parse_checksum_algo(optarg, &checksum_algo_iso)) + { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Problem with ISO checksum choices: %s \n", optarg); +#else + fprintf(stderr, "Problem with ISO checksum choices: %s\n", optarg); + exit(1); +#endif + } + + break; + + case OPTION_JT_CHECKSUM_ALGO_TMPL: + if (parse_checksum_algo(optarg, &checksum_algo_tmpl)) + { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Problem with template checksum choices: %s \n", optarg); +#else + fprintf(stderr, "Problem with template checksum choices: %s\n", optarg); + exit(1); +#endif + } + break; + +#endif /* JIGDO_TEMPLATE */ + case OPTION_NOBAK: + all_files = 0; + break; + case 'b': + do_sort++; /* We sort bootcat/botimage */ + use_eltorito++; + boot_image = optarg; /* pathname of the boot image */ + /* on disk */ + if (boot_image == NULL) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Required Eltorito boot image pathname missing\n"); +#else + fprintf(stderr, + "Required Eltorito boot image pathname missing\n"); + exit(1); +#endif + } + get_boot_entry(); + current_boot_entry->boot_image = boot_image; + break; + case OPTION_ALT_BOOT: + /* + * Start new boot entry parameter list. + */ + new_boot_entry(); + break; + case OPTION_BOOTALPHA: + use_alphaboot++; + /* list of pathnames of boot images */ + add_boot_alpha_filename(optarg); + break; + case OPTION_HPPA_CMDLINE: + use_hppaboot++; + add_boot_hppa_cmdline(optarg); + break; + case OPTION_HPPA_KERNEL_32: + use_hppaboot++; + add_boot_hppa_kernel_32(optarg); + break; + case OPTION_HPPA_KERNEL_64: + use_hppaboot++; + add_boot_hppa_kernel_64(optarg); + break; + case OPTION_HPPA_BOOTLOADER: + use_hppaboot++; + add_boot_hppa_bootloader(optarg); + break; + case OPTION_HPPA_RAMDISK: + use_hppaboot++; + /* list of pathnames of boot images */ + add_boot_hppa_ramdisk(optarg); + break; + case OPTION_BOOTMIPS: + use_mipsboot++; + /* list of pathnames of boot images */ + add_boot_mips_filename(optarg); + break; + case OPTION_BOOTMIPSEL: + use_mipselboot++; + add_boot_mipsel_filename(optarg); + break; + case 'B': + if (use_sunx86boot) + comerrno(EX_BAD, + "-sparc-boot and -sunx86-boot are mutual exclusive.\n"); + use_sparcboot++; + /* list of pathnames of boot images */ + scan_sparc_boot(optarg); + break; + case OPTION_SUNX86BOOT: + if (use_sparcboot) + comerrno(EX_BAD, + "-sparc-boot and -sunx86-boot are mutual exclusive.\n"); + use_sunx86boot++; + /* list of pathnames of boot images */ + scan_sunx86_boot(optarg); + break; + case 'G': + use_genboot++; + /* pathname of the boot image on disk */ + genboot_image = optarg; + if (genboot_image == NULL) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Required generic boot image pathname missing\n"); +#else + fprintf(stderr, + "Required generic boot image pathname missing\n"); + exit(1); +#endif + } + break; + case OPTION_SPARCLABEL: + /* Sun disk label string */ + sparc_boot_label(optarg); + break; + case OPTION_SUNX86LABEL: + /* Sun disk label string */ + sunx86_boot_label(optarg); + break; + case 'c': + use_eltorito++; + /* pathname of the boot image on cd */ + boot_catalog = optarg; + if (boot_catalog == NULL) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Required boot catalog pathname missing\n"); +#else + fprintf(stderr, + "Required boot catalog pathname missing\n"); + exit(1); +#endif + } + break; + case OPTION_ABSTRACT: + abstract = optarg; + if (strlen(abstract) > 37) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Abstract filename string too long\n"); +#else + fprintf(stderr, + "Abstract filename string too long\n"); + exit(1); +#endif + } + break; + case 'A': + appid = optarg; + if (strlen(appid) > 128) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Application-id string too long\n"); +#else + fprintf(stderr, + "Application-id string too long\n"); + exit(1); +#endif + } + break; + case OPTION_BIBLIO: + biblio = optarg; + if (strlen(biblio) > 37) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Bibliographic filename string too long\n"); +#else + fprintf(stderr, + "Bibliographic filename string too long\n"); + exit(1); +#endif + } + break; + case OPTION_CACHE_INODES: + cache_inodes = 1; + break; + case OPTION_NOCACHE_INODES: + cache_inodes = 0; + break; + case OPTION_CHECK_OLDNAMES: + check_oldnames++; + break; + case OPTION_CHECK_SESSION: + check_session++; + check_oldnames++; + merge_image = optarg; + outfile = "/dev/null"; + /* + * cdrecord_data is handled specially in multi.c + * as we cannot write to all strings. + * If genisoimage is called with -C xx,yy + * our default is overwritten. + */ +/* cdrecord_data = "0,0";*/ + break; + case OPTION_COPYRIGHT: + copyright = optarg; + if (strlen(copyright) > 37) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Copyright filename string too long\n"); +#else + fprintf(stderr, + "Copyright filename string too long\n"); + exit(1); +#endif + } + break; + case OPTION_DEBUG: + debug++; + break; + case 'd': + omit_period++; + warn_violate++; + break; + case 'D': + RR_relocation_depth = 32767; + break; + case 'f': + follow_links++; + break; + case 'l': + full_iso9660_filenames++; + break; + case OPTION_MAX_FILENAMES: + iso9660_namelen = MAX_ISONAME_V1; /* allow 37 chars */ + full_iso9660_filenames++; + omit_version_number++; + warn_violate++; + break; + case 'L': + /* FALLTHRU */ + case OPTION_ALLOW_LEADING_DOTS: + allow_leading_dots++; + warn_violate++; + break; + case OPTION_LOG_FILE: + log_file = optarg; + break; + case 'M': + merge_image = optarg; + break; + case OPTION_RELOC_ROOT: + reloc_root = optarg; + break; + case OPTION_RELOC_OLD_ROOT: + reloc_old_root = optarg; + break; + case 'N': + omit_version_number++; + warn_violate++; + break; + case OPTION_FORCE_RR: + force_rr++; + break; + case OPTION_NO_RR: + no_rr++; + break; + case 'o': + outfile = optarg; + break; + case OPTION_PAD: + dopad++; + break; + case OPTION_NOPAD: + dopad = 0; + break; + case OPTION_P_LIST: + pathnames = optarg; + break; + case 'p': + preparer = optarg; + if (strlen(preparer) > 128) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Preparer string too long\n"); +#else + fprintf(stderr, "Preparer string too long\n"); + exit(1); +#endif + } + break; + case OPTION_PRINT_SIZE: + print_size++; + break; + case 'P': + /* FALLTHRU */ + case OPTION_PUBLISHER: + publisher = optarg; + if (strlen(publisher) > 128) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Publisher string too long\n"); +#else + fprintf(stderr, "Publisher string too long\n"); + exit(1); +#endif + } + break; + case OPTION_QUIET: + verbose = 0; + break; + case 'R': + use_RockRidge++; + break; + case 'r': + rationalize_all++; + use_RockRidge++; + break; + case OPTION_XA: + use_XA++; + break; + case OPTION_XA_RATIONALIZED: + rationalize_all++; + use_XA++; + break; + + case 's': + if (strcmp(optarg, "data") == 0) + osecsize = 2048; + else if (strcmp(optarg, "xa1") == 0) + osecsize = 2056; + else if (strcmp(optarg, "raw") == 0) { + osecsize = 2352; + comerrno(EX_BAD, + "Unsupported sector type '%s'.\n", + optarg); + } + break; + case 'S': +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Option -%c is reserved for future use.\n", c); +#else + fprintf(stderr, "Option -%c is reserved for future use.\n", c); +#endif + susage(1); + /* NOTREACHED */ + + case OPTION_NEW_DIR_MODE: + rationalize++; + { + char *end = 0; + + new_dir_mode = strtol(optarg, &end, 8); + if (!end || *end != 0 || + new_dir_mode < 0 || new_dir_mode > 07777) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Bad mode for -new-dir-mode\n"); +#else + fprintf(stderr, "Bad mode for -new-dir-mode\n"); + exit(1); +#endif + } + break; + } + + case OPTION_UID: + rationalize++; + use_RockRidge++; + rationalize_uid++; + { + char *end = 0; + + uid_to_use = strtol(optarg, &end, 0); + if (!end || *end != 0) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Bad value for -uid\n"); +#else + fprintf(stderr, "Bad value for -uid\n"); + exit(1); +#endif + } + break; + } + + case OPTION_GID: + rationalize++; + use_RockRidge++; + rationalize_gid++; + { + char *end = 0; + + gid_to_use = strtol(optarg, &end, 0); + if (!end || *end != 0) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Bad value for -gid\n"); +#else + fprintf(stderr, "Bad value for -gid\n"); + exit(1); +#endif + } + break; + } + + case OPTION_FILEMODE: + rationalize++; + use_RockRidge++; + rationalize_filemode++; + { + char *end = 0; + + filemode_to_use = strtol(optarg, &end, 8); + if (!end || *end != 0 || + filemode_to_use < 0 || filemode_to_use > 07777) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Bad mode for -file-mode\n"); +#else + fprintf(stderr, "Bad mode for -file-mode\n"); + exit(1); +#endif + } + break; + } + + case OPTION_DIRMODE: + rationalize++; + use_RockRidge++; + rationalize_dirmode++; + { + char *end = 0; + + dirmode_to_use = strtol(optarg, &end, 8); + if (!end || *end != 0 || + dirmode_to_use < 0 || dirmode_to_use > 07777) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Bad mode for -dir-mode\n"); +#else + fprintf(stderr, "Bad mode for -dir-mode\n"); + exit(1); +#endif + } + break; + } + +#ifdef SORTING + case OPTION_SORT: + do_sort++; + add_sort_list(optarg); + break; +#endif /* SORTING */ + + case OPTION_SPLIT_OUTPUT: + split_output++; + break; + + case OPTION_STREAM_FILE_NAME: + stream_filename = optarg; + break; + + case OPTION_STREAM_CD_SIZE: + stream_media_size = atoi(optarg); + break; + + case OPTION_SYSID: + system_id = optarg; + if (strlen(system_id) > 32) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "System ID string too long\n"); +#else + fprintf(stderr, "System ID string too long\n"); + exit(1); +#endif + } + break; + case OPTION_TRANS_TBL: + trans_tbl = optarg; + /* FALLTHRU */ + case 'T': + generate_tables++; + break; + case OPTION_UCS_LEVEL: + ucs_level = atoi(optarg); + if (ucs_level < 1 || ucs_level > 3) + comerrno(EX_BAD, "Illegal UCS Level %d, use 1..3.\n", + ucs_level); + break; +#ifdef UDF + case OPTION_UDF: + use_udf++; + break; +#endif + +#ifdef DVD_VIDEO + case OPTION_DVD: + use_udf++; + dvd_video++; + break; +#endif + case OPTION_USE_FILEVERSION: + use_fileversion++; + break; + case 'U': + /* + * Minimal (only truncation of 31+ characters) + * translation of filenames. + * + * Forces -l, -d, -N, -allow-leading-dots, + * -relaxed-filenames, + * -allow-lowercase, -allow-multidot + * + * This is for HP-UX, which does not recognize ANY + * extentions (Rock Ridge, Joliet), causing pain when + * loading software. pfs_mount can be used to read the + * extensions, but the untranslated filenames can be + * read by the "native" cdfs mounter. Completely + * violates iso9660. + */ + full_iso9660_filenames++; /* 31 chars */ + omit_period++; /* trailing dot */ + allow_leading_dots++; + omit_version_number++; + relaxed_filenames++; /* all chars */ + allow_lowercase++; /* even lowcase */ + allow_multidot++; /* > 1 dots */ + warn_violate++; + break; + + case OPTION_RELAXED_FILENAMES: + relaxed_filenames++; + warn_violate++; + break; + case OPTION_ALLOW_LOWERCASE: + allow_lowercase++; + warn_violate++; + break; + case OPTION_ALLOW_MULTIDOT: + allow_multidot++; + warn_violate++; + break; + case OPTION_ISO_TRANSLATE: + iso_translate = 0; + warn_violate++; + break; + case 'V': + volume_id = optarg; + if (strlen(volume_id) > 32) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Volume ID string too long\n"); +#else + fprintf(stderr, + "Volume ID string too long\n"); + exit(1); +#endif + } + break; + case OPTION_VOLSET: + volset_id = optarg; + if (strlen(volset_id) > 128) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Volume set ID string too long\n"); +#else + fprintf(stderr, + "Volume set ID string too long\n"); + exit(1); +#endif + } + break; + case OPTION_VOLSET_SIZE: + volume_set_size = atoi(optarg); + if (volume_set_size <= 0) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Illegal Volume Set Size %s\n", optarg); +#else + fprintf(stderr, + "Illegal Volume Set Size %s\n", optarg); + exit(1); +#endif + } + if (volume_set_size > 1) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Volume Set Size > 1 not yet supported\n"); +#else + fprintf(stderr, + "Volume Set Size > 1 not yet supported\n"); + exit(1); +#endif + } + break; + case OPTION_VOLSET_SEQ_NUM: + volume_sequence_number = atoi(optarg); + if (volume_sequence_number > volume_set_size) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Volume set sequence number too big\n"); +#else + fprintf(stderr, + "Volume set sequence number too big\n"); + exit(1); +#endif + } + break; + case 'v': + verbose++; + break; + case 'z': +#ifdef VMS +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Transparent compression not supported with VMS\n"); +#else + fprintf(stderr, + "Transparent compression not supported with VMS\n"); + exit(1); +#endif +#else + transparent_compression++; +#endif + break; + case 'x': + case 'm': + /* + * Somehow two options to do basically the same thing + * got added somewhere along the way. The 'match' + * code supports limited globbing, so this is the one + * that got selected. Unfortunately the 'x' switch is + * probably more intuitive. + */ + add_match(optarg); + break; + case OPTION_X_LIST: + add_list(optarg); + break; + case OPTION_I_HIDE: + i_add_match(optarg); + break; + case OPTION_I_LIST: + i_add_list(optarg); + break; + case OPTION_H_HIDE: + h_add_match(optarg); + break; + case OPTION_H_LIST: + h_add_list(optarg); + break; + case OPTION_J_HIDE: + j_add_match(optarg); + break; + case OPTION_J_LIST: + j_add_list(optarg); + break; + case OPTION_HIDE_TRANS_TBL: + jhide_trans_tbl++; + break; + case OPTION_HIDE_RR_MOVED: + hide_rr_moved++; + break; + case OPTION_HELP: + usage(0); + break; + case OPTION_PVERSION: + if(mkisofs_call) + printf("mkisofs 2.01 is not what you see here. This line is only a fake for too clever\n" + "GUIs and other frontend applications. In fact, this program is:\n"); + printf("%s (%s)\n", version_string, HOST_SYSTEM); + exit(0); + break; + case OPTION_NOSPLIT_SL_COMPONENT: + split_SL_component = 0; + break; + case OPTION_NOSPLIT_SL_FIELD: + split_SL_field = 0; + break; + case OPTION_HARD_DISK_BOOT: + use_eltorito++; + hard_disk_boot++; + get_boot_entry(); + current_boot_entry->hard_disk_boot = 1; + break; + case OPTION_NO_EMUL_BOOT: + use_eltorito++; + no_emul_boot++; + get_boot_entry(); + current_boot_entry->no_emul_boot = 1; + break; + case OPTION_NO_BOOT: + use_eltorito++; + not_bootable++; + get_boot_entry(); + current_boot_entry->not_bootable = 1; + break; + case OPTION_BOOT_LOAD_ADDR: + use_eltorito++; + { + long val; + char *ptr; + + val = strtol(optarg, &ptr, 0); + if (*ptr || val < 0 || val >= 0x10000) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Boot image load address invalid.\n"); +#else + fprintf(stderr, "Boot image load address invalid.\n"); + exit(1); +#endif + } + load_addr = val; + } + get_boot_entry(); + current_boot_entry->load_addr = load_addr; + break; + case OPTION_BOOT_LOAD_SIZE: + use_eltorito++; + { + long val; + char *ptr; + + val = strtol(optarg, &ptr, 0); + if (*ptr || val < 0 || val >= 0x10000) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Boot image load size invalid.\n"); +#else + fprintf(stderr, + "Boot image load size invalid.\n"); + exit(1); +#endif + } + load_size = val; + } + get_boot_entry(); + current_boot_entry->load_size = load_size; + break; + case OPTION_BOOT_INFO_TABLE: + use_eltorito++; + boot_info_table++; + get_boot_entry(); + current_boot_entry->boot_info_table = 1; + break; +#ifdef APPLE_HYB + case OPTION_HFS_TYPE: + deftype = optarg; + hfs_ct++; + if (strlen(deftype) != 4) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "HFS default TYPE string has illegal length.\n"); +#else + fprintf(stderr, + "HFS default TYPE string has illegal length.\n"); + exit(1); +#endif + } + break; + case OPTION_HFS_CREATOR: + defcreator = optarg; + hfs_ct++; + if (strlen(defcreator) != 4) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "HFS default CREATOR string has illegal length.\n"); +#else + fprintf(stderr, + "HFS default CREATOR string has illegal length.\n"); + exit(1); +#endif + } + break; + case 'H': + /* FALLTHRU */ + case OPTION_MAP_FILE: + afpfile = optarg; + hfs_last = MAP_LAST; + break; + case 'h': + apple_hyb = 1; + break; + case 'g': + apple_ext = 1; + break; + case OPTION_PROBE: + probe = 1; + break; + case OPTION_MACNAME: + use_mac_name = 1; + break; + case OPTION_NOMACFILES: +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Warning: -no-mac-files no longer used ... ignoring\n"); +#else + fprintf(stderr, + "Warning: -no-mac-files no longer used ... ignoring\n"); +#endif + break; + case OPTION_BOOT_HFS_FILE: + hfs_boot_file = optarg; + /* FALLTHRU */ + case OPTION_GEN_PT: + gen_pt = 1; + break; + case OPTION_MAGIC_FILE: +#ifndef USE_MAGIC + fprintf(stderr, "This program has been compiled without magic library support.\n" + "Ignoring the -magic option.\n"); +#endif + magic_filename = optarg; + hfs_last = MAG_LAST; + break; + case OPTION_AUTOSTART: + autoname = optarg; + /* gen_pt = 1; */ + break; + case OPTION_BSIZE: + afe_size = atoi(optarg); + hfs_select |= DO_FEU; + hfs_select |= DO_FEL; + break; + case OPTION_HFS_VOLID: + hfs_volume_id = optarg; + break; + case OPTION_ROOT_INFO: + root_info = optarg; + /* FALLTHRU */ + case OPTION_ICON_POS: + icon_pos = 1; + break; + /* Mac/Unix types to include */ + case OPTION_CAP: + hfs_select |= DO_CAP; + break; + case OPTION_NETA: + hfs_select |= DO_NETA; + break; + case OPTION_DBL: + hfs_select |= DO_DBL; + break; + case OPTION_ESH: + case OPTION_USH: + hfs_select |= DO_ESH; + break; + case OPTION_FE: + hfs_select |= DO_FEU; + hfs_select |= DO_FEL; + break; + case OPTION_SGI: + case OPTION_XIN: + hfs_select |= DO_SGI; + break; + case OPTION_MBIN: + hfs_select |= DO_MBIN; + break; + case OPTION_SGL: + hfs_select |= DO_SGL; + break; + case OPTION_DAVE: + hfs_select |= DO_DAVE; + break; + case OPTION_SFM: + hfs_select |= DO_SFM; + break; + case OPTION_XDBL: + hfs_select |= DO_XDBL; + break; + case OPTION_XHFS: +#ifdef IS_MACOS_X + hfs_select |= DO_XHFS; +#else /* IS_MACOS_X */ +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Warning: --osx-hfs only works on MacOS X ... ignoring\n"); +#else /* USE_LIBSCHILY */ + fprintf(stderr, + "Warning: --osx-hfs only works on MacOS X ... ignoring\n"); +#endif /* USE_LIBSCHILY */ +#endif /* IS_MACOS_X */ + break; + case OPTION_CREATE_DT: + create_dt = 0; + break; + case OPTION_HFS_HIDE: + hfs_add_match(optarg); + break; + case OPTION_HFS_LIST: + hfs_add_list(optarg); + break; + case OPTION_HFS_INPUT_CHARSET: + use_mac_name = 1; + hfs_icharset = optarg; + break; + case OPTION_HFS_OUTPUT_CHARSET: + hfs_ocharset = optarg; + break; + case OPTION_HFS_UNLOCK: + hfs_lock = 0; + break; + case OPTION_HFS_BLESS: + hfs_bless = optarg; + break; + case OPTION_HFS_PARMS: + hfs_parms = strdup(optarg); + break; +#ifdef PREP_BOOT + case OPTION_PREP_BOOT: + use_prep_boot++; + if (use_prep_boot > 4 - use_chrp_boot) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Maximum of 4 PRep+CHRP partition entries are allowed\n"); +#else + fprintf(stderr, + "Maximum of 4 PRep+CHRP partition entries are allowed\n"); +#endif + exit(1); + } + /* pathname of the boot image on cd */ + prep_boot_image[use_prep_boot - 1] = optarg; + if (prep_boot_image[use_prep_boot - 1] == NULL) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Required PReP boot image pathname missing\n"); +#else + fprintf(stderr, + "Required PReP boot image pathname missing\n"); +#endif + exit(1); + } + break; + case OPTION_CHRP_BOOT: + if (use_chrp_boot) + break; /* silently allow duplicates */ + use_chrp_boot = 1; + if (use_prep_boot > 3) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Maximum of 4 PRep+CHRP partition entries are allowed\n"); +#else + fprintf(stderr, + "Maximum of 4 PRep+CHRP partition entries are allowed\n"); +#endif + exit(1); + } + break; +#endif /* PREP_BOOT */ +#endif /* APPLE_HYB */ + case OPTION_ALLOW_LIMITED_SIZE: + allow_limited_size++; + use_udf++; + break; + default: + susage(1); + } + /* + * "--" was found, the next argument is a pathspec + */ + if (argc != optind) + have_cmd_line_pathspec = 1; + +parse_input_files: + path_ind = optind; + + /* + * XXX This is a hack until we have a decent separate name handling + * XXX for UDF filenames. + */ + if (dvd_video && use_Joliet) { + use_Joliet = 0; + fprintf(stderr, "Warning: Disabling Joliet support for DVD-Video.\n"); + } + if (use_udf && !use_Joliet) + jlen = 255; + + if (preparer) { + if (strlen(preparer) > 128) { + comerrno(EX_BAD, "Preparer string too long\n"); + } + } + if (publisher) { + if (strlen(publisher) > 128) { + comerrno(EX_BAD, + "Publisher string too long\n"); + } + } + if (stream_filename) { + if (strlen(stream_filename) > MAX_ISONAME) + comerrno(EX_BAD, + "stream-file-name too long (%d), max is %d.\n", + (int)strlen(stream_filename), (int)MAX_ISONAME); + if (strchr(stream_filename, '/')) + comerrno(EX_BAD, "Illegal character '/' in stream-file-name.\n"); + iso9660_level = 4; + } else { + stream_filename = "STREAM.IMG;1"; + } + if (system_id) { + if (strlen(system_id) > 32) { + comerrno(EX_BAD, + "System ID string too long\n"); + } + } + + + if (use_RockRidge && (iso9660_namelen > MAX_ISONAME_V2_RR)) + iso9660_namelen = MAX_ISONAME_V2_RR; + + if (warn_violate) /* this one is enough for quiet mode, print others warnings only in more verbose modes */ + fprintf(stderr, "Warning: creating filesystem that does not conform to ISO-9660.\n"); + if (iso9660_level > 3 && verbose>0) + fprintf(stderr, "Warning: Creating ISO-9660:1999 (version 2) filesystem.\n"); + if (iso9660_namelen > LEN_ISONAME && verbose>0) + fprintf(stderr, "Warning: ISO-9660 filenames longer than %d may cause buffer overflows in the OS.\n", + LEN_ISONAME); + if (use_Joliet && !use_RockRidge && verbose>0) { + fprintf(stderr, + "Warning: creating filesystem with Joliet extensions but without Rock Ridge\n" + " extensions. It is highly recommended to add Rock Ridge.\n"); + } + if (transparent_compression && verbose>0) { + fprintf(stderr, "Warning: using transparent compression. This is a nonstandard Rock Ridge\n"); + fprintf(stderr, " extension. The resulting filesystem can only be transparently\n"); + fprintf(stderr, " read on Linux. On other operating systems you need to call\n"); + fprintf(stderr, " mkzftree by hand to decompress the files.\n"); + } + if (transparent_compression && !use_RockRidge && verbose>0) { + fprintf(stderr, "Warning: transparent decompression is a Linux Rock Ridge extension, but\n"); + fprintf(stderr, " creating filesystem without Rock Ridge attributes; files\n"); + fprintf(stderr, " will not be transparently decompressed.\n"); + } + if(follow_links && verbose>0) + fprintf(stderr, + "Warning: -follow-links does not always work correctly; be careful.\n"); + + init_unls(); /* Initialize UNICODE tables */ + + /* initialize code tables from a file - if they exists */ + init_unls_file(icharset); + init_unls_file(ocharset); +#ifdef APPLE_HYB + init_unls_file(hfs_icharset); + init_unls_file(hfs_ocharset); +#endif /* APPLE_HYB */ + +#ifdef USE_ICONV + iconv_possible = !(iso9660_level >= 4 || ((ocharset && + strcmp(ocharset, icharset ? icharset : "")) && + use_RockRidge) || apple_ext || apple_hyb); + + setlocale(LC_CTYPE, ""); + + if (icharset == NULL && iconv_possible) { + char *charset = nl_langinfo(CODESET); + /* set to detected value but only if it is not pure US-ASCII */ + if(charset) { /* workaround for SunOS, iconv is case-sensitive */ + char *t; + charset = strdup(charset); + for(t=charset;*t!='\0';t++) + *t=tolower(*t); + } + + if(strcmp(charset, "ansi_x3.4-1968") != 0) + icharset = charset; + + if(icharset && verbose > 0) + fprintf(stderr, "I: -input-charset not specified, using %s (detected in locale settings)\n", + icharset); + } + + if(iconv_possible) { + /* + * don't care if initialization fails + */ + init_nls_iconv(icharset); + init_nls_iconv(ocharset); + } +#endif + + if (icharset == NULL) { +#if (defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__DJGPP__)) && !defined(IS_CYGWIN_1) + in_nls = load_unls("cp437"); +#else + in_nls = load_unls("iso8859-1"); +#endif + } else { + if (strcmp(icharset, "default") == 0) + in_nls = load_unls_default(); + else + in_nls = load_unls(icharset); + } + /* + * set the output charset to the same as the input or the given output + * charset + */ + if (ocharset == NULL) { + out_nls = in_nls; + } else { + if (strcmp(ocharset, "default") == 0) + out_nls = load_unls_default(); + else + out_nls = load_unls(ocharset); + } + if (in_nls == NULL || out_nls == NULL) { /* Unknown charset specified */ + fprintf(stderr, "Unknown charset\nKnown charsets are:\n"); + list_unls(); /* List all known charset names */ +#ifdef USE_ICONV + fprintf(stderr, "\nAdditional input charsets are available for Joliet through the iconv support." + "\nRun \"iconv -l\" to display them. Iconv charsets cannot be used with HFS, Apple" + "\nextension, ISO9660 version 2 or Rock Ridge.\n"); +#endif + exit(1); + } + + +#ifdef APPLE_HYB + if (hfs_icharset == NULL || strcmp(hfs_icharset, "mac-roman")) { + hfs_inls = load_unls("cp10000"); + } else { + if (strcmp(hfs_icharset, "default") == 0) + hfs_inls = load_unls_default(); + else + hfs_inls = load_unls(hfs_icharset); + } + if (hfs_ocharset == NULL) { + hfs_onls = hfs_inls; + } else { + if (strcmp(hfs_ocharset, "default") == 0) + hfs_onls = load_unls_default(); + else if (strcmp(hfs_ocharset, "mac-roman") == 0) + hfs_onls = load_unls("cp10000"); + else + hfs_onls = load_unls(hfs_ocharset); + } + + if (hfs_inls == NULL || hfs_onls == NULL) { + fprintf(stderr, "Unknown HFS charset\nKnown charsets are:\n"); + list_unls(); + exit(1); + } +#endif /* APPLE_HYB */ + + if (merge_image != NULL) { + if (open_merge_image(merge_image) < 0) { + /* Complain and die. */ +#ifdef USE_LIBSCHILY + comerr("Unable to open previous session image '%s'.\n", + merge_image); +#else + fprintf(stderr, + "Unable to open previous session image '%s'.\n", + merge_image); + exit(1); +#endif + } + } + /* We don't need root privilleges anymore. */ +#ifdef HAVE_SETREUID + if (setreuid(-1, getuid()) < 0) +#else +#ifdef HAVE_SETEUID + if (seteuid(getuid()) < 0) +#else + if (setuid(getuid()) < 0) +#endif +#endif +#ifdef USE_LIBSCHILY + comerr("Panic cannot set back effective uid.\n"); +#else + { + perror("Panic cannot set back effective uid."); + exit(1); + } +#endif + + +#ifdef no_more_needed +#ifdef __NetBSD__ + { + int resource; + struct rlimit rlp; + + if (getrlimit(RLIMIT_DATA, &rlp) == -1) + perror("Warning: getrlimit failed"); + else { + rlp.rlim_cur = 33554432; + if (setrlimit(RLIMIT_DATA, &rlp) == -1) + perror("Warning: setrlimit failed"); + } + } +#endif +#endif /* no_more_needed */ +#ifdef HAVE_SBRK + mem_start = (unsigned long) sbrk(0); +#endif + + /* + * if the -hide-joliet option has been given, set the Joliet option + */ + if (!use_Joliet && j_ishidden()) + use_Joliet++; + +#ifdef APPLE_HYB + if (apple_hyb && apple_ext) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Can't have both -apple and -hfs options"); +#else + fprintf(stderr, "Can't have both -apple and -hfs options"); + exit(1); +#endif + } + /* + * if -probe, -macname, any hfs selection and/or mapping file is given, + * but no HFS option, then select apple_hyb + */ + if (!apple_hyb && !apple_ext) { + if (*afpfile || probe || use_mac_name || hfs_select || + hfs_boot_file || magic_filename || + hfs_ishidden() || gen_pt || autoname || + afe_size || icon_pos || hfs_ct || + hfs_icharset || hfs_ocharset) { + apple_hyb = 1; + } + } + if (apple_ext && hfs_boot_file) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Can't have -hfs-boot-file with -apple\n"); +#else + fprintf(stderr, "Can't have -hfs-boot-file with -apple\n"); + exit(1); +#endif + } + if (apple_ext && autoname) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Can't have -auto with -apple\n"); +#else + fprintf(stderr, "Can't have -auto with -apple\n"); + exit(1); +#endif + } + if (apple_hyb && (use_sparcboot || use_sunx86boot)) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Can't have -hfs with -sparc-boot/-sunx86-boot\n"); +#else + fprintf(stderr, "Can't have -hfs with -sparc-boot/-sunx86-boot\n"); + exit(1); +#endif + } + if (apple_hyb && use_genboot) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Can't have -hfs with -generic-boot\n"); +#else + fprintf(stderr, "Can't have -hfs with -generic-boot\n"); + exit(1); +#endif + } +#ifdef PREP_BOOT + if (apple_ext && use_prep_boot) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Can't have -prep-boot with -apple\n"); +#else + fprintf(stderr, "Can't have -prep-boot with -apple\n"); + exit(1); +#endif + } +#endif /* PREP_BOOT */ + + if (apple_hyb || apple_ext) + apple_both = 1; + + if (probe) + /* we need to search for all types of Apple/Unix files */ + hfs_select = ~0; + + if (apple_both && verbose && !(hfs_select || *afpfile || magic_filename)) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Warning: no Apple/Unix files will be decoded/mapped\n"); +#else + fprintf(stderr, + "Warning: no Apple/Unix files will be decoded/mapped\n"); +#endif + } + if (apple_both && verbose && !afe_size && + (hfs_select & (DO_FEU | DO_FEL))) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Warning: assuming PC Exchange cluster size of 512 bytes\n"); +#else + fprintf(stderr, + "Warning: assuming PC Exchange cluster size of 512 bytes\n"); +#endif + afe_size = 512; + } + if (apple_both) { + /* set up the TYPE/CREATOR mappings */ + hfs_init(afpfile, 0, hfs_select); + } + if (apple_ext && !use_RockRidge) { +#ifdef nonono + /* use RockRidge to set the SystemUse field ... */ + use_RockRidge++; + rationalize_all++; +#else + /* EMPTY */ +#endif + } + if (apple_ext && !(use_XA || use_RockRidge)) { + comerrno(EX_BAD, "Need either -XA/-xa or -R/-r for -apple to become active.\n"); + } + +#endif /* APPLE_HYB */ + + if (rationalize_all) { + rationalize++; + rationalize_uid++; + rationalize_gid++; + rationalize_filemode++; + rationalize_dirmode++; + } + + if (verbose > 1) { + fprintf(stderr, "%s (%s)\n", version_string, HOST_SYSTEM); + } + if (cdrecord_data == NULL && !check_session && merge_image != NULL) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Multisession usage bug: Must specify -C if -M is used.\n"); +#else + fprintf(stderr, + "Multisession usage bug: Must specify -C if -M is used.\n"); + exit(1); +#endif + } + if (cdrecord_data != NULL && merge_image == NULL) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Warning: -C specified without -M: old session data will not be merged.\n"); +#else + fprintf(stderr, + "Warning: -C specified without -M: old session data will not be merged.\n"); +#endif + } +#ifdef APPLE_HYB + if (merge_image != NULL && apple_hyb) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Warning: files from previous sessions will not be included in the HFS volume.\n"); +#else + fprintf(stderr, + "Warning: files from previous sessions will not be included in the HFS volume.\n"); +#endif + } +#endif /* APPLE_HYB */ + + /* + * see if we have a list of pathnames to process + */ + if (pathnames) { + /* "-" means take list from the standard input */ + if (strcmp(pathnames, "-")) { + if ((pfp = fopen(pathnames, "r")) == NULL) { +#ifdef USE_LIBSCHILY + comerr("Unable to open pathname list %s.\n", + pathnames); +#else + fprintf(stderr, + "Unable to open pathname list %s.\n", + pathnames); + exit(1); +#endif + } + } else + pfp = stdin; + } + + /* The first step is to scan the directory tree, and take some notes */ + + if ((arg = get_pnames(argc, argv, optind, pname, + sizeof (pname), pfp)) == NULL) { + if (check_session == 0 && !stream_media_size) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Missing pathspec.\n"); +#endif + susage(1); + } + } + + /* + * if we don't have a pathspec, then save the pathspec found + * in the pathnames file (stored in pname) - we don't want + * to skip this pathspec when we read the pathnames file again + */ + if (!have_cmd_line_pathspec && !stream_media_size) { + save_pname = 1; + } + if (stream_media_size) { + if (use_XA || use_RockRidge || use_udf || use_Joliet) + comerrno(EX_BAD, + "Cannot use XA, Rock Ridge, UDF or Joliet with -stream-media-size\n"); + if (merge_image) + comerrno(EX_BAD, + "Cannot use multi session with -stream-media-size\n"); + if (use_eltorito || use_sparcboot || use_sunx86boot || + use_genboot || use_prep_boot || hfs_boot_file) + comerrno(EX_BAD, + "Cannot use boot options with -stream-media-size\n"); + if (apple_hyb) + comerrno(EX_BAD, + "Cannot use Apple hybrid options with -stream-media-size\n"); + } + + if (use_RockRidge) { + /* BEGIN CSTYLED */ +#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 + /* END CSTYLED */ + } + if (log_file) { + FILE *lfp; + int i; + + /* open log file - test that we can open OK */ + if ((lfp = fopen(log_file, "w")) == NULL) { +#ifdef USE_LIBSCHILY + comerr("Can't open logfile: '%s'.\n", log_file); +#else + fprintf(stderr, "Can't open logfile: '%s'.\n", log_file); + exit(1); +#endif + } + fclose(lfp); + + /* redirect all stderr message to log_file */ + fprintf(stderr, "re-directing all messages to %s\n", log_file); + fflush(stderr); + + /* associate stderr with the log file */ + if (freopen(log_file, "w", stderr) == NULL) { +#ifdef USE_LIBSCHILY + comerr("Can't open logfile: '%s'.\n", log_file); +#else + fprintf(stderr, "Can't open logfile: '%s'.\n", log_file); + exit(1); +#endif + } + if (verbose > 1) { + for (i = 0; i < argc; i++) + fprintf(stderr, "%s ", argv[i]); + + fprintf(stderr, "\n%s (%s)\n", + version_string, HOST_SYSTEM); + } + } + /* Find name of root directory. */ + if (arg != NULL) + node = findgequal(arg); + if (!use_graft_ptrs) + node = NULL; + if (node == NULL) { + if (use_graft_ptrs && arg != NULL) + node = escstrcpy(nodename, arg); + else + node = arg; + } else { + /* + * Remove '\\' escape chars which are located + * before '\\' and '=' chars + */ + node = escstrcpy(nodename, ++node); + } + + /* + * See if boot catalog file exists in root directory, if not we will + * create it. + */ + if (use_eltorito) + init_boot_catalog(node); + + /* + * Find the device and inode number of the root directory. Record this + * in the hash table so we don't scan it more than once. + */ + stat_filter(node, &statbuf); + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + + memset(&de, 0, sizeof (de)); + + /* + * PO: + * Isn't root NULL at this time anyway? + * I think it is created by the first call to + * find_or_create_directory() below. + */ + de.filedir = root; /* We need this to bootstrap */ + + if (cdrecord_data != NULL && merge_image == NULL) { + /* + * in case we want to add a new session, but don't want to + * merge old one + */ + get_session_start(NULL); + } + if (merge_image != NULL) { + char sector[SECTOR_SIZE]; + + errno = 0; + mrootp = merge_isofs(merge_image); + if (mrootp == NULL) { + /* Complain and die. */ +#ifdef USE_LIBSCHILY + if (errno == 0) + errno = -1; + comerr("Unable to find previous session PVD '%s'.\n", + merge_image); +#else + fprintf(stderr, + "Unable to find previous session PVD '%s'.\n", + merge_image); + exit(1); +#endif + } + memcpy(de.isorec.extent, mrootp->extent, 8); + + /* + * Look for RR Attributes in '.' entry of root dir. + * This is the first ISO directory entry in the root dir. + */ + c = isonum_733((unsigned char *)mrootp->extent); +#ifdef USE_SCG + readsecs(c, sector, 1); +#else + lseek(fileno(in_image), c*2048, SEEK_SET); + read(fileno(in_image), sector, sizeof (sector)); +#endif + c = rr_flags((struct iso_directory_record *)sector); + if (c & RR_FLAG_XA) + fprintf(stderr, "XA signatures found\n"); + if (c & RR_FLAG_AA) + fprintf(stderr, "AA signatures found\n"); + if (c & ~(RR_FLAG_XA|RR_FLAG_AA)) { + if (c & RR_FLAG_SP) { + fprintf(stderr, "Rock Ridge signatures found\n"); + } else { + fprintf(stderr, "Bad Rock Ridge signatures found (SU record missing)\n"); + if (!force_rr) + no_rr++; + } + } else { + fprintf(stderr, "NO Rock Ridge present\n"); + if ((c & (RR_FLAG_XA|RR_FLAG_AA)) == 0) { + if (!force_rr) + no_rr++; + } + } + if (no_rr) + fprintf(stderr, "Disabling Rock Ridge / XA / AA\n"); + } + /* + * Create an empty root directory. If we ever scan it for real, + * we will fill in the contents. + */ + find_or_create_directory(NULL, "", &de, TRUE, NULL); + +#ifdef APPLE_HYB + /* may need to set window layout of the volume */ + if (root_info) + set_root_info(root_info); +#endif /* APPLE_HYB */ + + if(optind < argc-1) + merge_warn_msg="NOTE: multiple source directories have been specified and merged into the root\n" + "of the filesystem. Check your program arguments. genisoimage is not tar.\n"; + + /* + * Scan the actual directory (and any we find below it) for files to + * write out to the output image. Note - we take multiple source + * directories and keep merging them onto the image. + */ +if (check_session == 0) + while ((arg = get_pnames(argc, argv, optind, pname, + sizeof (pname), pfp)) != NULL) { + struct directory *graft_dir; + struct stat st; + char *short_name; + int status; + char graft_point[PATH_MAX + 1]; + + /* + * We would like a syntax like: + * + * /tmp=/usr/tmp/xxx + * + * where the user can specify a place to graft each component + * of the tree. To do this, we may have to create directories + * along the way, of course. Secondly, I would like to allow + * the user to do something like: + * + * /home/baz/RMAIL=/u3/users/baz/RMAIL + * + * so that normal files could also be injected into the tree + * at an arbitrary point. + * + * The idea is that the last component of whatever is being + * entered would take the name from the last component of + * whatever the user specifies. + * + * The default will be that the file is injected at the root of + * the image tree. + */ + node = findgequal(arg); + if (!use_graft_ptrs) + node = NULL; + /* + * Remove '\\' escape chars which are located + * before '\\' and '=' chars ---> below in escstrcpy() + */ + + short_name = NULL; + + if (node != NULL || reloc_root) { + char *pnt; + char *xpnt; + size_t len; + int node_is_dir; + + /* insert -root prefix */ + if (reloc_root != NULL) { + strcpy(graft_point, reloc_root); + len = strlen(graft_point); + if (graft_point[len] != '/') { + graft_point[len++] = '/'; + graft_point[len] = '\0'; + } + } else { + len = 0; + } + + if (node) { + *node = '\0'; + escstrcpy(&graft_point[len], arg); + *node = '='; + } + + /* + * Remove unwanted "./" & "/" sequences from start... + */ + do { + xpnt = graft_point; + while (xpnt[0] == '.' && xpnt[1] == '/') + xpnt += 2; + while (*xpnt == PATH_SEPARATOR) { + xpnt++; + } + memmove(graft_point, xpnt, strlen(xpnt)+1); + } while (xpnt > graft_point); + + if (node) { + node = escstrcpy(nodename, ++node); + } else { + node = arg; + } + + graft_dir = root; + xpnt = graft_point; + + /* + * If "node" points to a directory, then graft_point + * needs to point to a directory too. + */ + if (follow_links) + status = stat_filter(node, &st); + else + status = lstat_filter(node, &st); + + node_is_dir = S_ISDIR(st.st_mode); + if (status == 0 && node_is_dir) { + len = strlen(graft_point); + + if ((len <= (sizeof (graft_point) -1)) && + graft_point[len-1] != '/') { + graft_point[len++] = '/'; + graft_point[len] = '\0'; + } + } + if (debug) + fprintf(stderr, "GRAFT:'%s'\n", xpnt); + /* + * Loop down deeper and deeper until we find the + * correct insertion spot. + * Canonicalize the filename while parsing it. + */ + for (;;) { + struct stat* stat_template; + + do { + while (xpnt[0] == '.' && xpnt[1] == '/') + xpnt += 2; + while (xpnt[0] == '/') + xpnt += 1; + if (xpnt[0] == '.' && xpnt[1] == '.' && xpnt[2] == '/') { + if (graft_dir && graft_dir != root) { + graft_dir = graft_dir->parent; + xpnt += 2; + } + } + } while ((xpnt[0] == '/') || (xpnt[0] == '.' && xpnt[1] == '/')); + pnt = strchr(xpnt, PATH_SEPARATOR); + if (pnt == NULL) { + if (*xpnt != '\0') { + short_name = xpnt; + } + break; + } + *pnt = '\0'; + if (debug) { + fprintf(stderr, "GRAFT Point:'%s' in '%s : %s' (%s)\n", + xpnt, + graft_dir->whole_name, + graft_dir->de_name, + graft_point); + } + /* + * If the node being grafted is a + * directory, then we want the last + * directory in this graft chain to have + * the ownership and permissions of the + * source node. Other directories in the + * chain get default ownership and + * permissions. + */ + stat_template = + (pnt[1] == '\0' && node_is_dir) ? &st : 0; + + graft_dir = find_or_create_directory(graft_dir, + graft_point, NULL, TRUE, + stat_template); + + *pnt = PATH_SEPARATOR; + xpnt = pnt + 1; + } + } else { + graft_dir = root; + if (use_graft_ptrs) + node = escstrcpy(nodename, arg); + else + node = arg; + } + + /* + * Get information on the node + */ + if (follow_links) + status = stat_filter(node, &st); + else + status = lstat_filter(node, &st); + if (status != 0) { + /* + * This is a fatal error - the user won't be getting + * what they want if we were to proceed. + */ +#ifdef USE_LIBSCHILY + comerr("Invalid node - '%s'.\n", node); +#else + fprintf(stderr, "Invalid node - '%s'.\n", node); + exit(1); +#endif + } else { + /* + * Now see whether the user wants to add a regular + * file or a directory at this point. + */ + if (S_ISDIR(st.st_mode)) { + if (debug) { + fprintf(stderr, "graft_dir: '%s : %s', node: '%s', (scan)\n", + graft_dir->whole_name, + graft_dir->de_name, node); + } + if (!scan_directory_tree(graft_dir, + node, &de)) { + exit(1); + } + if (debug) { + fprintf(stderr, "scan done\n"); + } + } else { + if (short_name == NULL) { + short_name = strrchr(node, + PATH_SEPARATOR); + if (short_name == NULL || + short_name < node) { + short_name = node; + } else { + short_name++; + } + } + if (debug) { + fprintf(stderr, "graft_dir: '%s : %s', node: '%s', short_name: '%s'\n", + graft_dir->whole_name, + graft_dir->de_name, node, + short_name); + } +#ifdef APPLE_HYB + if (!insert_file_entry(graft_dir, node, + short_name, 0)) +#else + if (!insert_file_entry(graft_dir, node, + short_name)) +#endif /* APPLE_HYB */ + { + /* + * Should we ignore this? + */ +/* exit(1);*/ + /* EMPTY */ + } + } + } + + optind++; + no_path_names = 0; + } + + if (pfp && pfp != stdin) + fclose(pfp); + + /* + * exit if we don't have any pathnames to process + * - not going to happen at the moment as we have to have at least one + * path on the command line + */ + if (no_path_names && !check_session && !stream_media_size) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "No pathnames found.\n"); +#endif + susage(1); + } + /* + * Now merge in any previous sessions. This is driven on the source + * side, since we may need to create some additional directories. + */ + if (merge_image != NULL) { + if (merge_previous_session(root, mrootp, + reloc_root, reloc_old_root) < 0) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Cannot merge previous session.\n"); +#else + fprintf(stderr, "Cannot merge previous session.\n"); + exit(1); +#endif + } + close_merge_image(); + + /* + * set up parent_dir and filedir in relocated entries which + * were read from previous session so that + * finish_cl_pl_entries can do its job + */ + match_cl_re_entries(); + } +#ifdef APPLE_HYB + /* free up any HFS filename mapping memory */ + if (apple_both) + clean_hfs(); +#endif /* APPLE_HYB */ + + /* hide "./rr_moved" if all its contents have been hidden */ + if (reloc_dir && i_ishidden()) + hide_reloc_dir(); + + /* insert the boot catalog if required */ + if (use_eltorito) + insert_boot_cat(); + + /* + * Free up any matching memory + */ + for (n = 0; n < MAX_MAT; n++) + gen_del_match(n); + +#ifdef SORTING + del_sort(); +#endif /* SORTING */ + + /* + * Sort the directories in the required order (by ISO9660). Also, + * choose the names for the 8.3 filesystem if required, and do any + * other post-scan work. + */ + goof += sort_tree(root); + + if (goof) { + fprintf(stderr, "ISO9660/Rock Ridge tree sort failed.\n"); + if(merge_warn_msg) + fprintf(stderr, merge_warn_msg); + exit(1); + } +#ifdef UDF + if (use_Joliet || use_udf) { +#else + if (use_Joliet) { +#endif + goof += joliet_sort_tree(root); + } + if (goof) { + fprintf(stderr, "Joliet tree sort failed. The -joliet-long switch may help you.\n"); + if(merge_warn_msg) + fprintf(stderr, merge_warn_msg); + exit(1); + } + /* + * Fix a couple of things in the root directory so that everything is + * self consistent. Fix this up so that the path tables get done right. + */ + root->self = root->contents; + + /* OK, ready to write the file. Open it up, and generate the thing. */ + if (print_size) { + discimage = fopen("/dev/null", "wb"); + if (!discimage) { +#ifdef USE_LIBSCHILY + comerr("Unable to open /dev/null\n"); +#else + fprintf(stderr, "Unable to open /dev/null\n"); + exit(1); +#endif + } + } else if (outfile && (strcmp (outfile, "-")) != 0) { + discimage = fopen(outfile, "wb"); + if (!discimage) { +#ifdef USE_LIBSCHILY + comerr("Unable to open disc image file '%s'.\n", outfile); +#else + fprintf(stderr, "Unable to open disc image file '%s'.\n", outfile); + exit(1); +#endif + } + if (jtemplate_out || jjigdo_out) { + if (!jtemplate_out || !jjigdo_out || !jmd5_list) { +#ifdef USE_LIBSCHILY + comerr("Bad options - need to specify output names for jigdo and template file, and also the md5-list input file!\n"); +#else + fprintf(stderr, "Bad options - need to specify output names for jigdo and template file, and also the md5-list input file!\n"); + exit(1); +#endif + } + jtjigdo = fopen(jjigdo_out, "wb"); + jttemplate = fopen(jtemplate_out, "wb"); + if (!jtjigdo || !jttemplate) { +#ifdef USE_LIBSCHILY + comerr("Unable to open jigdo template image file\n"); +#else + fprintf(stderr, "Unable to open jigdo template image file\n"); + exit(1); +#endif + } + write_jt_header(jttemplate, jtjigdo); + } + } else if ((outfile == NULL) + && isatty (fileno (stdout))) { + /* FIXME: a cleaner way to override this check? */ + fputs (("image not written to a terminal.\n" + "Use -o - to force the output.\n"), + stderr); + exit (1); + } else { + discimage = stdout; + +#ifdef NEED_O_BINARY + setmode(fileno(stdout), O_BINARY); +#endif + } + + /* Now assign addresses on the disc for the path table. */ + + path_blocks = ISO_BLOCKS(path_table_size); + if (path_blocks & 1) + path_blocks++; + + jpath_blocks = ISO_BLOCKS(jpath_table_size); + if (jpath_blocks & 1) + jpath_blocks++; + + /* + * Start to set up the linked list that we use to track the contents + * of the disc. + */ +#ifdef APPLE_HYB +#ifdef PREP_BOOT + if (apple_hyb || use_prep_boot || use_chrp_boot) +#else /* PREP_BOOT */ + if (apple_hyb) +#endif /* PREP_BOOT */ + outputlist_insert(&hfs_desc); +#endif /* APPLE_HYB */ + if (use_sparcboot || use_sunx86boot) + outputlist_insert(&sunlabel_desc); + if (use_alphaboot) + outputlist_insert(&alphaboot_desc); + if (use_hppaboot) + outputlist_insert(&hppaboot_desc); + if (use_alphaboot || use_hppaboot) + outputlist_insert(&alpha_hppa_boot_desc); + if (use_mipsboot) + outputlist_insert(&mipsboot_desc); + if (use_mipselboot) + outputlist_insert(&mipselboot_desc); + if (use_genboot) + outputlist_insert(&genboot_desc); + outputlist_insert(&startpad_desc); + + /* PVD for disc. */ + outputlist_insert(&voldesc_desc); + + /* SVD for El Torito. MUST be immediately after the PVD! */ + if (use_eltorito) { + outputlist_insert(&torito_desc); + } + /* Enhanced PVD for disc. neded if we write ISO-9660:1999 */ + if (iso9660_level > 3) + outputlist_insert(&xvoldesc_desc); + + /* SVD for Joliet. */ + if (use_Joliet) { + outputlist_insert(&joliet_desc); + } + /* Finally the last volume descriptor. */ + outputlist_insert(&end_vol); + +#ifdef UDF + if (use_udf) { + outputlist_insert(&udf_vol_recognition_area_frag); + } +#endif + + /* Insert the version descriptor. */ + outputlist_insert(&version_desc); + +#ifdef UDF + if (use_udf) { + /* + * Most of the space before sector 256 is wasted when + * UDF is turned on. The waste could be reduced by + * putting the ISO9660/Joliet structures before the + * pad_to_sector_256; the problem is that they might + * overshoot sector 256, so there would have to be some + * ugly logic to detect this case and rearrange things + * appropriately. I don't know if it's worth it. + */ + outputlist_insert(&udf_pad_to_sector_32_frag); + outputlist_insert(&udf_main_seq_frag); + outputlist_insert(&udf_main_seq_copy_frag); + outputlist_insert(&udf_integ_seq_frag); + outputlist_insert(&udf_pad_to_sector_256_frag); + outputlist_insert(&udf_anchor_vol_desc_frag); + outputlist_insert(&udf_file_set_desc_frag); + outputlist_insert(&udf_dirtree_frag); + outputlist_insert(&udf_file_entries_frag); + } +#endif + + /* Now start with path tables and directory tree info. */ + if (!stream_media_size) + outputlist_insert(&pathtable_desc); + else + outputlist_insert(&strpath_desc); + + if (use_Joliet) { + outputlist_insert(&jpathtable_desc); + } + + if (!stream_media_size) + outputlist_insert(&dirtree_desc); + + if (use_Joliet) { + outputlist_insert(&jdirtree_desc); + } + outputlist_insert(&dirtree_clean); + + if (extension_record) { + outputlist_insert(&extension_desc); + } + + if (!stream_media_size) { + outputlist_insert(&files_desc); + } else { + outputlist_insert(&strfile_desc); + outputlist_insert(&strdir_desc); + } + + /* + * Allow room for the various headers we will be writing. + * There will always be a primary and an end volume descriptor. + */ + last_extent = session_start; + + /* + * Calculate the size of all of the components of the disc, and assign + * extent numbers. + */ + for (opnt = out_list; opnt; opnt = opnt->of_next) { + opnt->of_start_extent = last_extent; + if (opnt->of_size != NULL) { + (*opnt->of_size) (last_extent); + } + } + + /* + * Generate the contents of any of the sections that we want to + * generate. Not all of the fragments will do anything here + * - most will generate the data on the fly when we get to the write + * pass. + */ + for (opnt = out_list; opnt; opnt = opnt->of_next) { + if (opnt->of_generate != NULL) { + (*opnt->of_generate) (); + } + } + + /* + * Padding just after the ISO-9660 filesystem. + * + * files_desc does not have an of_size function. For this + * reason, we must insert us after the files content has been + * generated. + */ +#ifdef UDF + if (use_udf) { + /* Single anchor volume descriptor pointer at end */ + outputlist_insert(&udf_end_anchor_vol_desc_frag); + if (udf_end_anchor_vol_desc_frag.of_size != NULL) { + (*udf_end_anchor_vol_desc_frag.of_size) (last_extent); + } + if (dopad) { + /* + * Pad with anchor volume descriptor pointer + * blocks instead of zeroes. + */ + outputlist_insert(&udf_padend_avdp_frag); + if (udf_padend_avdp_frag.of_size != NULL) { + (*udf_padend_avdp_frag.of_size) (last_extent); + } + } + } else +#endif + if (dopad && !(use_sparcboot || use_sunx86boot)) { + outputlist_insert(&endpad_desc); + if (endpad_desc.of_size != NULL) { + (*endpad_desc.of_size) (last_extent); + } + } + c = 0; + if (use_sparcboot) { + if (dopad) { + /* Padding before the boot partitions. */ + outputlist_insert(&interpad_desc); + if (interpad_desc.of_size != NULL) { + (*interpad_desc.of_size) (last_extent); + } + } + c = make_sun_label(); + last_extent += c; + outputlist_insert(&sunboot_desc); + if (dopad) { + outputlist_insert(&endpad_desc); + if (endpad_desc.of_size != NULL) { + (*endpad_desc.of_size) (last_extent); + } + } + } else if (use_sunx86boot) { + if (dopad) { + /* Padding before the boot partitions. */ + outputlist_insert(&interpad_desc); + if (interpad_desc.of_size != NULL) { + (*interpad_desc.of_size) (last_extent); + } + } + c = make_sunx86_label(); + last_extent += c; + outputlist_insert(&sunboot_desc); + if (dopad) { + outputlist_insert(&endpad_desc); + if (endpad_desc.of_size != NULL) { + (*endpad_desc.of_size) (last_extent); + } + } + } + if (print_size > 0) { + if (verbose > 0) + fprintf(stderr, + "Total extents scheduled to be written = %u\n", + (last_extent - session_start)); + printf("%u\n", (last_extent - session_start)); + exit(0); + } + /* + * Now go through the list of fragments and write the data that + * corresponds to each one. + */ + for (opnt = out_list; opnt; opnt = opnt->of_next) { + Uint oext; + + oext = last_extent_written; + if (opnt->of_start_extent != 0 && + opnt->of_start_extent != last_extent_written) { + /* + * Consistency check. + * XXX Should make sure that all entries have + * XXXX of_start_extent set up correctly. + */ + comerrno(EX_BAD, + "Implementation botch: %s should start at %u but starts at %u.\n", + opnt->of_name, opnt->of_start_extent, last_extent_written); + } + if (opnt->of_write != NULL) { + if (verbose > 1) + fprintf(stderr, "Writing: %-40sStart Block %u\n", + opnt->of_name, last_extent_written); + (*opnt->of_write) (discimage); + if (verbose > 1) + fprintf(stderr, "Done with: %-40sBlock(s) %u\n", + opnt->of_name, last_extent_written-oext); + } + } + if (last_extent != last_extent_written) { + comerrno(EX_BAD, + "Implementation botch: FS should end at %u but ends at %u.\n", + last_extent, last_extent_written); + } + + if (jttemplate) { + write_jt_footer(); + fclose(jttemplate); + } + if (jtjigdo) + fclose(jtjigdo); + + if (verbose > 0) { +#ifdef HAVE_SBRK + fprintf(stderr, "Max brk space used %x\n", + (unsigned int)(((unsigned long) sbrk(0)) - mem_start)); +#endif + fprintf(stderr, "%u extents written (%u MB)\n", + last_extent, last_extent >> 9); + } +#ifdef VMS + return (1); +#else + return (0); +#endif +} + +/* + * Find unescaped equal sign in graft pointer string. + */ +char * +findgequal(char *s) +{ + char *p = s; + + while ((p = strchr(p, '=')) != NULL) { + if (p > s && p[-1] != '\\') + return (p); + p++; + } + return (NULL); +} + +/* + * Find unescaped equal sign in string. + */ +static char * +escstrcpy(char *to, char *from) +{ + char *p = to; + + if (debug) + fprintf(stderr, "FROM: '%s'\n", from); + + while ((*p = *from++) != '\0') { + if (*p == '\\') { + if ((*p = *from++) == '\0') + break; + if (*p != '\\' && *p != '=') { + p[1] = p[0]; + *p++ = '\\'; + } + } + p++; + } + if (debug) + fprintf(stderr, "ESC: '%s'\n", to); + return (to); +} + +void * +e_malloc(size_t size) +{ + void *pt = 0; + + if ((size > 0) && ((pt = malloc(size)) == NULL)) { +#ifdef USE_LIBSCHILY + comerr("Not enough memory\n"); +#else + fprintf(stderr, "Not enough memory\n"); + exit(1); +#endif + } + /* + * Not all code is clean yet. + * Filling all allocated data with zeroes will help + * to avoid core dumps. + */ + if (size > 0) /* a workaround for gcc bug gcc.gnu.org/PR25639 */ + memset(pt, 0, size); + return (pt); +} diff --git a/genisoimage/genisoimage.h b/genisoimage/genisoimage.h new file mode 100644 index 0000000..bbedfb0 --- /dev/null +++ b/genisoimage/genisoimage.h @@ -0,0 +1,802 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)genisoimage.h 1.95 05/05/01 joerg */ +/* + * Header file genisoimage.h - assorted structure definitions and typecasts. + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * Copyright (c) 1999,2000-2003 J. Schilling + * + * 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. + */ + +/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */ + +#define APPID_DEFAULT "GENISOIMAGE ISO 9660/HFS FILESYSTEM CREATOR (C) 1993 E.YOUNGDALE (C) 1997-2006 J.PEARSON/J.SCHILLING (C) 2006-2007 CDRKIT TEAM" + + +#include <mconfig.h> /* Must be before stdio.h for LARGEFILE support */ +#include <stdio.h> +#include <statdefs.h> +#include <stdxlib.h> +#include <unixstd.h> /* Needed for for LARGEFILE support */ +#include <strdefs.h> +#include <dirdefs.h> +#include <utypes.h> +#include <standard.h> +#include <libport.h> +#include "scsi.h" +#ifdef JIGDO_TEMPLATE +#include "jte.h" +#endif + +#ifdef DVD_VIDEO +#ifndef UDF +#define UDF +#endif +#endif + +/*#if _LFS_LARGEFILE*/ +#ifdef HAVE_LARGEFILES +/* + * XXX Hack until fseeko()/ftello() are available everywhere or until + * XXX we know a secure way to let autoconf ckeck for fseeko()/ftello() + * XXX without defining FILE_OFFSETBITS to 64 in confdefs.h + */ +# define fseek fseeko +# define ftell ftello +#endif + +#ifndef HAVE_LSTAT +#ifndef VMS +#define lstat stat +#endif +#endif + +#include "iso9660.h" +#include "defaults.h" +#include <unls.h> + +extern struct unls_table *in_nls; /* input UNICODE conversion table */ +extern struct unls_table *out_nls; /* output UNICODE conversion table */ +extern struct unls_table *hfs_inls; /* input HFS UNICODE conversion table */ +extern struct unls_table *hfs_onls; /* output HFS UNICODE conversion table */ + +#ifdef APPLE_HYB +#include "mactypes.h" +#include "hfs.h" + +struct hfs_info { + unsigned char finderinfo[32]; + char name[HFS_MAX_FLEN + 1]; + /* should have fields for dates here as well */ + char *keyname; + struct hfs_info *next; +}; + +#endif /* APPLE_HYB */ + +struct directory_entry { + struct directory_entry *next; + struct directory_entry *jnext; + struct iso_directory_record isorec; + unsigned int starting_block; + off_t size; + unsigned short priority; + unsigned char jreclen; /* Joliet record len */ + char *name; + char *table; + char *whole_name; + struct directory *filedir; + struct directory_entry *parent_rec; + unsigned int de_flags; + ino_t inode; /* Used in the hash table */ + dev_t dev; /* Used in the hash table */ + unsigned char *rr_attributes; + unsigned int rr_attr_size; + unsigned int total_rr_attr_size; + unsigned int got_rr_name; +#ifdef APPLE_HYB + struct directory_entry *assoc; /* entry has a resource fork */ + hfsdirent *hfs_ent; /* HFS parameters */ + off_t hfs_off; /* offset to real start of fork */ + int hfs_type; /* type of HFS Unix file */ +#endif /* APPLE_HYB */ +#ifdef SORTING + int sort; /* sort weight for entry */ +#endif /* SORTING */ +#ifdef UDF + int udf_file_entry_sector; /* also used as UDF unique ID */ +#endif + uint64_t realsize; +}; + +struct file_hash { + struct file_hash *next; + ino_t inode; /* Used in the hash table */ + dev_t dev; /* Used in the hash table */ + nlink_t nlink; /* Used to compute new link count */ + unsigned int starting_block; + off_t size; +#ifdef SORTING + struct directory_entry *de; +#endif /* SORTING */ +}; + + +/* + * This structure is used to control the output of fragments to the cdrom + * image. Everything that will be written to the output image will eventually + * go through this structure. There are two pieces - first is the sizing where + * we establish extent numbers for everything, and the second is when we actually + * generate the contents and write it to the output image. + * + * This makes it trivial to extend genisoimage to write special things in the image. + * All you need to do is hook an additional structure in the list, and the rest + * works like magic. + * + * The three passes each do the following: + * + * The 'size' pass determines the size of each component and assigns the extent number + * for that component. + * + * The 'generate' pass will adjust the contents and pointers as required now that extent + * numbers are assigned. In some cases, the contents of the record are also generated. + * + * The 'write' pass actually writes the data to the disc. + */ +struct output_fragment { + struct output_fragment *of_next; + int (*of_size)(int); + int (*of_generate)(void); + int (*of_write)(FILE *); + char *of_name; /* Textual description */ + unsigned int of_start_extent; /* For consist check */ +}; + +extern struct output_fragment *out_list; +extern struct output_fragment *out_tail; + +extern struct output_fragment startpad_desc; +extern struct output_fragment voldesc_desc; +extern struct output_fragment xvoldesc_desc; +extern struct output_fragment joliet_desc; +extern struct output_fragment torito_desc; +extern struct output_fragment end_vol; +extern struct output_fragment version_desc; +extern struct output_fragment pathtable_desc; +extern struct output_fragment jpathtable_desc; +extern struct output_fragment dirtree_desc; +extern struct output_fragment dirtree_clean; +extern struct output_fragment jdirtree_desc; +extern struct output_fragment extension_desc; +extern struct output_fragment files_desc; +extern struct output_fragment interpad_desc; +extern struct output_fragment endpad_desc; +extern struct output_fragment sunboot_desc; +extern struct output_fragment sunlabel_desc; +extern struct output_fragment genboot_desc; +extern struct output_fragment strfile_desc; +extern struct output_fragment strdir_desc; +extern struct output_fragment strpath_desc; +extern struct output_fragment alphaboot_desc; +extern struct output_fragment hppaboot_desc; +extern struct output_fragment alpha_hppa_boot_desc; +extern struct output_fragment mipsboot_desc; +extern struct output_fragment mipselboot_desc; + +#ifdef APPLE_HYB +extern struct output_fragment hfs_desc; + +#endif /* APPLE_HYB */ +#ifdef DVD_VIDEO +/* + * This structure holds the information necessary to create a valid + * DVD-Video image. Basically it's how much to pad the files so the + * file offsets described in the video_ts.ifo and vts_xx_0.ifo are + * the correct one in the image that we create. + */ +typedef struct { + int realsize_ifo; + int realsize_menu; + int realsize_bup; + int size_ifo; + int size_menu; + int size_title; + int size_bup; + int pad_ifo; + int pad_menu; + int pad_title; + int pad_bup; + int number_of_vob_files; + int realsize_vob[10]; +} title_set_t; + +typedef struct { + int num_titles; + title_set_t *title_set; +} title_set_info_t; +#endif /* DVD_VIDEO */ + +/* + * This structure describes one complete directory. It has pointers + * to other directories in the overall tree so that it is clear where + * this directory lives in the tree, and it also must contain pointers + * to the contents of the directory. Note that subdirectories of this + * directory exist twice in this stucture. Once in the subdir chain, + * and again in the contents chain. + */ +struct directory { + struct directory *next; /* Next directory at same level as this one */ + struct directory *subdir; /* First subdirectory in this directory */ + struct directory *parent; + struct directory_entry *contents; + struct directory_entry *jcontents; + struct directory_entry *self; + char *whole_name; /* Entire path */ + char *de_name; /* Entire path */ + unsigned int ce_bytes; /* Number of bytes of CE entries read */ + /* for this dir */ + unsigned int depth; + unsigned int size; + unsigned int extent; + unsigned int jsize; + unsigned int jextent; + unsigned int path_index; + unsigned int jpath_index; + unsigned short dir_flags; + unsigned short dir_nlink; +#ifdef APPLE_HYB + hfsdirent *hfs_ent; /* HFS parameters */ + struct hfs_info *hfs_info; /* list of info for all entries in dir */ +#endif /* APPLE_HYB */ +#ifdef SORTING + int sort; /* sort weight for child files */ +#endif /* SORTING */ +}; + +struct deferred_write { + struct deferred_write *next; + char *table; + unsigned int extent; + off_t size; + char *name; + struct directory_entry *s_entry; + unsigned int pad; + off_t off; +}; + +struct eltorito_boot_entry_info { + struct eltorito_boot_entry_info *next; + char *boot_image; + int not_bootable; + int no_emul_boot; + int hard_disk_boot; + int boot_info_table; + int load_size; + int load_addr; +}; + +extern int goof; +extern struct directory *root; +extern struct directory *reloc_dir; +extern unsigned int next_extent; +extern unsigned int last_extent; +extern unsigned int last_extent_written; +extern unsigned int session_start; + +extern unsigned int path_table_size; +extern unsigned int path_table[4]; +extern unsigned int path_blocks; +extern char *path_table_l; +extern char *path_table_m; + +extern unsigned int jpath_table_size; +extern unsigned int jpath_table[4]; +extern unsigned int jpath_blocks; +extern char *jpath_table_l; +extern char *jpath_table_m; + +extern struct iso_directory_record root_record; +extern struct iso_directory_record jroot_record; + +extern int check_oldnames; +extern int check_session; +extern int use_eltorito; +extern int hard_disk_boot; +extern int not_bootable; +extern int no_emul_boot; +extern int load_addr; +extern int load_size; +extern int boot_info_table; +extern int use_RockRidge; +extern int osecsize; +extern int use_XA; +extern int use_Joliet; +extern int rationalize; +extern int rationalize_uid; +extern int rationalize_gid; +extern int rationalize_filemode; +extern int rationalize_dirmode; +extern uid_t uid_to_use; +extern gid_t gid_to_use; +extern int filemode_to_use; +extern int dirmode_to_use; +extern int new_dir_mode; +extern int follow_links; +extern int cache_inodes; +extern int verbose; +extern int debug; +extern int gui; +extern int all_files; +extern int generate_tables; +extern int print_size; +extern int split_output; +extern int use_graft_ptrs; +extern int jhide_trans_tbl; +extern int hide_rr_moved; +extern int omit_period; +extern int omit_version_number; +extern int no_rr; +extern int transparent_compression; +extern Uint RR_relocation_depth; +extern int iso9660_level; +extern int iso9660_namelen; +extern int full_iso9660_filenames; +extern int relaxed_filenames; +extern int allow_lowercase; +extern int allow_multidot; +extern int iso_translate; +extern int allow_leading_dots; +extern int use_fileversion; +extern int split_SL_component; +extern int split_SL_field; +extern char *trans_tbl; +char *outfile; + +#define JMAX 64 /* maximum Joliet file name length (spec) */ +#define JLONGMAX 103 /* out of spec Joliet file name length */ +extern int jlen; /* selected maximum Joliet file name length */ + +#ifdef DVD_VIDEO +extern int dvd_video; +#endif /* DVD_VIDEO */ + + +#ifdef APPLE_HYB +extern int apple_hyb; /* create HFS hybrid */ +extern int apple_ext; /* use Apple extensions */ +extern int apple_both; /* common flag (for above) */ +extern int hfs_extra; /* extra ISO extents (hfs_ce_size) */ +extern hce_mem *hce; /* libhfs/genisoimage extras */ +extern int use_mac_name; /* use Mac name for ISO9660/Joliet/RR */ +extern int create_dt; /* create the Desktp files */ +extern char *hfs_boot_file; /* name of HFS boot file */ +extern char *magic_filename; /* magic file for CREATOR/TYPE matching */ +extern int hfs_last; /* order in which to process map/magic files */ +extern char *deftype; /* default Apple TYPE */ +extern char *defcreator; /* default Apple CREATOR */ +extern int gen_pt; /* generate HFS partition table */ +extern char *autoname; /* Autostart filename */ +extern int afe_size; /* Apple File Exchange block size */ +extern char *hfs_volume_id; /* HFS volume ID */ +extern int icon_pos; /* Keep Icon position */ +extern int hfs_lock; /* lock HFS volume (read-only) */ +extern char *hfs_bless; /* name of folder to 'bless' (System Folder) */ +extern char *hfs_parms; /* low level HFS parameters */ + +#define MAP_LAST 1 /* process magic then map file */ +#define MAG_LAST 2 /* process map then magic file */ + +#ifndef PREP_BOOT +#define PREP_BOOT +#endif /* PREP_BOOT */ + +#ifdef PREP_BOOT +extern char *prep_boot_image[4]; +extern int use_prep_boot; +extern int use_chrp_boot; + +#endif /* PREP_BOOT */ +#endif /* APPLE_HYB */ + +#ifdef SORTING +extern int do_sort; +#endif /* SORTING */ + +/* tree.c */ +extern int stat_filter(char *, struct stat *); +extern int lstat_filter(char *, struct stat *); +extern int sort_tree(struct directory *); +extern struct directory * +find_or_create_directory(struct directory *, const char *, + struct directory_entry *self, + int, + struct stat *stat_template); +extern void finish_cl_pl_entries(void); +extern int scan_directory_tree(struct directory *this_dir, char *path, + struct directory_entry *self); + +#ifdef APPLE_HYB +extern int insert_file_entry(struct directory *, char *, char *, int); +#else +extern int insert_file_entry(struct directory *, char *, char *); +#endif /* APPLE_HYB */ + +extern void generate_iso9660_directories(struct directory *, FILE *); +extern void dump_tree(struct directory * node); +extern struct directory_entry * +search_tree_file(struct directory * node, char *filename); +extern void update_nlink_field(struct directory * node); +extern void init_fstatbuf(void); +extern struct stat root_statbuf; +extern struct stat fstatbuf; + +/* eltorito.c */ +extern void init_boot_catalog(const char *path); +extern void insert_boot_cat(void); +extern void get_boot_entry(void); +extern void new_boot_entry(void); + +/* boot.c */ +extern void sparc_boot_label(char *label); +extern void sunx86_boot_label(char *label); +extern void scan_sparc_boot(char *files); +extern void scan_sunx86_boot(char *files); +extern int make_sun_label(void); +extern int make_sunx86_label(void); + +/* boot-alpha.c */ +extern int add_boot_alpha_filename(char *filename); + +/* boot-hppa.c */ +extern int add_boot_hppa_cmdline(char *cmdline); +extern int add_boot_hppa_kernel_32(char *filename); +extern int add_boot_hppa_kernel_64(char *filename); +extern int add_boot_hppa_bootloader(char *filename); +extern int add_boot_hppa_ramdisk(char *filename); + +/* boot-mips.c */ +extern int add_boot_mips_filename(char *filename); + +/* boot-mipsel.c */ +extern int add_boot_mipsel_filename(char *filename); + +/* rsync.c */ +extern unsigned long long rsync64(unsigned char *mem, size_t size); + +/* write.c */ +extern int get_731(char *); +extern int get_732(char *); +extern int get_733(char *); +extern int isonum_733(unsigned char *); +extern void set_723(char *, unsigned int); +extern void set_731(char *, unsigned int); +extern void set_721(char *, unsigned int); +extern void set_733(char *, unsigned int); +extern int sort_directory(struct directory_entry **, int); +extern void generate_one_directory(struct directory *, FILE *); +extern void memcpy_max(char *, char *, int); +extern int oneblock_size(int starting_extent); +extern struct iso_primary_descriptor vol_desc; +extern void xfwrite(void *buffer, int size, int count, FILE *file, int submode, + BOOL islast); +extern void set_732(char *pnt, unsigned int i); +extern void set_722(char *pnt, unsigned int i); +extern void outputlist_insert(struct output_fragment * frag); + +#ifdef APPLE_HYB +extern Ulong get_adj_size(int Csize); +extern int adj_size(int Csize, int start_extent, int extra); +extern void adj_size_other(struct directory * dpnt); +extern int insert_padding_file(int size); +extern int gen_mac_label(struct deferred_write *); + +#ifdef PREP_BOOT +extern void gen_prepboot_label(unsigned char *); + +#endif /* PREP_BOOT */ +#endif /* APPLE_HYB */ + +/* multi.c */ + +extern FILE *in_image; +extern int open_merge_image(char *path); +extern int close_merge_image(void); +extern struct iso_directory_record * +merge_isofs(char *path); +extern unsigned char *parse_xa(unsigned char *pnt, int *lenp, + struct directory_entry *dpnt); +extern int rr_flags(struct iso_directory_record *idr); +extern int merge_previous_session(struct directory *, + struct iso_directory_record *, + char *, char *); +extern int get_session_start(int *); + +/* joliet.c */ +#ifdef UDF +# ifdef USE_ICONV +extern size_t convert_to_unicode (unsigned char *buffer, + int size, char *source, struct unls_table *inls); +# else +extern void convert_to_unicode (unsigned char *buffer, + int size, char *source, struct unls_table *inls); +# endif +extern int joliet_strlen (const char *string, struct unls_table *inls); +#endif +extern unsigned char conv_charset(unsigned char, struct unls_table *, + struct unls_table *); +extern int joliet_sort_tree(struct directory * node); + +/* match.c */ +extern int matches(char *); +extern int add_match(char *); + +/* files.c */ +struct dirent *readdir_add_files(char **, char *, DIR *); + +/* name.c */ + +extern void iso9660_check(struct iso_directory_record *idr, + struct directory_entry *ndr); +extern int iso9660_file_length(const char *name, + struct directory_entry *sresult, int flag); + +/* various */ +extern int iso9660_date(char *, time_t); +extern void add_hash(struct directory_entry *); +extern struct file_hash *find_hash(dev_t, ino_t); + +extern void flush_hash(void); +extern void add_directory_hash(dev_t, ino_t); +extern struct file_hash *find_directory_hash(dev_t, ino_t); +extern void flush_file_hash(void); +extern int delete_file_hash(struct directory_entry *); +extern struct directory_entry *find_file_hash(char *); +extern void add_file_hash(struct directory_entry *); + +extern int generate_xa_rr_attributes(char *, char *, struct directory_entry *, + struct stat *, struct stat *, + int deep_flag); +extern char *generate_rr_extension_record(char *id, char *descriptor, + char *source, int *size); + +extern int check_prev_session(struct directory_entry **, int len, + struct directory_entry *, struct stat *, + struct stat *, struct directory_entry **); + +extern void match_cl_re_entries(void); +extern void finish_cl_pl_for_prev_session(void); +extern char *find_rr_attribute(unsigned char *pnt, int len, char *attr_type); + +#ifdef APPLE_HYB +/* volume.c */ +extern int make_mac_volume(struct directory * dpnt, int start_extent); +extern int write_fork(hfsfile * hfp, long tot); + +/* apple.c */ + +extern void del_hfs_info(struct hfs_info *); +extern int get_hfs_dir(char *, char *, struct directory_entry *); +extern int get_hfs_info(char *, char *, struct directory_entry *); +extern int get_hfs_rname(char *, char *, char *); +extern int hfs_exclude(char *); +extern void print_hfs_info(struct directory_entry *); +extern void hfs_init(char *, unsigned short, unsigned int); +extern void delete_rsrc_ent(struct directory_entry *); +extern void clean_hfs(void); +extern void perr(char *); +extern void set_root_info(char *); + +/* desktop.c */ + +extern int make_desktop(hfsvol *, int); + +/* mac_label.c */ + +#ifdef _MAC_LABEL_H +#ifdef PREP_BOOT +extern void gen_prepboot_label(MacLabel * mac_label); +#endif +extern int gen_mac_label(defer *); +#endif +extern int autostart(void); + +/* libfile */ + +extern char *get_magic_match(const char *); +extern void clean_magic(void); + +#endif /* APPLE_HYB */ + +extern char *extension_record; +extern int extension_record_extent; +extern int n_data_extents; + +/* + * These are a few goodies that can be specified on the command line, and are + * filled into the root record + */ +extern char *preparer; +extern char *publisher; +extern char *copyright; +extern char *biblio; +extern char *abstract; +extern char *appid; +extern char *volset_id; +extern char *system_id; +extern char *volume_id; +extern char *boot_catalog; +extern char *boot_image; +extern char *genboot_image; +extern int ucs_level; +extern int volume_set_size; +extern int volume_sequence_number; + +extern struct eltorito_boot_entry_info *first_boot_entry; +extern struct eltorito_boot_entry_info *last_boot_entry; +extern struct eltorito_boot_entry_info *current_boot_entry; + +extern char *findgequal(char *); +extern void *e_malloc(size_t); + +/* + * Note: always use these macros to avoid problems. + * + * ISO_ROUND_UP(X) may cause an integer overflow and thus give + * incorrect results. So avoid it if possible. + * + * ISO_BLOCKS(X) is overflow safe. Prefer this when ever it is possible. + */ +#define SECTOR_SIZE (2048) +#define ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1)) +#define ISO_BLOCKS(X) (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0)) + +#define ROUND_UP(X, Y) (((X + (Y - 1)) / Y) * Y) + +#ifdef APPLE_HYB +/* + * ISO blocks == 2048, HFS blocks == 512 + */ +#define HFS_BLK_CONV (SECTOR_SIZE/HFS_BLOCKSZ) + +#define HFS_ROUND_UP(X) ISO_ROUND_UP(((X)*HFS_BLOCKSZ)) /* XXX ??? */ +#define HFS_BLOCKS(X) (ISO_BLOCKS(X) * HFS_BLK_CONV) + +#define USE_MAC_NAME(E) (use_mac_name && ((E)->hfs_ent != NULL) && (E)->hfs_type) +#endif /* APPLE_HYB */ + +/* + * Rock Ridge defines + */ +#define NEED_RE 1 /* Need Relocated Direcotry */ +#define NEED_PL 2 /* Need Parent link */ +#define NEED_CL 4 /* Need Child link */ +#define NEED_CE 8 /* Need Continuation Area */ +#define NEED_SP 16 /* Need SUSP record */ + +#define RR_FLAG_PX 1 /* POSIX attributes */ +#define RR_FLAG_PN 2 /* POSIX device number */ +#define RR_FLAG_SL 4 /* Symlink */ +#define RR_FLAG_NM 8 /* Alternate Name */ +#define RR_FLAG_CL 16 /* Child link */ +#define RR_FLAG_PL 32 /* Parent link */ +#define RR_FLAG_RE 64 /* Relocated Direcotry */ +#define RR_FLAG_TF 128 /* Time stamp */ + +#define RR_FLAG_SP 1024 /* SUSP record */ +#define RR_FLAG_AA 2048 /* Apple Signature record */ +#define RR_FLAG_XA 4096 /* XA signature record */ + +#define RR_FLAG_CE 8192 /* SUSP Continuation aerea */ +#define RR_FLAG_ER 16384 /* Extension record for RR signature */ +#define RR_FLAG_RR 32768 /* RR Signature in every file */ +#define RR_FLAG_ZF 65535 /* Linux compression extension */ + + +#define PREV_SESS_DEV (sizeof (dev_t) >= 4 ? 0x7ffffffd : 0x7ffd) +#define TABLE_INODE (sizeof (ino_t) >= 4 ? 0x7ffffffe : 0x7ffe) +#define UNCACHED_INODE (sizeof (ino_t) >= 4 ? 0x7fffffff : 0x7fff) +#define UNCACHED_DEVICE (sizeof (dev_t) >= 4 ? 0x7fffffff : 0x7fff) + +#ifdef VMS +#define STAT_INODE(X) (X.st_ino[0]) +#define PATH_SEPARATOR ']' +#define SPATH_SEPARATOR "" +#else +#define STAT_INODE(X) (X.st_ino) +#define PATH_SEPARATOR '/' +#define SPATH_SEPARATOR "/" +#endif + +/* + * When using multi-session, indicates that we can reuse the + * TRANS.TBL information for this directory entry. If this flag + * is set for all entries in a directory, it means we can just + * reuse the TRANS.TBL and not generate a new one. + */ +#define SAFE_TO_REUSE_TABLE_ENTRY 0x01 /* de_flags only */ +#define DIR_HAS_DOT 0x02 /* dir_flags only */ +#define DIR_HAS_DOTDOT 0x04 /* dir_flags only */ +#define INHIBIT_JOLIET_ENTRY 0x08 +#define INHIBIT_RR_ENTRY 0x10 /* not used */ +#define RELOCATED_DIRECTORY 0x20 /* de_flags only */ +#define INHIBIT_ISO9660_ENTRY 0x40 +#define MEMORY_FILE 0x80 /* de_flags only */ +#define HIDDEN_FILE 0x100 /* de_flags only */ +#define DIR_WAS_SCANNED 0x200 /* dir_flags only */ + +/* + * Volume sequence number to use in all of the iso directory records. + */ +#define DEF_VSN 1 + +/* + * Make sure we have a definition for this. If not, take a very conservative + * guess. + * POSIX requires the max pathname component lenght to be defined in limits.h + * If variable, it may be undefined. If undefined, there should be + * a definition for _POSIX_NAME_MAX in limits.h or in unistd.h + * As _POSIX_NAME_MAX is defined to 14, we cannot use it. + * XXX Eric's wrong comment: + * XXX From what I can tell SunOS is the only one with this trouble. + */ +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +#ifndef NAME_MAX +#ifdef FILENAME_MAX +#define NAME_MAX FILENAME_MAX +#else +#define NAME_MAX 256 +#endif +#endif + +#ifndef PATH_MAX +#ifdef FILENAME_MAX +#define PATH_MAX FILENAME_MAX +#else +#define PATH_MAX 1024 +#endif +#endif + +/* + * XXX JS: Some structures have odd lengths! + * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length. + * For this reason, we cannot use sizeof (struct iso_path_table) or + * sizeof (struct iso_directory_record) to compute on disk sizes. + * Instead, we use offsetof(..., name) and add the name size. + * See iso9660.h + */ +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +/* + * EB: various shared stuff + */ +extern char *merge_warn_msg; diff --git a/genisoimage/genisoimagerc.5 b/genisoimage/genisoimagerc.5 new file mode 100644 index 0000000..71082b4 --- /dev/null +++ b/genisoimage/genisoimagerc.5 @@ -0,0 +1,144 @@ +.\" genisoimagerc.5 -*- nroff -*- +.\" Derived from genisoimage.1 +.\" Copyright 1993-1998 by Yggdrasil Computing +.\" Copyright 1996-1997 by Robert Leslie +.\" Copyright 1997-2001 by James Pearson +.\" Copyright 1999-2006 by Joerg Schilling +.\" Copyright 2002-2003 by Jungshik Shin +.\" Copyright 2003 by Jaakko Heinonen +.\" Copyright 2006 by the Cdrkit maintainers +.\" +.TH GENISOIMAGERC 5 "13 Dec 2006" +.\" ---------------------------------------- +.SH NAME +genisoimagerc \- startup configuration file for genisoimage +.SH DESCRIPTION +.BR genisoimage (1) +searches for a configuration file in several places; it uses the first +one it is able to open. First, if the +.B GENISOIMAGERC +environment variable is set, its value is used as the filename; +likewise for the +.B MKISOFSRC +environment variable. Next, +.B genisoimage +looks for files named +.IR .genisoimagerc " or " .mkisofsrc , +first in the current working directory, then in the user's home +directory. Next, it looks for +.IR /etc/genisoimagerc . +Finally, it looks for a +.I .genisoimagerc +in the same directory as +.B genisoimage +itself is stored. +.PP +The +.I .genisoimagerc +file contains lines of the form +.IP +.BI TAG= value +.PP +where +.B TAG +is one of the settings defined below. The case of the tag is not +significant. All settings have command-line equivalents; if the +command-line parameter is specified, it takes priority over the +configuration file. +.PP +Blank lines and lines beginning with `#' are ignored. +.\" ---------------------------------------- +.SH "CONFIGURATION SETTINGS" +.IP ABST +The abstract information, typically the name of a file on the disc +containing an abstract. There is space for 37 characters. +Equivalent to the +.B \-abstract +command-line option. +.IP APPI +The application identifier should describe the application that will be +on the disc. There is space for 128 characters. Equivalent to the +.B \-A +command-line option. +.IP BIBL +The bibliographic information, often the name of a file on the disc +containing a bibliography. There is space for 37 characters. +Equivalent to the +.B \-biblio +command-line option. +.IP COPY +The copyright information, typically the name of a file on the disc +containing the copyright notice. There is space for 37 characters. +Equivalent to the +.B \-copyright +command-line option. +.IP HFS_TYPE +The default +.B TYPE +for Macintosh files. Must be exactly 4 characters. Equivalent to the +.B \-hfs\-type +command-line option. The default value is +.IR TEXT . +.IP HFS_CREATOR +The default +.B CREATOR +for Macintosh files. Must be exactly 4 characters. Equivalent to the +.B \-hfs\-creator +command-line option. The default value is +.IR Unix . +.IP PREP +This should describe the preparer of the CD-ROM, usually with a mailing +address and phone number. There is space for 128 characters. +Equivalent to the +.B \-p +command-line option. +.IP PUBL +This should describe the publisher of the CD-ROM, usually with a +mailing address and phone number. There is space for 128 characters. +Equivalent to the +.B \-publisher +command-line option. +.IP SYSI +The System Identifier. There is space for 32 characters. +Equivalent to the +.B \-sysid +command-line option. +.IP VOLI +The Volume Identifier. There is space for 32 characters. +Equivalent to the +.B \-V +command-line option. +.IP VOLS +The Volume Set Name. There is space for 128 characters. +Equivalent to the +.B \-volset +command-line option. +.PP +.B genisoimage +can also be configured at compile time with defaults for many of these +fields. See the file +.IR defaults.h . +.\" ---------------------------------------- +.SH EXAMPLES +The following file +.IP +.nf +COPY=src/COPYING +SYSI=Multics 75 +.fi +.PP +is equivalent to the +.B genisoimage +command-line parameters +.IP +.I "\-copyright src/COPYING \-sysid \(dqMultics 75\(dq" +.\" ---------------------------------------- +.SH "SEE ALSO" +.BR genisoimage (1). +.\" ---------------------------------------- +.SH AUTHORS +See the +.BR genisoimage (1) +manual page for credits for the +.B genisoimage +program and documentation. diff --git a/genisoimage/getopt.c b/genisoimage/getopt.c new file mode 100644 index 0000000..64fcb18 --- /dev/null +++ b/genisoimage/getopt.c @@ -0,0 +1,790 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)getopt.c 1.6 03/03/09 joerg */ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95 + Free Software Foundation, Inc. + +This file is part of the libiberty library. This library 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 library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. + Ditto for AIX 3.2 and <stdlib.h>. */ +/* + * XXX Never do it this way, it is FSF junk + */ +#ifndef _NO_PROTO +/*#define _NO_PROTO*/ +#endif +/* + * We do this instead: + */ +#undef getopt +#define getopt __nothing__ + +#ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +/* We use <config.h> instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include <config.h> +#else +#include "config.h" +#endif +#endif + +#ifndef __STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ +/* Many versions of the Linux C library include older, broken versions + of these routines, which will break the linker's command-line + parsing. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include <stdlib.h> +#define __DID_STDLIB__ /* FSF rubbish compensation */ +#endif /* GNU C library. */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +static void exchange(char **argv); +static const char *_getopt_initialize(const char *optstring); + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include <string.h> +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char *my_index(const char *str, int chr); + +static char * +my_index (const char *str, int chr) +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#ifndef __STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +#ifndef __DID_STDLIB__ /* FSF rubbish compensation */ +/* + * This is the clean code using Schily constructs... + */ +#undef getopt +#define getopt __nothing__ +#include <stdxlib.h> +#endif +#ifndef my_index +/* + * FSF rubbish compensation + * If GCC has problems with the system include files, it has to be fixed + */ +#include <strdefs.h> +#endif +#undef getopt + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (char **argv) +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +static const char * +_getopt_initialize (const char *optstring) +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (getenv ("POSIXLY_CORRECT") != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (int argc, char *const *argv, const char *optstring, + const struct option *longopts, int *longind, int long_only) +{ + optarg = NULL; + + if (optind == 0) + optstring = _getopt_initialize (optstring); + + if (argc == 0) + return EOF; + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0')) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if (nameend - nextchar == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); + } + optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (int argc, char *const *argv, const char *optstring) +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (int argc, char *argv[]) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/genisoimage/getopt.h b/genisoimage/getopt.h new file mode 100644 index 0000000..e2eb2b7 --- /dev/null +++ b/genisoimage/getopt.h @@ -0,0 +1,148 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)getopt.h 1.3 03/03/06 eric */ +/* Declarations for getopt. + Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifndef _MCONFIG_H +#include <mconfig.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +/*#if __STDC__*/ +#ifdef PROTOTYPES + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +/*#if __STDC__*/ +#ifdef PROTOTYPES +#if defined(__GNU_LIBRARY__) +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* not __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* not __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/genisoimage/getopt1.c b/genisoimage/getopt1.c new file mode 100644 index 0000000..9c51b0c --- /dev/null +++ b/genisoimage/getopt1.c @@ -0,0 +1,193 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)getopt1.c 1.1 97/11/04 eric */ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +/* We use <config.h> instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include <config.h> +#else +#include "config.h" +#endif +#endif + +#include "getopt.h" + +#ifndef __STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ +/* Many versions of the Linux C library include older, broken versions + of these routines, which will break the linker's command-line + parsing. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include <stdlib.h> +#else +char *getenv (); +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (int argc, char *const *argv, const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (int argc, char *const *argv, const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +#include <stdio.h> + +int +main (int argc, char *argv[]) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == EOF) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/genisoimage/hash.c b/genisoimage/hash.c new file mode 100644 index 0000000..054aea6 --- /dev/null +++ b/genisoimage/hash.c @@ -0,0 +1,404 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)hash.c 1.18 04/06/18 joerg */ +/* @(#)hash.c 1.23 06/10/04 joerg */ +/* + * File hash.c - generate hash tables for iso9660 filesystem. + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * Copyright (c) 1999,2000-2006 J. Schilling + * + * 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. + */ + +/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */ + +/* + * From jb@danware.dk: + * + * Cygwin fakes inodes by hashing file info, actual collisions observed! + * This is documented in the cygwin source, look at winsup/cygwin/path.cc + * and search for the word 'Hash'. On NT, cygwin ORs together the + * high and low 32 bits of the 64 bit genuine inode, look at fhandler.cc. + * + * Note: Other operating systems which support the FAT filesystem may + * have the same problem because FAT does not use the inode + * concept. For NTFS, genuine inode numbers exist, but they are + * 64 bits and available only through an open file handle. + * + * The solution is the new options -no-cache-inodes/-cache-inodes that + * allow to disable the genisoimage inode cache. + */ + +#include <mconfig.h> +#include "genisoimage.h" +#include <schily.h> + +#define NR_HASH (16*1024) + +#define HASH_FN(DEV, INO) ((DEV + INO + (INO >> 8) + (INO << 16)) % NR_HASH) + +static struct file_hash *hash_table[NR_HASH]; + +void add_hash(struct directory_entry *spnt); +struct file_hash *find_hash(dev_t dev, ino_t inode); +void flush_hash(void); +void add_directory_hash(dev_t dev, ino_t inode); +struct file_hash *find_directory_hash(dev_t dev, ino_t inode); +static unsigned int name_hash(const char *name); +void add_file_hash(struct directory_entry *de); +struct directory_entry *find_file_hash(char *name); +static BOOL isoname_endsok(char *name); +int delete_file_hash(struct directory_entry *de); +void flush_file_hash(void); + +void +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) { + comerrno(EX_BAD, + "Non zero-length file '%s' assigned zero extent.\n", + spnt->name); + }; + + if (!cache_inodes) + return; + if (spnt->dev == UNCACHED_DEVICE && + (spnt->inode == TABLE_INODE || spnt->inode == UNCACHED_INODE)) { + return; + } + hash_number = HASH_FN((unsigned int) spnt->dev, + (unsigned int) spnt->inode); + +#if 0 + if (verbose > 1) + 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->nlink = 0; + s_hash->starting_block = spnt->starting_block; + s_hash->size = spnt->size; +#ifdef SORTING + s_hash->de = spnt; +#endif /* SORTING */ + hash_table[hash_number] = s_hash; +} + +struct file_hash * +find_hash(dev_t dev, ino_t inode) +{ + unsigned int hash_number; + struct file_hash *spnt; + + if (!cache_inodes) + return (NULL); + if (dev == UNCACHED_DEVICE && + (inode == TABLE_INODE || inode == UNCACHED_INODE)) + return (NULL); + + hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode); + spnt = hash_table[hash_number]; + while (spnt) { + if (spnt->inode == inode && spnt->dev == dev) + return (spnt); + spnt = spnt->next; + }; + return (NULL); +} + +/* + * based on flush_file_hash() below - needed as we want to re-use the + * file hash table. + */ +void +flush_hash() +{ + struct file_hash *fh; + struct file_hash *fh1; + int i; + + for (i = 0; i < NR_HASH; i++) { + fh = hash_table[i]; + while (fh) { + fh1 = fh->next; + free(fh); + fh = fh1; + } + hash_table[i] = NULL; + } +} + +static struct file_hash *directory_hash_table[NR_HASH]; + +void +add_directory_hash(dev_t dev, ino_t inode) +{ + struct file_hash *s_hash; + unsigned int hash_number; + + if (!cache_inodes) + return; + if (dev == UNCACHED_DEVICE && + (inode == TABLE_INODE || 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; + s_hash->nlink = 0; + directory_hash_table[hash_number] = s_hash; +} + +struct file_hash * +find_directory_hash(dev_t dev, ino_t inode) +{ + unsigned int hash_number; + struct file_hash *spnt; + + if (!cache_inodes) + return (NULL); + if (dev == UNCACHED_DEVICE && + (inode == TABLE_INODE || inode == UNCACHED_INODE)) + return (NULL); + + hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode); + 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; + int sum; +}; + +#define NR_NAME_HASH (256*1024) + +static struct name_hash *name_hash_table[NR_NAME_HASH] = {0, }; + +/* + * Find the hash bucket for this name. + */ +static unsigned int +name_hash(const char *name) +{ + unsigned int hash = 0; + const char *p; + + p = name; + + while (*p) { + /* + * Don't hash the iso9660 version number. + * This way we can detect duplicates in cases where we have + * directories (i.e. foo) and non-directories (i.e. foo;1). + */ + if (*p == ';') { + break; + } + hash = (hash << 15) + (hash << 3) + (hash >> 3) + (*p++ & 0xFF); + } + return (hash % NR_NAME_HASH); +} + +void +add_file_hash(struct directory_entry *de) +{ + struct name_hash *new; + int hash; + Uchar *p; + int sum = 0; + + new = (struct name_hash *) e_malloc(sizeof (struct name_hash)); + new->de = de; + new->next = NULL; + for (p = (Uchar *)de->isorec.name; *p; p++) { + if (*p == ';') + break; + sum += *p & 0xFF; + } + new->sum = sum; + 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 * +find_file_hash(register char *name) +{ + register char *p1; + register char *p2; + register struct name_hash *nh; + register int sum = 0; + + if (debug > 1) + fprintf(stderr, "find_hash('%s')\n", name); + + for (p1 = name; *p1; p1++) { + if (*p1 == ';') + break; + sum += *p1 & 0xFF; + } + + for (nh = name_hash_table[name_hash(name)]; nh; nh = nh->next) { + if (nh->sum != sum) + continue; + + p1 = name; + p2 = nh->de->isorec.name; + if (debug > 1) + fprintf(stderr, "Checking name '%s' isorec.name '%s'\n", p1, p2); + + /* Look for end of string, or a mismatch. */ + while (1 == 1) { + if ((*p1 == '\0' || *p1 == ';') || + (*p2 == '\0' || *p2 == ';') || + (*p1 != *p2)) { + break; + } + p1++; + p2++; + } + if (!isoname_endsok(p1) || !isoname_endsok(p2)) { + if (debug > 1) { + if (!isoname_endsok(p1)) + fprintf(stderr, "'%s' does NOT END OK\n", p1); + if (!isoname_endsok(p2)) + fprintf(stderr, "'%s' does NOT END OK\n", p2); + } + /* + * If one file does not end with a valid version number + * and the other name ends here, we found a miss match. + */ + if (*p1 == '\0' || *p2 == '\0') + continue; + + if (*p1 == ';' && *p2 == ';') { + p1++; + p2++; + continue; + } + } + + /* + * If we are at the end of both strings, then we have a match. + */ + if ((*p1 == '\0' || *p1 == ';') && + (*p2 == '\0' || *p2 == ';')) { + return (nh->de); + } + } + return (NULL); +} + +/* + * The macro 'eo' is just an idea on how one might speed up isoname_endsok() + */ +#define eo(p) (((p)[0] == '\0') || \ + ((p)[0] == ';' && (p)[1] == '1' && (p)[2] == '\0') || \ + isoname_endsok(p)) + +static BOOL +isoname_endsok(char *name) +{ + int i; + char *p; + + if (*name == '\0') + return (TRUE); + if (*name != ';') + return (FALSE); + + for (p = ++name, i = 0; *p && i < 5; p++, i++) { + if (*p < '0' || *p > '9') + return (FALSE); + } + i = atoi(name); + if (i < 1 || i > 32767) + return (FALSE); + return (TRUE); +} + +int +delete_file_hash(struct directory_entry *de) +{ + struct name_hash *nh; + struct name_hash *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; + struct name_hash *nh1; + int i; + + for (i = 0; i < NR_NAME_HASH; i++) { + nh = name_hash_table[i]; + while (nh) { + nh1 = nh->next; + free(nh); + nh = nh1; + } + name_hash_table[i] = NULL; + + } +} diff --git a/genisoimage/hdisk.pl b/genisoimage/hdisk.pl new file mode 100755 index 0000000..55ef66c --- /dev/null +++ b/genisoimage/hdisk.pl @@ -0,0 +1,65 @@ +#!/usr/bin/perl + +############################################################################### +# +# hfsutils - tools for reading and writing Macintosh HFS volumes +# Copyright (C) 1996, 1997 Robert Leslie +# +# 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. +# +############################################################################### + +die "Usage: $0 device-path\n" unless (@ARGV == 1); + +($disk) = @ARGV; + +format STDOUT_TOP = + # Partition Type HFS Volume Name Start Length +------------------------------------------------------------------------------- +. + +format STDOUT = +@# @<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<< @####### @######## +$bnum, $pmParType, $drVN, $pmPyPartStart, $pmPartBlkCnt +. + +open(DISK, $disk) || die "$disk: $!\n"; + +$bnum = 1; + +do { + seek(DISK, 512 * $bnum, 0) || die "seek: $!\n"; + read(DISK, $block, 512) || die "read: $!\n"; + + ($pmSig, $pmMapBlkCnt, $pmPyPartStart, $pmPartBlkCnt, $pmParType) = + (unpack('n2 N3 A32 A32 N10 A16', $block))[0, 2..4, 6]; + + die "$disk: unsupported partition map\n" if ($pmSig == 0x5453); + die "$disk: no partition map\n" unless ($pmSig == 0x504d); + + if ($pmParType eq 'Apple_HFS') { + seek(DISK, 512 * ($pmPyPartStart + 2), 0) || die "seek: $!\n"; + read(DISK, $block, 512) || die "read: $!\n"; + + ($len, $drVN) = (unpack('n N2 n5 N2 n N n c A27', $block))[13, 14]; + $drVN = substr($drVN, 0, $len); + } else { + $drVN = ''; + } + + write; +} while ($bnum++ < $pmMapBlkCnt); + +close(DISK); diff --git a/genisoimage/ifo_read.c b/genisoimage/ifo_read.c new file mode 100644 index 0000000..0173c47 --- /dev/null +++ b/genisoimage/ifo_read.c @@ -0,0 +1,559 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)ifo_read.c 1.5 04/03/04 joerg */ +/* + * Copyright (C) 2002 Olaf Beck <olaf_sc@yahoo.com> + * Jörg Schilling <schilling@fokus.gmd.de> + * (making the code portable) + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * NOTE: This is a cut down version of libdvdread for genisoimage, due + * to portability issues with the current libdvdread according to + * the maintainer of genisoimage. + * This cut down version only reads from a harddisk file structure + * and it only implements the functions necessary inorder to make + * genisoimage produce valid DVD-Video images. + * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL + * LIBDVDREAD INSTEAD + */ +#ifdef DVD_VIDEO + +#include <mconfig.h> +#include "genisoimage.h" +#include <fctldefs.h> +#include <utypes.h> +#include <schily.h> + +#include "ifo_read.h" +#include "bswap.h" + +#define MSGEREAD "Failed to read VIDEO_TS.IFO\n" +#define MSGESEEK "Failed to seek VIDEO_TS.IFO\n" +#define MSGEOPEN "Failed to open VIDEO_TS.IFO\n" + +static ifo_handle_t *ifoReadVTSI(int file, ifo_handle_t * ifofile); +static ifo_handle_t *ifoReadVGMI(int file, ifo_handle_t * ifofile); +ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title); +static void ifoFree_TT_SRPT(ifo_handle_t *ifofile); +void ifoClose(ifo_handle_t * ifofile); + + +static ifo_handle_t * +ifoReadVTSI(int file, ifo_handle_t *ifofile) +{ + off_t offset; + UInt32_t sector; + + vtsi_mat_t * vtsi_mat; + + /* Make the VMG part NULL */ + ifofile->vmgi_mat = NULL; + ifofile->tt_srpt = NULL; + + vtsi_mat = (vtsi_mat_t *)e_malloc(sizeof (vtsi_mat_t)); + if (!vtsi_mat) { +/* fprintf(stderr, "Memmory allocation error\n");*/ + free(ifofile); + return (0); + } + + ifofile->vtsi_mat = vtsi_mat; + + /* Last sector of VTS i.e. last sector of BUP */ + + offset = 12; + + if (lseek(file, offset, SEEK_SET) != offset) { +#ifdef USE_LIBSCHILY + errmsg(MSGESEEK); +#else + printf(stderr, MSGESEEK); +#endif + ifoClose(ifofile); + return (0); + } + + if (read(file, §or, sizeof (sector)) != sizeof (sector)) { +#ifdef USE_LIBSCHILY + errmsg(MSGEREAD); +#else + printf(stderr, MSGEREAD); +#endif + ifoClose(ifofile); + return (0); + } + + B2N_32(sector); + + vtsi_mat->vts_last_sector = sector; + + /* Last sector of IFO */ + + offset = 28; + + if (lseek(file, offset, SEEK_SET) != offset) { +#ifdef USE_LIBSCHILY + errmsg(MSGESEEK); +#else + printf(stderr, MSGESEEK); +#endif + ifoClose(ifofile); + return (0); + } + + if (read(file, §or, sizeof (sector)) != sizeof (sector)) { +#ifdef USE_LIBSCHILY + errmsg(MSGEREAD); +#else + printf(stderr, MSGEREAD); +#endif + ifoClose(ifofile); + return (0); + } + + B2N_32(sector); + + vtsi_mat->vtsi_last_sector = sector; + + + /* Star sector of VTS Menu VOB */ + + offset = 192; + + if (lseek(file, offset, SEEK_SET) != offset) { +#ifdef USE_LIBSCHILY + errmsg(MSGESEEK); +#else + printf(stderr, MSGESEEK); +#endif + ifoClose(ifofile); + return (0); + } + + + if (read(file, §or, sizeof (sector)) != sizeof (sector)) { +#ifdef USE_LIBSCHILY + errmsg(MSGEREAD); +#else + printf(stderr, MSGEREAD); +#endif + ifoClose(ifofile); + return (0); + } + + B2N_32(sector); + + vtsi_mat->vtsm_vobs = sector; + + + /* Start sector of VTS Title VOB */ + + offset = 196; + + if (lseek(file, offset, SEEK_SET) != offset) { +#ifdef USE_LIBSCHILY + errmsg(MSGESEEK); +#else + printf(stderr, MSGESEEK); +#endif + ifoClose(ifofile); + return (0); + } + + + if (read(file, §or, sizeof (sector)) != sizeof (sector)) { +#ifdef USE_LIBSCHILY + errmsg(MSGEREAD); +#else + printf(stderr, MSGEREAD); +#endif + ifoClose(ifofile); + return (0); + } + + B2N_32(sector); + + vtsi_mat->vtstt_vobs = sector; + + return (ifofile); +} + + +static ifo_handle_t * +ifoReadVGMI(int file, ifo_handle_t *ifofile) +{ + off_t offset; + Uint counter; + UInt32_t sector; + UInt16_t titles; + + vmgi_mat_t *vmgi_mat; + tt_srpt_t *tt_srpt; + + /* Make the VTS part null */ + ifofile->vtsi_mat = NULL; + + vmgi_mat = (vmgi_mat_t *)e_malloc(sizeof (vmgi_mat_t)); + if (!vmgi_mat) { +/* fprintf(stderr, "Memmory allocation error\n");*/ + free(ifofile); + return (0); + } + + ifofile->vmgi_mat = vmgi_mat; + + /* Last sector of VMG i.e. last sector of BUP */ + + offset = 12; + + if (lseek(file, offset, SEEK_SET) != offset) { +#ifdef USE_LIBSCHILY + errmsg(MSGESEEK); +#else + printf(stderr, MSGESEEK); +#endif + ifoClose(ifofile); + return (0); + } + + if (read(file, §or, sizeof (sector)) != sizeof (sector)) { +#ifdef USE_LIBSCHILY + errmsg(MSGEREAD); +#else + printf(stderr, MSGEREAD); +#endif + ifoClose(ifofile); + return (0); + } + + B2N_32(sector); + + vmgi_mat->vmg_last_sector = sector; + + /* Last sector of IFO */ + + offset = 28; + + if (lseek(file, offset, SEEK_SET) != offset) { +#ifdef USE_LIBSCHILY + errmsg(MSGESEEK); +#else + printf(stderr, MSGESEEK); +#endif + ifoClose(ifofile); + return (0); + } + + + if (read(file, §or, sizeof (sector)) != sizeof (sector)) { +#ifdef USE_LIBSCHILY + errmsg(MSGEREAD); +#else + printf(stderr, MSGEREAD); +#endif + ifoClose(ifofile); + return (0); + } + + B2N_32(sector); + + vmgi_mat->vmgi_last_sector = sector; + + + /* Number of VTS i.e. title sets */ + + offset = 62; + + if (lseek(file, offset, SEEK_SET) != offset) { +#ifdef USE_LIBSCHILY + errmsg(MSGESEEK); +#else + printf(stderr, MSGESEEK); +#endif + ifoClose(ifofile); + return (0); + } + + + if (read(file, &titles, sizeof (titles)) != sizeof (titles)) { +#ifdef USE_LIBSCHILY + errmsg(MSGEREAD); +#else + printf(stderr, MSGEREAD); +#endif + ifoClose(ifofile); + return (0); + } + + B2N_16(titles); + + vmgi_mat->vmg_nr_of_title_sets = titles; + + + /* Star sector of VMG Menu VOB */ + + offset = 192; + + if (lseek(file, offset, SEEK_SET) != offset) { +#ifdef USE_LIBSCHILY + errmsg(MSGESEEK); +#else + printf(stderr, MSGESEEK); +#endif + ifoClose(ifofile); + return (0); + } + + + if (read(file, §or, sizeof (sector)) != sizeof (sector)) { +#ifdef USE_LIBSCHILY + errmsg(MSGEREAD); +#else + printf(stderr, MSGEREAD); +#endif + ifoClose(ifofile); + return (0); + } + + B2N_32(sector); + + vmgi_mat->vmgm_vobs = sector; + + + /* Sector offset to TT_SRPT */ + + offset = 196; + + if (lseek(file, offset, SEEK_SET) != offset) { +#ifdef USE_LIBSCHILY + errmsg(MSGESEEK); +#else + printf(stderr, MSGESEEK); +#endif + ifoClose(ifofile); + return (0); + } + + + if (read(file, §or, sizeof (sector)) != sizeof (sector)) { +#ifdef USE_LIBSCHILY + errmsg(MSGEREAD); +#else + printf(stderr, MSGEREAD); +#endif + ifoClose(ifofile); + return (0); + } + + B2N_32(sector); + + vmgi_mat->tt_srpt = sector; + + tt_srpt = (tt_srpt_t *)e_malloc(sizeof (tt_srpt_t)); + if (!tt_srpt) { +/* fprintf(stderr, "Memmory allocation error\n");*/ + ifoClose(ifofile); + return (0); + } + + ifofile->tt_srpt = tt_srpt; + + + /* Number of titles in TT_SRPT */ + + offset = 2048 * vmgi_mat->tt_srpt; + + if (lseek(file, offset, SEEK_SET) != offset) { +#ifdef USE_LIBSCHILY + errmsg(MSGESEEK); +#else + printf(stderr, MSGESEEK); +#endif + return (0); + } + + if (read(file, &titles, sizeof (titles)) != sizeof (titles)) { +#ifdef USE_LIBSCHILY + errmsg(MSGEREAD); +#else + printf(stderr, MSGEREAD); +#endif + return (0); + } + + B2N_16(titles); + + tt_srpt->nr_of_srpts = titles; + + tt_srpt->title = (title_info_t *)e_malloc(sizeof (title_info_t) * tt_srpt->nr_of_srpts); + if (!tt_srpt->title) { +/* fprintf(stderr, "Memmory allocation error\n");*/ + ifoClose(ifofile); + return (0); + } + + /* Start sector of each title in TT_SRPT */ + + for (counter = 0; counter < tt_srpt->nr_of_srpts; counter++) { + offset = (2048 * vmgi_mat->tt_srpt) + 8 + (counter * 12) + 8; + if (lseek(file, offset, SEEK_SET) != offset) { +#ifdef USE_LIBSCHILY + errmsg(MSGESEEK); +#else + printf(stderr, MSGESEEK); +#endif + ifoClose(ifofile); + return (0); + } + + if (read(file, §or, sizeof (sector)) != sizeof (sector)) { +#ifdef USE_LIBSCHILY + errmsg(MSGEREAD); +#else + printf(stderr, MSGEREAD); +#endif + ifoClose(ifofile); + return (0); + } + + B2N_32(sector); + + tt_srpt->title[counter].title_set_sector = sector; + + } + return (ifofile); +} + +ifo_handle_t * +ifoOpen(dvd_reader_t *dvd, int title) +{ + /* The main ifofile structure */ + ifo_handle_t *ifofile; + + /* File handles and offset */ + int file; + off_t offset; + char full_path[ PATH_MAX + 1 ]; + + /* Identifier of the IFO */ + char identifier[13]; + + identifier[0] = '\0'; + + ifofile = (ifo_handle_t *)e_malloc(sizeof (ifo_handle_t)); + + memset(ifofile, 0, sizeof (ifo_handle_t)); + + if (title) { + snprintf(full_path, sizeof (full_path), + "%s/VIDEO_TS/VTS_%02d_0.IFO", dvd->path_root, title); + } else { + snprintf(full_path, sizeof (full_path), + "%s/VIDEO_TS/VIDEO_TS.IFO", dvd->path_root); + } + + if ((file = open(full_path, O_RDONLY | O_BINARY)) == -1) { +#ifdef USE_LIBSCHILY + errmsg(MSGEOPEN); +#else + printf(stderr, MSGEOPEN); +#endif + free(ifofile); + return (0); + } + + offset = 0; + + /* Determine if we have a VMGI or VTSI */ + + if (read(file, identifier, sizeof (identifier)) != sizeof (identifier)) { +#ifdef USE_LIBSCHILY + errmsg(MSGEREAD); +#else + printf(stderr, MSGEREAD); +#endif + return (0); + } + + if ((strstr("DVDVIDEO-VMG", identifier) != 0) && (title == 0)) { + ifofile = ifoReadVGMI(file, ifofile); + close(file); + return (ifofile); + } else if ((strstr("DVDVIDEO-VTS", identifier) != 0) && (title != 0)) { + ifofile = ifoReadVTSI(file, ifofile); + close(file); + return (ifofile); + } else { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Giving up this is not a valid IFO file\n"); +#else + fprintf(stderr, "Giving up this is not a valid IFO file\n"); +#endif + close(file); + free(ifofile); + ifofile = 0; + return (0); + } +} + +static void +ifoFree_TT_SRPT(ifo_handle_t *ifofile) +{ + if (!ifofile) + return; + + if (ifofile->tt_srpt) { + if (ifofile->tt_srpt->title) { + free(ifofile->tt_srpt->title); + } + free(ifofile->tt_srpt); + ifofile->tt_srpt = 0; + } +} + +void +ifoClose(ifo_handle_t *ifofile) +{ + + if (!ifofile) + return; + + ifoFree_TT_SRPT(ifofile); + + if (ifofile->vmgi_mat) { + free(ifofile->vtsi_mat); + } + + if (ifofile->vtsi_mat) { + free(ifofile->vtsi_mat); + } + + free(ifofile); + ifofile = 0; +} +#endif /* DVD_VIDEO */ diff --git a/genisoimage/ifo_read.h b/genisoimage/ifo_read.h new file mode 100644 index 0000000..b8fa009 --- /dev/null +++ b/genisoimage/ifo_read.h @@ -0,0 +1,81 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)ifo_read.h 1.2 04/03/02 joerg */ + +#ifndef _IFO_READ_H +#define _IFO_READ_H + +/* + * Copyright (C) 2000, 2001, 2002 Björn Englund <d4bjorn@dtek.chalmers.se>, + * Håkan Hjort <d95hjort@dtek.chalmers.se + * Olaf Beck <olaf_sc@yahoo.com> + * (I only did the cut down no other contribs) + * Jörg Schilling <schilling@fokus.gmd.de> + * (making the code portable) + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * NOTE: This is a cut down version of libdvdread for genisoimage, due + * to portability issues with the current libdvdread according to + * the maintainer of genisoimage. + * This cut down version only reads from a harddisk file structure + * and it only implements the functions necessary inorder to make + * genisoimage produce valid DVD-Video images. + * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL + * LIBDVDREAD INSTEAD + */ + + + +#include "ifo_types.h" +#include "dvd_reader.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * handle = ifoOpen(dvd, title); + * + * Opens an IFO and reads a tiny fraction of the data for the IFO file + * corresponding to the given title set. If title 0 is given, the video + * manager IFO file is read. + * Returns a handle to a tiny parsed fraction of a IFO strcuture + */ +extern ifo_handle_t *ifoOpen(dvd_reader_t *, int); + + +/* + * ifoClose(ifofile); + * Cleans up the IFO information. This will free all data allocated. + */ +extern void ifoClose(ifo_handle_t *); + +#ifdef __cplusplus +}; +#endif +#endif /* _IFO_READ_H */ diff --git a/genisoimage/ifo_types.h b/genisoimage/ifo_types.h new file mode 100644 index 0000000..00b3bde --- /dev/null +++ b/genisoimage/ifo_types.h @@ -0,0 +1,91 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)ifo_types.h 1.2 04/03/02 joerg */ + +#ifndef _IFO_TYPES_H +#define _IFO_TYPES_H +/* + * Copyright (C) 2001, 2002 Billy Biggs <vektor@dumbterm.net>, + * Håkan Hjort <d95hjort@dtek.chalmers.se>, + * Olaf Beck <olaf_sc@yahoo.com> + * (I only did the cut down no other contribs) + * Jörg Schilling <schilling@fokus.gmd.de> + * (making the code portable) + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * NOTE: This is a cut down version of libdvdread for genisoimage, due + * to portability issues with the current libdvdread according to + * the maintainer of genisoimage. + * This cut down version only reads from a harddisk file structure + * and it only implements the functions necessary inorder to make + * genisoimage produce valid DVD-Video images. + * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL + * LIBDVDREAD INSTEAD + */ + +#include "dvd_reader.h" + + +typedef struct { + UInt32_t title_set_sector; /* sector */ +} title_info_t; + + +typedef struct { + UInt16_t nr_of_srpts; + title_info_t * title; /* array of title info */ +} tt_srpt_t; + +typedef struct { + UInt32_t vmg_last_sector; /*sector */ + UInt32_t vmgi_last_sector; /* sector */ + UInt16_t vmg_nr_of_title_sets; + UInt32_t vmgm_vobs; /* sector */ + UInt32_t tt_srpt; /* sector */ +} vmgi_mat_t; + + + +typedef struct { + UInt32_t vts_last_sector; /* sector */ + UInt32_t vtsi_last_sector; /* sector */ + UInt32_t vtsm_vobs; /* sector */ + UInt32_t vtstt_vobs; /* sector */ +} vtsi_mat_t; + + +typedef struct { + /* VMGI */ + vmgi_mat_t * vmgi_mat; + tt_srpt_t * tt_srpt; + + /* VTSI */ + vtsi_mat_t * vtsi_mat; +} ifo_handle_t; + + +#endif /* _IFO_TYPES_H */ diff --git a/genisoimage/iso9660.h b/genisoimage/iso9660.h new file mode 100644 index 0000000..c74c2a9 --- /dev/null +++ b/genisoimage/iso9660.h @@ -0,0 +1,359 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)iso9660.h 1.19 04/03/02 joerg */ +/* + * Header file iso9660.h - assorted structure definitions and typecasts. + * specific to iso9660 filesystem. + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * Copyright (c) 1999,2000-2004 J. Schilling + * + * 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_SUPPLEMENTARY 2 /* Used by Joliet */ +#define ISO_VD_END 255 + +#define ISO_STANDARD_ID "CD001" + +#define EL_TORITO_ID "EL TORITO SPECIFICATION" +#define EL_TORITO_ARCH_x86 0 +#define EL_TORITO_ARCH_PPC 1 +#define EL_TORITO_ARCH_MAC 2 + +#define EL_TORITO_BOOTABLE 0x88 +#define EL_TORITO_NOT_BOOTABLE 0 + +#define EL_TORITO_MEDIA_NOEMUL 0 +#define EL_TORITO_MEDIA_12FLOP 1 +#define EL_TORITO_MEDIA_144FLOP 2 +#define EL_TORITO_MEDIA_288FLOP 3 +#define EL_TORITO_MEDIA_HD 4 + +struct iso_primary_descriptor { + char type [ISODCL(1, 1)]; /* 711 */ + char id [ISODCL(2, 6)]; + char version [ISODCL(7, 7)]; /* 711 */ + char unused1 [ISODCL(8, 8)]; + char system_id [ISODCL(9, 40)]; /* achars */ + char volume_id [ISODCL(41, 72)]; /* dchars */ + char unused2 [ISODCL(73, 80)]; + char volume_space_size [ISODCL(81, 88)]; /* 733 */ + char escape_sequences [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)]; +}; + +/* + * Supplementary or enhanced volume descriptor + */ +struct iso_enhanced_descriptor { + char type [ISODCL(1, 1)]; /* 711 */ + char id [ISODCL(2, 6)]; + char version [ISODCL(7, 7)]; /* 711 */ + char flags [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 escape_sequences [ISODCL(89, 120)]; + char volume_set_size [ISODCL(121, 124)]; /* 723 */ + char volume_sequence_number [ISODCL(125, 128)]; /* 723 */ + char logical_block_size [ISODCL(129, 132)]; /* 723 */ + char path_table_size [ISODCL(133, 140)]; /* 733 */ + char type_l_path_table [ISODCL(141, 144)]; /* 731 */ + char opt_type_l_path_table [ISODCL(145, 148)]; /* 731 */ + char type_m_path_table [ISODCL(149, 152)]; /* 732 */ + char opt_type_m_path_table [ISODCL(153, 156)]; /* 732 */ + char root_directory_record [ISODCL(157, 190)]; /* 9.1 */ + char volume_set_id [ISODCL(191, 318)]; /* dchars */ + char publisher_id [ISODCL(319, 446)]; /* achars */ + char preparer_id [ISODCL(447, 574)]; /* achars */ + char application_id [ISODCL(575, 702)]; /* achars */ + char copyright_file_id [ISODCL(703, 739)]; /* 7.5 dchars */ + char abstract_file_id [ISODCL(740, 776)]; /* 7.5 dchars */ + char bibliographic_file_id [ISODCL(777, 813)]; /* 7.5 dchars */ + char creation_date [ISODCL(814, 830)]; /* 8.4.26.1 */ + char modification_date [ISODCL(831, 847)]; /* 8.4.26.1 */ + char expiration_date [ISODCL(848, 864)]; /* 8.4.26.1 */ + char effective_date [ISODCL(865, 881)]; /* 8.4.26.1 */ + char file_structure_version [ISODCL(882, 882)]; /* 711 */ + char unused4 [ISODCL(883, 883)]; + char application_data [ISODCL(884, 1395)]; + char unused5 [ISODCL(1396, 2048)]; +}; + +/* El Torito Boot Record Volume Descriptor */ +struct eltorito_boot_descriptor { + char type [ISODCL(1, 1)]; /* 711 */ + char id [ISODCL(2, 6)]; + char version [ISODCL(7, 7)]; /* 711 */ + char system_id [ISODCL(8, 39)]; + char unused2 [ISODCL(40, 71)]; + char bootcat_ptr [ISODCL(72, 75)]; + char unused5 [ISODCL(76, 2048)]; +}; + +/* Validation entry for El Torito */ +struct eltorito_validation_entry { + char headerid [ISODCL(1, 1)]; /* 711 */ + char arch [ISODCL(2, 2)]; + char pad1 [ISODCL(3, 4)]; /* 711 */ + char id [ISODCL(5, 28)]; /* CD devel/man*/ + char cksum [ISODCL(29, 30)]; + char key1 [ISODCL(31, 31)]; + char key2 [ISODCL(32, 32)]; +}; + +/* El Torito initial/default entry in boot catalog */ +struct eltorito_defaultboot_entry { + char boot_id [ISODCL(1, 1)]; /* 711 */ + char boot_media [ISODCL(2, 2)]; + char loadseg [ISODCL(3, 4)]; /* 711 */ + char sys_type [ISODCL(5, 5)]; + char pad1 [ISODCL(6, 6)]; + char nsect [ISODCL(7, 8)]; + char bootoff [ISODCL(9, 12)]; + char pad2 [ISODCL(13, 32)]; +}; + +/* + * XXX JS: The next two structures have odd lengths! + * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length. + * For this reason, we cannot use sizeof (struct iso_path_table) or + * sizeof (struct iso_directory_record) to compute on disk sizes. + * Instead, we use offsetof(..., name) and add the name size. + * See genisoimage.h + */ + +/* 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]; +}; + +/* + * A ISO filename is: "abcde.eee;1" -> <filename> '.' <ext> ';' <version #> + * + * The maximum needed string length is: + * 30 chars (filename + ext) + * + 2 chars ('.' + ';') + * + strlen("32767") + * + null byte + * ================================ + * = 38 chars + * + * We currently do not support CD-ROM-XA entension records, but we must honor + * the needed space for ISO-9660:1999 (Version 2). + * + * XXX If we ever will start to support XA records, we will need to take care + * XXX that the the maximum ISO-9660 name length will be reduced by another + * XXX 14 bytes resulting in a new total of 179 Bytes. + */ +#define LEN_ISONAME 31 +#define MAX_ISONAME_V1 37 +#define MAX_ISONAME_V2 207 /* 254 - 33 - 14 (XA Record) */ +#define MAX_ISONAME_V2_RR 193 /* 254 - 33 - 28 (CE Record) */ +#define MAX_ISONAME_V2_RR_XA 179 /* 254 - 33 - 14 - 28 */ +#define MAX_ISONAME MAX_ISONAME_V2 /* Used for array space defs */ +#define MAX_ISODIR 254 /* Must be even and <= 255 */ + +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 [MAX_ISONAME+1]; /* Not really, but we need something here */ +}; + + +/* + * Iso directory flags. + */ +#define ISO_FILE 0 /* Not really a flag... */ +#define ISO_EXISTENCE 1 /* Do not make existence known (hidden) */ +#define ISO_DIRECTORY 2 /* This file is a directory */ +#define ISO_ASSOCIATED 4 /* This file is an assiciated file */ +#define ISO_RECORD 8 /* Record format in extended attr. != 0 */ +#define ISO_PROTECTION 16 /* No read/execute perm. in ext. attr. */ +#define ISO_DRESERVED1 32 /* Reserved bit 5 */ +#define ISO_DRESERVED2 64 /* Reserved bit 6 */ +#define ISO_MULTIEXTENT 128 /* Not final entry of a mult. ext. file */ + + +struct iso_ext_attr_record { + char owner [ISODCL(1, 4)]; /* 723 */ + char group [ISODCL(5, 8)]; /* 723 */ + char permissions [ISODCL(9, 10)]; /* 16 bits */ + char creation_date [ISODCL(11, 27)]; /* 8.4.26.1 */ + char modification_date [ISODCL(28, 44)]; /* 8.4.26.1 */ + char expiration_date [ISODCL(45, 61)]; /* 8.4.26.1 */ + char effective_date [ISODCL(62, 78)]; /* 8.4.26.1 */ + char record_format [ISODCL(79, 79)]; /* 711 */ + char record_attributes [ISODCL(80, 80)]; /* 711 */ + char record_length [ISODCL(81, 84)]; /* 723 */ + char system_id [ISODCL(85, 116)]; /* achars */ + char system_use [ISODCL(117, 180)]; + char ext_attr_version [ISODCL(181, 181)]; /* 711 */ + char esc_seq_len [ISODCL(182, 182)]; /* 711 */ + char reserved [ISODCL(183, 246)]; /* for future use */ + char appl_use_len [ISODCL(247, 250)]; /* 723 */ + char appl_use[1]; /* really more */ +/* char esc_seq[]; escape sequences recorded after appl_use */ +}; + +/* + * Iso extended attribute permissions. + */ +#define ISO_GS_READ 0x0001 /* System Group Read */ +#define ISO_BIT_1 0x0002 +#define ISO_GS_EXEC 0x0004 /* System Group Execute */ +#define ISO_BIT_3 0x0008 + +#define ISO_O_READ 0x0010 /* Owner Read */ +#define ISO_BIT_5 0x0020 +#define ISO_O_EXEC 0x0040 /* Owner Exexute */ +#define ISO_BIT_7 0x0080 + +#define ISO_G_READ 0x0100 /* Group Read */ +#define ISO_BIT_9 0x0200 +#define ISO_G_EXEC 0x0400 /* Group Execute */ +#define ISO_BIT_11 0x0800 + +#define ISO_W_READ 0x1000 /* World (other) Read */ +#define ISO_BIT_13 0x2000 +#define ISO_W_EXEC 0x4000 /* World (other) Execute */ +#define ISO_BIT_15 0x8000 + +#define ISO_MB_ONE (ISO_BIT_1|ISO_BIT_3|ISO_BIT_5|ISO_BIT_7| \ + ISO_BIT_9|ISO_BIT_11|ISO_BIT_13|ISO_BIT_15) + +/* + * Extended Attributes record according to Yellow Book. + */ +struct iso_xa_dir_record { + char group_id [ISODCL(1, 2)]; + char user_id [ISODCL(3, 4)]; + char attributes [ISODCL(5, 6)]; + char signature [ISODCL(7, 8)]; + char file_number [ISODCL(9, 9)]; + char reserved [ISODCL(10, 14)]; +}; + +/* + * Definitions for XA attributes + */ +#define XA_O_READ 0x0001 /* Owner Read */ +#define XA_O_RES 0x0002 /* Owner Reserved (write ?) */ +#define XA_O_EXEC 0x0004 /* Owner Execute */ +#define XA_O_RES2 0x0008 /* Owner Reserved */ +#define XA_G_READ 0x0010 /* Group Read */ +#define XA_G_RES 0x0020 /* Group Reserved (write ?) */ +#define XA_G_EXEC 0x0040 /* Group Execute */ +#define XA_G_RES2 0x0080 /* Group Reserved */ +#define XA_W_READ 0x0100 /* World Read */ +#define XA_W_RES 0x0200 /* World Reserved (write ?) */ +#define XA_W_EXEC 0x0400 /* World Execute */ + +#define XA_FORM1 0x0800 /* File contains Form 1 sector */ +#define XA_FORM2 0x1000 /* File contains Form 2 sector */ +#define XA_INTERLEAVED 0x2000 /* File contains interleaved sectors */ +#define XA_CDDA 0x4000 /* File contains audio data */ +#define XA_DIR 0x8000 /* This is a directory */ + +/* + * Definitions for CD-ROM XA-Mode-2-form-1/2 sector sub-headers + */ +struct xa_subhdr { + Uchar file_number; /* Identifies file for block */ + Uchar channel_number; /* Playback channel selection */ + Uchar sub_mode; /* See bit definitions below */ + Uchar coding; /* Coding information */ +}; + +/* + * Sub mode bit definitions + */ +#define XA_SUBH_EOR 0x01 /* End-Of-Record */ +#define XA_SUBH_VIDEO 0x02 /* Video Block */ +#define XA_SUBH_AUDIO 0x04 /* Audio Block (not CD-DA) */ +#define XA_SUBH_DATA 0x08 /* Data Block */ +#define XA_SUBH_TRIGGER 0x10 /* Trigger Block */ +#define XA_SUBH_FORM2 0x20 /* 0 == Form1, 1 == Form2 */ +#define XA_SUBH_REALTIME 0x40 /* Real Time Block */ +#define XA_SUBH_EOF 0x80 /* End-Of-File */ + +#endif /* _ISOFS_FS_H */ diff --git a/genisoimage/joliet.c b/genisoimage/joliet.c new file mode 100644 index 0000000..b36f8f7 --- /dev/null +++ b/genisoimage/joliet.c @@ -0,0 +1,1456 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)joliet.c 1.38 05/05/01 joerg */ +/* + * File joliet.c - handle Win95/WinNT long file/unicode extensions for iso9660. + * + * Copyright 1997 Eric Youngdale. + * APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 22/2/2000 + * Copyright (c) 1999,2000,2001 J. Schilling + * + * 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. + */ + +/* + * Joliet extensions for ISO9660. These are spottily documented by + * Microsoft. In their infinite stupidity, they completely ignored + * the possibility of using an SUSP record with the long filename + * in it, and instead wrote out a duplicate directory tree with the + * long filenames in it. + * + * I am not sure why they did this. One reason is that they get the path + * tables with the long filenames in them. + * + * There are two basic principles to Joliet, and the non-Unicode variant + * known as Romeo. Long filenames seem to be the main one, and the second + * is that the character set and a few other things is substantially relaxed. + * + * The SVD is identical to the PVD, except: + * + * Id is 2, not 1 (indicates SVD). + * escape_sequences contains UCS-2 indicator (levels 1, 2 or 3). + * The root directory record points to a different extent (with different + * size). + * There are different path tables for the two sets of directory trees. + * + * The Unicode level is coded in the SVD as follows: + * + * Standard Level ASCII escape code + * UCS-2 Level-1 %/@ + * UCS-2 Level-2 %/C + * UCS-2 Level-3 %/E + * + * The following fields are recorded in Unicode: + * system_id + * volume_id + * volume_set_id + * publisher_id + * preparer_id + * application_id + * copyright_file_id + * abstract_file_id + * bibliographic_file_id + * + * Unicode strings are always encoded in big-endian format. + * + * In a directory record, everything is the same as with iso9660, except + * that the name is recorded in unicode. The name length is specified in + * total bytes, not in number of unicode characters. + * + * The character set used for the names is different with UCS - the + * restrictions are that the following are not allowed: + * + * Characters (00)(00) through (00)(1f) (control chars) + * (00)(2a) '*' + * (00)(2f) '/' + * (00)(3a) ':' + * (00)(3b) ';' + * (00)(3f) '?' + * (00)(5c) '\' + */ +#include <mconfig.h> +#include "genisoimage.h" +#include <timedefs.h> +#include <utypes.h> +#include <intcvt.h> +#include <unls.h> /* For UNICODE translation */ +#include <schily.h> +#include <string.h> + +#ifdef USE_ICONV +#include <iconv.h> +#include <errno.h> +#endif + +static Uint jpath_table_index; +static struct directory **jpathlist; +static int next_jpath_index = 1; +static int jsort_goof; + +static char ucs_codes[] = { + '\0', /* UCS-level 0 is illegal */ + '@', /* UCS-level 1 */ + 'C', /* UCS-level 2 */ + 'E', /* UCS-level 3 */ +}; + +#ifdef UDF +#ifdef USE_ICONV +size_t +#else +void +#endif +convert_to_unicode(unsigned char *buffer, int size, char *source, + struct unls_table *inls); +int joliet_strlen(const char *string, struct unls_table *inls); +#else +#ifdef USE_ICONV +static size_t +#else +static void +#endif +convert_to_unicode(unsigned char *buffer, int size, char *source, + struct unls_table *inls); +static int joliet_strlen(const char *string, struct nls_table *inls); +#endif +static void get_joliet_vol_desc(struct iso_primary_descriptor *jvol_desc); +static void assign_joliet_directory_addresses(struct directory *node); +static void build_jpathlist(struct directory *node); +static int joliet_compare_paths(void const *r, void const *l); +static int generate_joliet_path_tables(void); +static void generate_one_joliet_directory(struct directory *dpnt, + FILE *outfile); +static int joliet_sort_n_finish(struct directory *this_dir); +static int joliet_compare_dirs(const void *rr, const void *ll); +static int joliet_sort_directory(struct directory_entry **sort_dir); +int joliet_sort_tree(struct directory *node); +static void generate_joliet_directories(struct directory *node, FILE *outfile); +static int jpathtab_write(FILE *outfile); +static int jdirtree_size(int starting_extent); +static int jroot_gen(void); +static int jdirtree_write(FILE *outfile); +static int jvd_write(FILE *outfile); +static int jpathtab_size(int starting_extent); + +/* + * conv_charset: convert to/from charsets via Unicode. + * + * Any unknown character is set to '_' + * + */ +unsigned char +conv_charset(unsigned char c, + struct unls_table *inls, + struct unls_table *onls) +{ + unsigned char uh; + unsigned char ul; + unsigned char uc; + unsigned char *up; + + /* if we have a null mapping, just return the input character */ + if (inls == onls) + return (c); + +#ifdef USE_ICONV + if(inls->unls_cs2uni == NULL || onls->unls_uni2cs == NULL) { + /* + * This shouldn't be reached + */ + static BOOL iconv_warned = FALSE; + if(!iconv_warned) { + fprintf(stderr, "Warning: Iconv conversion not supported in conv_charset.\n"); + iconv_warned = TRUE; + } + return (c); + } +#endif + + /* get high and low UNICODE bytes */ + uh = inls->unls_cs2uni[c].unls_high; + ul = inls->unls_cs2uni[c].unls_low; + + /* get the backconverted page from the output charset */ + up = onls->unls_uni2cs[uh]; + + /* if the page exists, get the backconverted character */ + if (up == NULL) + uc = '\0'; + else + uc = up[ul]; + + /* return the backconverted, if it's not NULL */ + return (uc ? uc : '_'); +} + +/* + * Function: convert_to_unicode + * + * Purpose: Perform a unicode conversion on a text string + * using the supplied input character set. + * + * Notes: + */ +#ifdef USE_ICONV +# if UDF +size_t +# else +static size_t +# endif +#else +# if UDF +void +# else +static void +# endif +#endif +convert_to_unicode(unsigned char *buffer, int size, char *source, + struct unls_table *inls) +{ + unsigned char *tmpbuf; + int i; + int j; + unsigned char uh, + ul, + uc, + *up; + + /* + * If we get a NULL pointer for the source, it means we have an + * inplace copy, and we need to make a temporary working copy first. + */ + if (source == NULL) { + tmpbuf = (Uchar *) e_malloc(size+1); + memcpy(tmpbuf, buffer, size); + tmpbuf[size] = 0; + } else { + tmpbuf = (Uchar *) source; + } + +#ifdef USE_ICONV + if (inls->iconv_d && inls->unls_cs2uni==NULL && + inls->unls_uni2cs==NULL) { + char *inptr = (char *)tmpbuf; + char *outptr = (char *)buffer; + size_t inleft = strlen((char *)tmpbuf); + size_t inlen = inleft; + size_t outleft = size; + + iconv(inls->iconv_d, NULL, NULL, NULL, NULL); + if(iconv(inls->iconv_d, &inptr, &inleft, &outptr, &outleft) == + (size_t)-1 && errno == EILSEQ) { + fprintf(stderr, "Incorrectly encoded string (%s) " + "encountered.\nPossibly creating an invalid " + "Joliet extension. Aborting.\n", source); + exit(1); + } + + for (i = 0; (i + 1) < size - outleft; i += 2) { /* Size may be odd!!!*/ + if (buffer[i]=='\0') { + switch (buffer[i+1]) { /* Invalid characters for Joliet */ + case '*': + case '/': + case ':': + case ';': + case '?': + case '\\': + buffer[i+1]='_'; + default: + if (buffer[i+1] == 0x7f || + buffer[i+1] < 0x20) + buffer[i+1]='_'; + } + } + } + if (size & 1) { /* beautification */ + buffer[size - 1] = 0; + } + if (source == NULL) { + free(tmpbuf); + } + return (inlen - inleft); + } +#endif + + /* + * Now start copying characters. If the size was specified to be 0, + * then assume the input was 0 terminated. + */ + j = 0; + for (i = 0; (i + 1) < size; i += 2, j++) { /* Size may be odd! */ + /* + * JS integrated from: Achim_Kaiser@t-online.de + * SGE modified according to Linux kernel source + * Let all valid unicode characters pass + * through (according to charset). Others are set to '_' . + */ + uc = tmpbuf[j]; /* temporary copy */ + if (uc != '\0') { /* must be converted */ + uh = inls->unls_cs2uni[uc].unls_high; /* convert forward: */ + /* hibyte... */ + ul = inls->unls_cs2uni[uc].unls_low; /* ...lobyte */ + up = inls->unls_uni2cs[uh]; /* convert backward: */ + /* page... */ + if (up == NULL) + uc = '\0'; /* wrong unicode page */ + else + uc = up[ul]; /* backconverted character */ + if (uc != tmpbuf[j]) + uc = '\0'; /* should be identical */ + if (uc <= 0x1f || uc == 0x7f) + uc = '\0'; /* control char */ + switch (uc) { /* test special characters */ + + case '*': + case '/': + case ':': + case ';': + case '?': + case '\\': + case '\0': /* illegal char mark */ + /* + * Even Joliet has some standards as to what is + * allowed in a pathname. Pretty tame in + * comparison to what DOS restricts you to. + */ + uc = '_'; + } + } + buffer[i] = inls->unls_cs2uni[uc].unls_high; /* final UNICODE */ + /* conversion */ + buffer[i + 1] = inls->unls_cs2uni[uc].unls_low; + } + + if (size & 1) { /* beautification */ + buffer[size - 1] = 0; + } + if (source == NULL) { + free(tmpbuf); + } +#ifdef USE_ICONV + return j; +#endif +} + +/* + * Function: joliet_strlen + * + * Purpose: Return length in bytes of string after conversion to unicode. + * + * Notes: This is provided mainly as a convenience so that when more + * intelligent Unicode conversion for either Multibyte or 8-bit + * codes is available that we can easily adapt. + */ +#ifdef UDF +int +#else +static int +#endif +joliet_strlen(const char *string, struct unls_table *inls) +{ + int rtn; + +#ifdef USE_ICONV + if (inls->iconv_d && inls->unls_cs2uni==NULL && + inls->unls_uni2cs==NULL) { + /* + * we const-cast since we're sure iconv won't change + * the string itself + */ + char *string_ptr = (char *)string; + size_t string_len = strlen(string); + + /* + * iconv has no way of finding out the required size + * in the target + */ + + char *tmp, *tmp_ptr; + /* we assume that the maximum length is 2 * jlen */ + size_t tmp_len = (size_t)jlen * 2 + 1; + tmp = e_malloc(tmp_len); + tmp_ptr = tmp; + + iconv(inls->iconv_d, NULL, NULL, NULL, NULL); + iconv(inls->iconv_d, &string_ptr, &string_len, &tmp_ptr, + &tmp_len); + + /* + * iconv advanced the tmp pointer with as many chars + * as it has written to it, so we add up the delta + */ + rtn = (tmp_ptr - tmp); + + free(tmp); + } else { + rtn = strlen(string) << 1; + } +#else + rtn = strlen(string) << 1; +#endif + + /* + * We do clamp the maximum length of a Joliet string to be the + * maximum path size. This helps to ensure that we don't completely + * bolix things up with very long paths. The Joliet specs say that + * the maximum length is 128 bytes, or 64 unicode characters. + */ + if (rtn > 2*jlen) { + rtn = 2*jlen; + } + return (rtn); +} + +/* + * Function: get_joliet_vol_desc + * + * Purpose: generate a Joliet compatible volume desc. + * + * Notes: Assume that we have the non-joliet vol desc + * already present in the buffer. Just modifiy the + * appropriate fields. + */ +static void +get_joliet_vol_desc(struct iso_primary_descriptor *jvol_desc) +{ + jvol_desc->type[0] = ISO_VD_SUPPLEMENTARY; + jvol_desc->version[0] = 1; + jvol_desc->file_structure_version[0] = 1; + + /* + * For now, always do Unicode level 3. + * I don't really know what 1 and 2 are - perhaps a more limited + * Unicode set. + * FIXME(eric) - how does Romeo fit in here? + */ + sprintf(jvol_desc->escape_sequences, "%%/%c", ucs_codes[ucs_level]); + + /* Until we have Unicode path tables, leave these unset. */ + set_733((char *) jvol_desc->path_table_size, jpath_table_size); + set_731(jvol_desc->type_l_path_table, jpath_table[0]); + set_731(jvol_desc->opt_type_l_path_table, jpath_table[1]); + set_732(jvol_desc->type_m_path_table, jpath_table[2]); + set_732(jvol_desc->opt_type_m_path_table, jpath_table[3]); + + /* Set this one up. */ + memcpy(jvol_desc->root_directory_record, &jroot_record, + offsetof(struct iso_directory_record, name[0]) + 1); + + /* + * Finally, we have a bunch of strings to convert to Unicode. + * FIXME(eric) - I don't know how to do this in general, + * so we will just be really lazy and do a char -> short conversion. + * We probably will want to filter any characters >= 0x80. + */ + convert_to_unicode((Uchar *) jvol_desc->system_id, + sizeof (jvol_desc->system_id), NULL, in_nls); + convert_to_unicode((Uchar *) jvol_desc->volume_id, + sizeof (jvol_desc->volume_id), NULL, in_nls); + convert_to_unicode((Uchar *) jvol_desc->volume_set_id, + sizeof (jvol_desc->volume_set_id), NULL, in_nls); + convert_to_unicode((Uchar *) jvol_desc->publisher_id, + sizeof (jvol_desc->publisher_id), NULL, in_nls); + convert_to_unicode((Uchar *) jvol_desc->preparer_id, + sizeof (jvol_desc->preparer_id), NULL, in_nls); + convert_to_unicode((Uchar *) jvol_desc->application_id, + sizeof (jvol_desc->application_id), NULL, in_nls); + convert_to_unicode((Uchar *) jvol_desc->copyright_file_id, + sizeof (jvol_desc->copyright_file_id), NULL, in_nls); + convert_to_unicode((Uchar *) jvol_desc->abstract_file_id, + sizeof (jvol_desc->abstract_file_id), NULL, in_nls); + convert_to_unicode((Uchar *) jvol_desc->bibliographic_file_id, + sizeof (jvol_desc->bibliographic_file_id), NULL, in_nls); +} + +static void +assign_joliet_directory_addresses(struct directory *node) +{ + int dir_size; + struct directory *dpnt; + + dpnt = node; + + while (dpnt) { + if ((dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0) { + /* + * If we already have an extent for this + * (i.e. it came from a multisession disc), then + * don't reassign a new extent. + */ + dpnt->jpath_index = next_jpath_index++; + if (dpnt->jextent == 0) { + dpnt->jextent = last_extent; + dir_size = ISO_BLOCKS(dpnt->jsize); + last_extent += dir_size; + } + } + /* skip if hidden - but not for the rr_moved dir */ + if (dpnt->subdir && (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir)) { + assign_joliet_directory_addresses(dpnt->subdir); + } + dpnt = dpnt->next; + } +} + +static void +build_jpathlist(struct directory *node) +{ + struct directory *dpnt; + + dpnt = node; + + while (dpnt) { + if ((dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0) { + jpathlist[dpnt->jpath_index] = dpnt; + } + if (dpnt->subdir) + build_jpathlist(dpnt->subdir); + dpnt = dpnt->next; + } +}/* build_jpathlist(... */ + +static int +joliet_compare_paths(void const *r, void const *l) +{ + struct directory const *ll = *(struct directory * const *) l; + struct directory const *rr = *(struct directory * const *) r; + int rparent, + lparent; + char *rpnt, + *lpnt; + unsigned char rtmp[2], + ltmp[2]; + struct unls_table *rinls, *linls; + + /* make sure root directory is first */ + if (rr == root) + return (-1); + + if (ll == root) + return (1); + + rparent = rr->parent->jpath_index; + lparent = ll->parent->jpath_index; + if (rr->parent == reloc_dir) { + rparent = rr->self->parent_rec->filedir->jpath_index; + } + if (ll->parent == reloc_dir) { + lparent = ll->self->parent_rec->filedir->jpath_index; + } + if (rparent < lparent) { + return (-1); + } + if (rparent > lparent) { + return (1); + } +#ifdef APPLE_HYB + /* + * we may be using the HFS name - so select the correct input + * charset + */ + if (USE_MAC_NAME(rr->self)) { + rpnt = rr->self->hfs_ent->name; + rinls = hfs_inls; + } else { + rpnt = rr->self->name; + rinls = in_nls; + } + + if (USE_MAC_NAME(ll->self)) { + lpnt = ll->self->hfs_ent->name; + linls = hfs_inls; + } else { + lpnt = ll->self->name; + linls = in_nls; + } +#else + rpnt = rr->self->name; + lpnt = ll->self->name; + linls = rinls = in_nls; +#endif /* APPLE_HYB */ + + /* compare the Unicode names */ + + while (*rpnt && *lpnt) { +#ifdef USE_ICONV + size_t ri, li; + + ri = convert_to_unicode(rtmp, 2, rpnt, rinls); + li = convert_to_unicode(ltmp, 2, lpnt, linls); + rpnt += ri; + lpnt += li; + if(!ri && !li) + return (0); + else if(ri && !li) + return (1); + else if(!ri && li) + return (-1); +#else + convert_to_unicode(rtmp, 2, rpnt, rinls); + convert_to_unicode(ltmp, 2, lpnt, linls); +#endif + + if (a_to_u_2_byte(rtmp) < a_to_u_2_byte(ltmp)) + return (-1); + if (a_to_u_2_byte(rtmp) > a_to_u_2_byte(ltmp)) + return (1); + +#ifndef USE_ICONV + rpnt++; + lpnt++; +#endif + } + + if (*rpnt) + return (1); + if (*lpnt) + return (-1); + + return (0); + +}/* compare_paths(... */ + +static int +generate_joliet_path_tables() +{ + struct directory_entry *de; + struct directory *dpnt; + int fix; + int j; + int namelen; + char *npnt; + char *npnt1; + int tablesize; + + /* First allocate memory for the tables and initialize the memory */ + tablesize = jpath_blocks << 11; + jpath_table_m = (char *) e_malloc(tablesize); + jpath_table_l = (char *) e_malloc(tablesize); + memset(jpath_table_l, 0, tablesize); + memset(jpath_table_m, 0, tablesize); + + /* Now start filling in the path tables. Start with root directory */ + jpath_table_index = 0; + jpathlist = (struct directory **) e_malloc(sizeof (struct directory *) + * next_jpath_index); + memset(jpathlist, 0, sizeof (struct directory *) * next_jpath_index); + build_jpathlist(root); + + do { + fix = 0; +#ifdef PROTOTYPES + qsort(&jpathlist[1], next_jpath_index - 1, sizeof (struct directory *), + (int (*) (const void *, const void *)) joliet_compare_paths); +#else + qsort(&jpathlist[1], next_jpath_index - 1, sizeof (struct directory *), + joliet_compare_paths); +#endif + + for (j = 1; j < next_jpath_index; j++) { + if (jpathlist[j]->jpath_index != j) { + jpathlist[j]->jpath_index = j; + fix++; + } + } + } while (fix); + + for (j = 1; j < next_jpath_index; j++) { + dpnt = jpathlist[j]; + if (!dpnt) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Entry %d not in path tables\n", j); +#else + fprintf(stderr, "Entry %d not in path tables\n", j); + exit(1); +#endif + } + npnt = dpnt->de_name; + + npnt1 = strrchr(npnt, PATH_SEPARATOR); + if (npnt1) { + npnt = npnt1 + 1; + } + de = dpnt->self; + if (!de) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Fatal Joliet goof - directory has amnesia\n"); +#else + fprintf(stderr, + "Fatal Joliet goof - directory has amnesia\n"); + exit(1); +#endif + } +#ifdef APPLE_HYB + if (USE_MAC_NAME(de)) + namelen = joliet_strlen(de->hfs_ent->name, hfs_inls); + else +#endif /* APPLE_HYB */ + namelen = joliet_strlen(de->name, in_nls); + + if (dpnt == root) { + jpath_table_l[jpath_table_index] = 1; + jpath_table_m[jpath_table_index] = 1; + } else { + jpath_table_l[jpath_table_index] = namelen; + jpath_table_m[jpath_table_index] = namelen; + } + jpath_table_index += 2; + + set_731(jpath_table_l + jpath_table_index, dpnt->jextent); + set_732(jpath_table_m + jpath_table_index, dpnt->jextent); + jpath_table_index += 4; + + if (dpnt->parent->jpath_index > 0xffff) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Unable to generate sane path tables - too many directories (%d)\n", + dpnt->parent->jpath_index); +#else + fprintf(stderr, + "Unable to generate sane path tables - too many directories (%d)\n", + dpnt->parent->jpath_index); + exit(1); +#endif + } + + if (dpnt->parent != reloc_dir) { + set_721(jpath_table_l + jpath_table_index, + dpnt->parent->jpath_index); + set_722(jpath_table_m + jpath_table_index, + dpnt->parent->jpath_index); + } else { + set_721(jpath_table_l + jpath_table_index, + dpnt->self->parent_rec->filedir->jpath_index); + set_722(jpath_table_m + jpath_table_index, + dpnt->self->parent_rec->filedir->jpath_index); + } + + jpath_table_index += 2; + + /* + * The root directory is still represented in non-unicode + * fashion. + */ + if (dpnt == root) { + jpath_table_l[jpath_table_index] = 0; + jpath_table_m[jpath_table_index] = 0; + jpath_table_index++; + } else { +#ifdef APPLE_HYB + if (USE_MAC_NAME(de)) { + convert_to_unicode((Uchar *) jpath_table_l + + jpath_table_index, + namelen, de->hfs_ent->name, hfs_inls); + convert_to_unicode((Uchar *) jpath_table_m + + jpath_table_index, + namelen, de->hfs_ent->name, hfs_inls); + } else { +#endif /* APPLE_HYB */ + convert_to_unicode((Uchar *) jpath_table_l + + jpath_table_index, + namelen, de->name, in_nls); + convert_to_unicode((Uchar *) jpath_table_m + + jpath_table_index, + namelen, de->name, in_nls); +#ifdef APPLE_HYB + } +#endif /* APPLE_HYB */ + + jpath_table_index += namelen; + } + + if (jpath_table_index & 1) { + jpath_table_index++; /* For odd lengths we pad */ + } + } + + free(jpathlist); + if (jpath_table_index != jpath_table_size) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Joliet path table lengths do not match %d expected: %d\n", + jpath_table_index, + jpath_table_size); +#else + fprintf(stderr, + "Joliet path table lengths do not match %d expected: %d\n", + jpath_table_index, + jpath_table_size); +#endif + } + return (0); +}/* generate_path_tables(... */ + +static void +generate_one_joliet_directory(struct directory *dpnt, FILE *outfile) +{ + unsigned int dir_index; + char *directory_buffer; + int new_reclen; + struct directory_entry *s_entry; + struct directory_entry *s_entry1; + struct iso_directory_record jrec; + unsigned int total_size; + int cvt_len; + struct directory *finddir; + + total_size = ISO_ROUND_UP(dpnt->jsize); + directory_buffer = (char *) e_malloc(total_size); + memset(directory_buffer, 0, total_size); + dir_index = 0; + + s_entry = dpnt->jcontents; + while (s_entry) { + if (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) { + s_entry = s_entry->jnext; + continue; + } + /* + * If this entry was a directory that was relocated, + * we have a bit of trouble here. We need to dig out the real + * thing and put it back here. In the Joliet tree, there is + * no relocated rock ridge, as there are no depth limits to a + * directory tree. + */ + if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) { + for (s_entry1 = reloc_dir->contents; s_entry1; + s_entry1 = s_entry1->next) { + if (s_entry1->parent_rec == s_entry) { + break; + } + } + if (s_entry1 == NULL) { + /* We got trouble. */ +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Unable to locate relocated directory\n"); +#else + fprintf(stderr, + "Unable to locate relocated directory\n"); + exit(1); +#endif + } + } else { + s_entry1 = 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_entry1->jreclen; + if ((dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE) { + dir_index = ISO_ROUND_UP(dir_index); + } + memcpy(&jrec, &s_entry1->isorec, offsetof(struct iso_directory_record, name[0])); + +#ifdef APPLE_HYB + /* Use the HFS name if it exists */ + if (USE_MAC_NAME(s_entry1)) + cvt_len = joliet_strlen(s_entry1->hfs_ent->name, hfs_inls); + else +#endif /* APPLE_HYB */ + cvt_len = joliet_strlen(s_entry1->name, in_nls); + + /* + * Fix the record length + * - this was the non-Joliet version we were seeing. + */ + jrec.name_len[0] = cvt_len; + jrec.length[0] = s_entry1->jreclen; + + /* + * If this is a directory, + * fix the correct size and extent number. + */ + if ((jrec.flags[0] & ISO_DIRECTORY) != 0) { + if (strcmp(s_entry1->name, ".") == 0) { + jrec.name_len[0] = 1; + set_733((char *) jrec.extent, dpnt->jextent); + set_733((char *) jrec.size, ISO_ROUND_UP(dpnt->jsize)); + } else if (strcmp(s_entry1->name, "..") == 0) { + jrec.name_len[0] = 1; + if (dpnt->parent == reloc_dir) { + set_733((char *)jrec.extent, dpnt->self->parent_rec->filedir->jextent); + set_733((char *)jrec.size, ISO_ROUND_UP(dpnt->self->parent_rec->filedir->jsize)); + } else { + set_733((char *)jrec.extent, dpnt->parent->jextent); + set_733((char *)jrec.size, ISO_ROUND_UP(dpnt->parent->jsize)); + } + } else { + if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) { + finddir = reloc_dir->subdir; + } else { + finddir = dpnt->subdir; + } + while (1 == 1) { + if (finddir->self == s_entry1) + break; + finddir = finddir->next; + if (!finddir) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Fatal goof - unable to find directory location\n"); +#else + fprintf(stderr, "Fatal goof - unable to find directory location\n"); + exit(1); +#endif + } + } + set_733((char *)jrec.extent, finddir->jextent); + set_733((char *)jrec.size, + ISO_ROUND_UP(finddir->jsize)); + } + } + memcpy(directory_buffer + dir_index, &jrec, + offsetof(struct iso_directory_record, name[0])); + + dir_index += offsetof(struct iso_directory_record, name[0]); + + /* + * Finally dump the Unicode version of the filename. + * Note - . and .. are the same as with non-Joliet discs. + */ + if ((jrec.flags[0] & ISO_DIRECTORY) != 0 && + strcmp(s_entry1->name, ".") == 0) { + directory_buffer[dir_index++] = 0; + } else if ((jrec.flags[0] & ISO_DIRECTORY) != 0 && + strcmp(s_entry1->name, "..") == 0) { + directory_buffer[dir_index++] = 1; + } else { +#ifdef APPLE_HYB + if (USE_MAC_NAME(s_entry1)) { + /* Use the HFS name if it exists */ + convert_to_unicode( + (Uchar *) directory_buffer+dir_index, + cvt_len, + s_entry1->hfs_ent->name, hfs_inls); + } else +#endif /* APPLE_HYB */ + { + convert_to_unicode( + (Uchar *) directory_buffer+dir_index, + cvt_len, + s_entry1->name, in_nls); + } + dir_index += cvt_len; + } + + if (dir_index & 1) { + directory_buffer[dir_index++] = 0; + } + s_entry = s_entry->jnext; + } + + if (dpnt->jsize != dir_index) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Unexpected joliet directory length %d expected: %d '%s'\n", + dpnt->jsize, + dir_index, dpnt->de_name); +#else + fprintf(stderr, + "Unexpected joliet directory length %d expected: %d '%s'\n", + dpnt->jsize, + dir_index, dpnt->de_name); +#endif + } + jtwrite(directory_buffer, total_size, 1, 0, FALSE); + xfwrite(directory_buffer, total_size, 1, outfile, 0, FALSE); + last_extent_written += total_size >> 11; + free(directory_buffer); +}/* generate_one_joliet_directory(... */ + +static int +joliet_sort_n_finish(struct directory *this_dir) +{ + struct directory_entry *s_entry; + int status = 0; + + /* + * don't want to skip this directory if it's the reloc_dir + * at the moment + */ + if (this_dir != reloc_dir && + this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) { + return (0); + } + for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { + /* skip hidden entries */ + if ((s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0) { + continue; + } + /* + * First update the path table sizes for directories. + * + * Finally, set the length of the directory entry if Joliet is + * used. The name is longer, but no Rock Ridge is ever used + * here, so depending upon the options the entry size might + * turn out to be about the same. The Unicode name is always + * a multiple of 2 bytes, so we always add 1 to make it an + * even number. + */ + if (s_entry->isorec.flags[0] & ISO_DIRECTORY) { + if (strcmp(s_entry->name, ".") != 0 && + strcmp(s_entry->name, "..") != 0) { +#ifdef APPLE_HYB + if (USE_MAC_NAME(s_entry)) + /* Use the HFS name if it exists */ + jpath_table_size += + joliet_strlen(s_entry->hfs_ent->name, hfs_inls) + + offsetof(struct iso_path_table, name[0]); + else +#endif /* APPLE_HYB */ + jpath_table_size += + joliet_strlen(s_entry->name, in_nls) + + offsetof(struct iso_path_table, name[0]); + if (jpath_table_size & 1) { + jpath_table_size++; + } + } else { + if (this_dir == root && + strlen(s_entry->name) == 1) { + + jpath_table_size += 1 + offsetof(struct iso_path_table, name[0]); + if (jpath_table_size & 1) + jpath_table_size++; + } + } + } + if (strcmp(s_entry->name, ".") != 0 && + strcmp(s_entry->name, "..") != 0) { +#ifdef APPLE_HYB + if (USE_MAC_NAME(s_entry)) + /* Use the HFS name if it exists */ + s_entry->jreclen = + offsetof(struct iso_directory_record, name[0]) + + joliet_strlen(s_entry->hfs_ent->name, hfs_inls) + + 1; + else +#endif /* APPLE_HYB */ + s_entry->jreclen = + offsetof(struct iso_directory_record, name[0]) + + joliet_strlen(s_entry->name, in_nls) + + 1; + } else { + /* + * Special - for '.' and '..' we generate the same + * records we did for non-Joliet discs. + */ + s_entry->jreclen = + offsetof(struct iso_directory_record, name[0]) + + 1; + } + + + } + + if ((this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) != 0) { + return (0); + } + this_dir->jcontents = this_dir->contents; + status = joliet_sort_directory(&this_dir->jcontents); + + /* + * 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->jcontents; + /* + * XXX Is it ok to comment this out? + */ +/*XXX JS this_dir->ce_bytes = 0;*/ + for (s_entry = this_dir->jcontents; s_entry; + s_entry = s_entry->jnext) { + int jreclen; + + if ((s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0) { + continue; + } + jreclen = s_entry->jreclen; + + if ((this_dir->jsize & (SECTOR_SIZE - 1)) + jreclen >= + SECTOR_SIZE) { + this_dir->jsize = ISO_ROUND_UP(this_dir->jsize); + } + this_dir->jsize += jreclen; + } + return (status); +} + +/* + * Similar to the iso9660 case, + * except here we perform a full sort based upon the + * regular name of the file, not the 8.3 version. + */ +static int +joliet_compare_dirs(const void *rr, const void *ll) +{ + char *rpnt, + *lpnt; + struct directory_entry **r, + **l; + unsigned char rtmp[2], + ltmp[2]; + struct unls_table *linls, *rinls; + + r = (struct directory_entry **) rr; + l = (struct directory_entry **) ll; + +#ifdef APPLE_HYB + /* + * we may be using the HFS name - so select the correct input + * charset + */ + if (USE_MAC_NAME(*r)) { + rpnt = (*r)->hfs_ent->name; + rinls = hfs_inls; + } else { + rpnt = (*r)->name; + rinls = in_nls; + } + + if (USE_MAC_NAME(*l)) { + lpnt = (*l)->hfs_ent->name; + linls = hfs_inls; + } else { + lpnt = (*l)->name; + linls = in_nls; + } +#else + rpnt = (*r)->name; + lpnt = (*l)->name; + rinls = linls = in_nls; +#endif /* APPLE_HYB */ + + /* + * If the entries are the same, this is an error. + * Joliet specs allow for a maximum of 64 characters. + */ + if (strncmp(rpnt, lpnt, jlen) == 0) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Error: %s and %s have the same Joliet name\n", + (*r)->whole_name, (*l)->whole_name); +#else + fprintf(stderr, + "Error: %s and %s have the same Joliet name\n", + (*r)->whole_name, (*l)->whole_name); +#endif + jsort_goof++; + } + /* + * Put the '.' and '..' entries on the head of the sorted list. + * For normal ASCII, this always happens to be the case, but out of + * band characters cause this not to be the case sometimes. + */ + if (strcmp(rpnt, ".") == 0) + return (-1); + if (strcmp(lpnt, ".") == 0) + return (1); + + if (strcmp(rpnt, "..") == 0) + return (-1); + if (strcmp(lpnt, "..") == 0) + return (1); + +#ifdef DVD_VIDEO + /* + * There're rumors claiming that some players assume VIDEO_TS.IFO + * to be the first file in VIDEO_TS/ catalog. Well, it's basically + * the only file a player has to actually look for, as the whole + * video content can be "rolled down" from this file alone. + * <appro@fy.chalmers.se> + */ + /* + * XXX This code has to be moved from the Joliet implementation + * XXX to the UDF implementation if we implement decent UDF support + * XXX with a separate name space for the UDF file tree. + */ + if (dvd_video) { + if (strcmp(rpnt, "VIDEO_TS.IFO") == 0) + return (-1); + if (strcmp(lpnt, "VIDEO_TS.IFO") == 0) + return (1); + } +#endif + + while (*rpnt && *lpnt) { +#ifdef USE_ICONV + size_t ri, li; +#endif + if (*rpnt == ';' && *lpnt != ';') + return (-1); + if (*rpnt != ';' && *lpnt == ';') + return (1); + + if (*rpnt == ';' && *lpnt == ';') + return (0); + + /* + * Extensions are not special here. + * Don't treat the dot as something that must be bumped to + * the start of the list. + */ +#if 0 + if (*rpnt == '.' && *lpnt != '.') + return (-1); + if (*rpnt != '.' && *lpnt == '.') + return (1); +#endif + +#ifdef USE_ICONV + + ri = convert_to_unicode(rtmp, 2, rpnt, rinls); + li = convert_to_unicode(ltmp, 2, lpnt, linls); + rpnt += ri; + lpnt += li; + if(!ri && !li) + return (0); + else if(ri && !li) + return (1); + else if(!ri && li) + return (-1); +#else + convert_to_unicode(rtmp, 2, rpnt, rinls); + convert_to_unicode(ltmp, 2, lpnt, linls); +#endif + + if (a_to_u_2_byte(rtmp) < a_to_u_2_byte(ltmp)) + return (-1); + if (a_to_u_2_byte(rtmp) > a_to_u_2_byte(ltmp)) + return (1); + +#ifndef USE_ICONV + rpnt++; + lpnt++; +#endif + } + if (*rpnt) + return (1); + if (*lpnt) + return (-1); + return (0); +} + + +/* + * Function: sort_directory + * + * Purpose: Sort the directory in the appropriate ISO9660 + * order. + * + * Notes: Returns 0 if OK, returns > 0 if an error occurred. + */ +static int +joliet_sort_directory(struct directory_entry **sort_dir) +{ + int dcount = 0; + int i; + struct directory_entry *s_entry; + struct directory_entry **sortlist; + + s_entry = *sort_dir; + while (s_entry) { + /* skip hidden entries */ + if (!(s_entry->de_flags & INHIBIT_JOLIET_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) { + /* skip hidden entries */ + if (!(s_entry->de_flags & INHIBIT_JOLIET_ENTRY)) { + sortlist[dcount] = s_entry; + dcount++; + } + s_entry = s_entry->next; + } + + jsort_goof = 0; +#ifdef PROTOTYPES + qsort(sortlist, dcount, sizeof (struct directory_entry *), + (int (*) (const void *, const void *)) joliet_compare_dirs); +#else + qsort(sortlist, dcount, sizeof (struct directory_entry *), + joliet_compare_dirs); +#endif + + /* Now reassemble the linked list in the proper sorted order */ + for (i = 0; i < dcount - 1; i++) { + sortlist[i]->jnext = sortlist[i + 1]; + } + + sortlist[dcount - 1]->jnext = NULL; + *sort_dir = sortlist[0]; + + free(sortlist); + return (jsort_goof); +} + +int +joliet_sort_tree(struct directory *node) +{ + struct directory *dpnt; + int ret = 0; + + dpnt = node; + + while (dpnt) { + ret = joliet_sort_n_finish(dpnt); + if (ret) { + break; + } + if (dpnt->subdir) + ret = joliet_sort_tree(dpnt->subdir); + if (ret) { + break; + } + dpnt = dpnt->next; + } + return (ret); +} + +static void +generate_joliet_directories(struct directory *node, FILE *outfile) +{ + struct directory *dpnt; + + dpnt = node; + + while (dpnt) { + if ((dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0) { + /* + * In theory we should never reuse a directory, so this + * doesn't make much sense. + */ + if (dpnt->jextent > session_start) { + generate_one_joliet_directory(dpnt, outfile); + } + } + /* skip if hidden - but not for the rr_moved dir */ + if (dpnt->subdir && + (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || + dpnt == reloc_dir)) { + generate_joliet_directories(dpnt->subdir, outfile); + } + dpnt = dpnt->next; + } +} + + +/* + * Function to write the EVD for the disc. + */ +static int +jpathtab_write(FILE *outfile) +{ + /* Next we write the path tables */ + jtwrite(jpath_table_l, jpath_blocks << 11, 1, 0, FALSE); + xfwrite(jpath_table_l, jpath_blocks << 11, 1, outfile, 0, FALSE); + last_extent_written += jpath_blocks; + jtwrite(jpath_table_m, jpath_blocks << 11, 1, 0, FALSE); + xfwrite(jpath_table_m, jpath_blocks << 11, 1, outfile, 0, FALSE); + last_extent_written += jpath_blocks; + free(jpath_table_l); + free(jpath_table_m); + jpath_table_l = NULL; + jpath_table_m = NULL; + return (0); +} + +static int +jdirtree_size(int starting_extent) +{ + assign_joliet_directory_addresses(root); + return (0); +} + +static int +jroot_gen() +{ + jroot_record.length[0] = + 1 + offsetof(struct iso_directory_record, name[0]); + jroot_record.ext_attr_length[0] = 0; + set_733((char *) jroot_record.extent, root->jextent); + set_733((char *) jroot_record.size, ISO_ROUND_UP(root->jsize)); + iso9660_date(jroot_record.date, root_statbuf.st_mtime); + jroot_record.flags[0] = ISO_DIRECTORY; + jroot_record.file_unit_size[0] = 0; + jroot_record.interleave[0] = 0; + set_723(jroot_record.volume_sequence_number, volume_sequence_number); + jroot_record.name_len[0] = 1; + return (0); +} + +static int +jdirtree_write(FILE *outfile) +{ + generate_joliet_directories(root, outfile); + return (0); +} + +/* + * Function to write the EVD for the disc. + */ +static int +jvd_write(FILE *outfile) +{ + struct iso_primary_descriptor jvol_desc; + + /* Next we write out the boot volume descriptor for the disc */ + jvol_desc = vol_desc; + get_joliet_vol_desc(&jvol_desc); + jtwrite(&jvol_desc, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(&jvol_desc, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + return (0); +} + +/* + * Functions to describe padding block at the start of the disc. + */ +static int +jpathtab_size(int starting_extent) +{ + jpath_table[0] = starting_extent; + jpath_table[1] = 0; + jpath_table[2] = jpath_table[0] + jpath_blocks; + jpath_table[3] = 0; + + last_extent += 2 * jpath_blocks; + return (0); +} + +struct output_fragment joliet_desc = {NULL, oneblock_size, jroot_gen, jvd_write, "Joliet Volume Descriptor" }; +struct output_fragment jpathtable_desc = {NULL, jpathtab_size, generate_joliet_path_tables, jpathtab_write, "Joliet path table" }; +struct output_fragment jdirtree_desc = {NULL, jdirtree_size, NULL, jdirtree_write, "Joliet directory tree" }; diff --git a/genisoimage/jte.c b/genisoimage/jte.c new file mode 100644 index 0000000..0dff289 --- /dev/null +++ b/genisoimage/jte.c @@ -0,0 +1,1042 @@ +/* + * jte.c + * + * Copyright (c) 2004-2006 Steve McIntyre <steve@einval.com> + * + * Implementation of the Jigdo Template Engine - make jigdo files + * directly when making ISO images + * + * GNU GPL v2 + */ + +#include <mconfig.h> +#include "genisoimage.h" +#include <timedefs.h> +#include <fctldefs.h> +#include <zlib.h> +#include <bzlib.h> +#include <regex.h> +#ifdef SORTING +#include "match.h" +#endif /* SORTING */ +#include <errno.h> +#include <schily.h> +#ifdef DVD_VIDEO +#include "dvd_reader.h" +#include "dvd_file.h" +#include "ifo_read.h" +#include "endianconv.h" +#include "checksum.h" +#endif +#ifdef APPLE_HYB +#include <ctype.h> +#endif + +#ifdef VMS +#include "vms.h" +#endif + +/* Different types used in building our state list below */ +#define JTET_FILE_MATCH 1 +#define JTET_NOMATCH 2 + +#define JTE_VER_MAJOR 0x0001 +#define JTE_VER_MINOR 0x0013 +#define JTE_NAME "JTE" +#define JTE_COMMENT "JTE at http://www.einval.com/~steve/software/JTE/ ; jigdo at http://atterer.org/jigdo/" + +#define JIGDO_TEMPLATE_VERSION "1.1" + +/* + Simple list to hold the results of -jigdo-exclude and + -jigdo-force-match command line options. Seems easiest to do this + using regexps. +*/ +struct path_match +{ + regex_t match_pattern; + char *match_rule; + struct path_match *next; +}; + +/* List of mappings e.g. Debian=/mirror/debian */ +struct path_mapping +{ + char *from; + char *to; + struct path_mapping *next; +}; + +FILE *jtjigdo = NULL; /* File handle used throughout for the jigdo file */ +FILE *jttemplate = NULL; /* File handle used throughout for the template file */ +char *jjigdo_out = NULL; /* Output name for jigdo .jigdo file; NULL means don't do it */ +char *jtemplate_out = NULL; /* Output name for jigdo template file; NULL means don't do it */ +char *jmd5_list = NULL; /* Name of file to use for MD5 checking */ +int jte_min_size = MIN_JIGDO_FILE_SIZE; +jtc_t jte_template_compression = JTE_TEMP_GZIP; +struct path_match *exclude_list = NULL; +struct path_match *include_list = NULL; +struct path_mapping *map_list = NULL; +unsigned long long template_size = 0; +unsigned long long image_size = 0; +int checksum_algo_iso = (CHECK_MD5_USED | \ + CHECK_SHA1_USED | \ + CHECK_SHA256_USED | \ + CHECK_SHA512_USED); +int checksum_algo_tmpl = CHECK_MD5_USED; + +static checksum_context_t *iso_context = NULL; +static checksum_context_t *template_context = NULL; + +/* List of files that we've seen, ready to write into the template and + jigdo files */ +typedef struct _file_entry +{ + unsigned char md5[16]; + off_t file_length; + unsigned long long rsyncsum; + char *filename; +} file_entry_t; + +typedef struct _unmatched_entry +{ + off_t uncompressed_length; +} unmatched_entry_t; + +typedef struct _entry +{ + int entry_type; /* JTET_TYPE as above */ + struct _entry *next; + union + { + file_entry_t file; + unmatched_entry_t chunk; + } data; +} entry_t; + +typedef struct _jigdo_file_entry +{ + unsigned char type; + unsigned char fileLen[6]; + unsigned char fileRsync[8]; + unsigned char fileMD5[16]; +} jigdo_file_entry_t; + +typedef struct _jigdo_chunk_entry +{ + unsigned char type; + unsigned char skipLen[6]; +} jigdo_chunk_entry_t; + +typedef struct _jigdo_image_entry +{ + unsigned char type; + unsigned char imageLen[6]; + unsigned char imageMD5[16]; + unsigned char blockLen[4]; +} jigdo_image_entry_t; + +typedef struct _md5_list_entry +{ + struct _md5_list_entry *next; + unsigned char MD5[16]; + unsigned long long size; + char *filename; +} md5_list_entry_t; + +entry_t *entry_list = NULL; +entry_t *entry_last = NULL; +FILE *t_file = NULL; +FILE *j_file = NULL; +int num_matches = 0; +int num_chunks = 0; +md5_list_entry_t *md5_list = NULL; +md5_list_entry_t *md5_last = NULL; + +/* Grab the file component from a full path */ +static char *file_base_name(char *path) +{ + char *endptr = path; + char *ptr = path; + + while (*ptr != '\0') + { + if ('/' == *ptr) + endptr = ++ptr; + else + ++ptr; + } + return endptr; +} + +/* Build the list of exclusion regexps */ +extern int jte_add_exclude(char *pattern) +{ + struct path_match *new = NULL; + + new = malloc(sizeof *new); + if (!new) + return ENOMEM; + + regcomp(&new->match_pattern, pattern, REG_NEWLINE); + new->match_rule = pattern; + + /* Order on the exclude list doesn't matter! */ + new->next = exclude_list; + + exclude_list = new; + return 0; +} + +/* Check if the file should be excluded because of a filename match. 1 + means exclude, 0 means not */ +static int check_exclude_by_name(char *filename, char **matched) +{ + struct path_match *ptr = exclude_list; + regmatch_t pmatch[1]; + int i = 0; + + while (ptr) + { + if (!regexec(&ptr->match_pattern, filename, 1, pmatch, 0)) + { + *matched = ptr->match_rule; + return 1; + } + ptr = ptr->next; + } + + /* Not matched, so return 0 */ + return 0; +} + +/* Build the list of required inclusion regexps */ +extern int jte_add_include(char *pattern) +{ + struct path_match *new = NULL; + + new = malloc(sizeof *new); + if (!new) + return ENOMEM; + + regcomp(&new->match_pattern, pattern, REG_NEWLINE); + new->match_rule = pattern; + + /* Order on the include list doesn't matter! */ + new->next = include_list; + + include_list = new; + return 0; +} + +/* Check if a file has to be MD5-matched to be valid. If we get called + here, we've failed to match any of the MD5 entries we were + given. If the path to the filename matches one of the paths in our + list, clearly it must have been corrupted. Abort with an error. */ +static void check_md5_file_match(char *filename) +{ + struct path_match *ptr = include_list; + regmatch_t pmatch[1]; + int i = 0; + + while (ptr) + { + if (!regexec(&ptr->match_pattern, filename, 1, pmatch, 0)) + { +#ifdef USE_LIBSCHILY + comerr("File %s should have matched an MD5 entry, but didn't! (Rule '%s')\n", filename, ptr->match_rule); +#else + fprintf(stderr, "File %s should have matched an MD5 entry, but didn't! (Rule '%s')\n", filename, ptr->match_rule); + exit(1); +#endif + } + ptr = ptr->next; + } +} + +/* Should we list a file separately in the jigdo output, or should we + just dump it into the template file as binary data? Three things + cases to look for here: + + 1. Small files are better simply folded in, as they take less space that way. + + 2. Files in /doc (for example) may change in the archive all the + time and it's better to not have to fetch snapshot copies if we + can avoid it. + + 3. Files living in specified paths *must* match an entry in the + md5-list, or they must have been corrupted. If we find a corrupt + file, bail out with an error. + +*/ +extern int list_file_in_jigdo(char *filename, off_t size, char **realname, unsigned char md5[16]) +{ + char *matched_rule; + md5_list_entry_t *entry = md5_list; + int md5sum_done = 0; + + if (!jtemplate_out) + return 0; + + memset(md5, 0, sizeof(md5)); + + /* Cheaper to check file size first */ + if (size < jte_min_size) + { + if (verbose > 1) + fprintf(stderr, "Jigdo-ignoring file %s; it's too small\n", filename); + return 0; + } + + /* Now check the excluded list by name */ + if (check_exclude_by_name(filename, &matched_rule)) + { + if (verbose > 1) + fprintf(stderr, "Jigdo-ignoring file %s; it's covered in the exclude list by \"%s\"\n", filename, matched_rule); + return 0; + } + + /* Check to see if the file is in our md5 list. Check three things: + + 1. the size + 2. the filename + 3. (only if the first 2 match) the md5sum + + If we get a match for all three, include the file and return + the full path to the file that we have gleaned from the mirror. + */ + + while (entry) + { + if (size == entry->size) + { + if (!strcmp(file_base_name(filename), file_base_name(entry->filename))) + { + if (!md5sum_done) + { + calculate_md5sum(filename, size, md5); + md5sum_done = 1; + } + if (!memcmp(md5, entry->MD5, sizeof(entry->MD5))) + { + *realname = entry->filename; + return 1; + } + } + } + entry = entry->next; + } + + /* We haven't found an entry in our MD5 list to match this + * file. If we should have done, complain and bail out. */ + check_md5_file_match(filename); + return 0; +} + +/* Add a mapping of pathnames (e.g. Debian=/mirror/debian). We should + be passed TO=FROM here */ +extern int jte_add_mapping(char *arg) +{ + int error = 0; + struct path_mapping *new = NULL; + struct path_mapping *entry = NULL; + char *p = arg; + char *from = NULL; + char *to = NULL; + + /* Find the "=" in the string passed. Set it to NULL and we can + use the string in-place */ + while (*p) + { + if ('=' == *p) + { + *p = 0; + p++; + to = arg; + from = p; + } + p++; + } + if (!from || !strlen(from) || !to || !strlen(to)) + return EINVAL; + + new = malloc(sizeof(*new)); + if (!new) + return ENOMEM; + + new->from = from; + new->to = to; + new->next = NULL; + + if (verbose > 0) + fprintf(stderr, "Adding mapping from %s to %s for the jigdo file\n", from, to); + if (!map_list) + map_list = new; + else + { + /* Order is important; add to the end of the list */ + entry = map_list; + while (NULL != entry->next) + entry = entry->next; + entry->next = new; + } + return 0; +} + +/* Check if the filename should be remapped; if so map it, otherwise + return the original name. */ +static char *remap_filename(char *filename) +{ + char *new_name = filename; + struct path_mapping *entry = map_list; + + while (entry) + { + if (!strncmp(filename, entry->from, strlen(entry->from))) + { + new_name = calloc(1, 2 + strlen(filename) + strlen(entry->to) - strlen(entry->from)); + if (!new_name) + { + fprintf(stderr, "Failed to malloc new filename; abort!\n"); + exit(1); + } + sprintf(new_name, "%s:%s", entry->to, &filename[strlen(entry->from)]); + return new_name; + } + entry = entry->next; + } + + /* No mapping in effect */ + return strdup(filename); +} + +/* Write data to the template file and update the MD5 sum */ +static size_t template_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + checksum_update(template_context, ptr, size * nmemb); + template_size += (unsigned long long)size * nmemb; + return fwrite(ptr, size, nmemb, stream); +} + +/* Create a new template file and initialise it */ +static void write_template_header() +{ + char buf[2048]; + int i = 0; + char *p = buf; + + memset(buf, 0, sizeof(buf)); + + template_context = checksum_init_context(checksum_algo_tmpl, "template"); + if (!template_context) + { +#ifdef USE_LIBSCHILY + comerr("cannot allocate template checksum contexts\n"); +#else + fprintf(stderr, "cannot allocate template checksum contexts\n"); + exit(1); +#endif + } + + i += sprintf(p, "JigsawDownload template %s %s/%d.%d \r\n", + JIGDO_TEMPLATE_VERSION, JTE_NAME, JTE_VER_MAJOR, JTE_VER_MINOR); + p = &buf[i]; + + i += sprintf(p, "%s \r\n", JTE_COMMENT); + p = &buf[i]; + + i += sprintf(p, "\r\n"); + template_fwrite(buf, i, 1, t_file); +} + +/* Read the MD5 list and build a list in memory for us to use later */ +static void add_md5_entry(unsigned char *md5, unsigned long long size, char *filename) +{ + int error = 0; + md5_list_entry_t *new = NULL; + + new = calloc(1, sizeof(md5_list_entry_t)); + memcpy(new->MD5, md5, sizeof(new->MD5)); + new->size = size; + new->filename = strdup(filename); + + /* Add to the end of the list */ + if (NULL == md5_last) + { + md5_last = new; + md5_list = new; + } + else + { + md5_last->next = new; + md5_last = new; + } +} + +/* Parse a 12-digit decimal number */ +static unsigned long long parse_number(unsigned char in[12]) +{ + unsigned long long size = 0; + int i = 0; + + for (i = 0; i < 12; i++) + { + size *= 10; + if (isdigit(in[i])) + size += (in[i] - '0'); + } + + return size; +} + +/* Read the MD5 list and build a list in memory for us to use later + MD5 list format: + + <---MD5---> <--Size--> <--Filename--> + 32 12 remaining +*/ +static void parse_md5_list(void) +{ + FILE *md5_file = NULL; + unsigned char buf[1024]; + unsigned char md5[16]; + char *filename = NULL; + unsigned char *numbuf = NULL; + int num_files = 0; + unsigned long long size = 0; + + md5_file = fopen(jmd5_list, "rb"); + if (!md5_file) + { +#ifdef USE_LIBSCHILY + comerr("cannot read from MD5 list file '%s'\n", jmd5_list); +#else + fprintf(stderr, "cannot read from MD5 list file '%s'\n", jmd5_list); + exit(1); +#endif + } + + memset(buf, 0, sizeof(buf)); + while (fgets((char *)buf, sizeof(buf), md5_file)) + { + numbuf = &buf[34]; + filename = (char *)&buf[48]; + /* Lose the trailing \n from the fgets() call */ + if (buf[strlen((char *)buf)-1] == '\n') + buf[strlen((char *)buf)-1] = 0; + + if (mk_MD5Parse(buf, md5)) + { +#ifdef USE_LIBSCHILY + comerr("cannot parse MD5 file '%s'\n", jmd5_list); +#else + fprintf(stderr, "cannot parse MD5 file '%s'\n", jmd5_list); + exit(1); +#endif + } + size = parse_number(numbuf); + add_md5_entry(md5, size, filename); + memset(buf, 0, sizeof(buf)); + num_files++; + } + if (verbose > 0) + fprintf(stderr, "parse_md5_list: added MD5 checksums for %d files\n", num_files); + fclose(md5_file); +} + +/* Initialise state and start the jigdo template file */ +void write_jt_header(FILE *template_file, FILE *jigdo_file) +{ + t_file = template_file; + j_file = jigdo_file; + + /* Start checksum work for the image */ + iso_context = checksum_init_context(checksum_algo_iso, "iso"); + if (!iso_context) + { +#ifdef USE_LIBSCHILY + comerr("cannot allocate iso checksum contexts\n"); +#else + fprintf(stderr, "cannot allocate iso checksum contexts\n"); + exit(1); +#endif + } + + /* Start the template file */ + write_template_header(); + + /* Load up the MD5 list if we've been given one */ + if (jmd5_list) + parse_md5_list(); +} + +/* Compress and flush out a buffer full of template data */ +static void flush_gzip_chunk(void *buffer, off_t size) +{ + z_stream c_stream; /* compression stream */ + unsigned char comp_size_out[6]; + unsigned char uncomp_size_out[6]; + off_t compressed_size_out = 0; + int err = 0; + unsigned char *comp_buf = NULL; + + c_stream.zalloc = NULL; + c_stream.zfree = NULL; + c_stream.opaque = NULL; + + err = deflateInit(&c_stream, Z_BEST_COMPRESSION); + comp_buf = malloc(2 * size); /* Worst case */ + c_stream.next_out = comp_buf; + c_stream.avail_out = 2 * size; + c_stream.next_in = buffer; + c_stream.avail_in = size; + + err = deflate(&c_stream, Z_NO_FLUSH); + err = deflate(&c_stream, Z_FINISH); + + compressed_size_out = c_stream.total_out + 16; + err = deflateEnd(&c_stream); + + template_fwrite("DATA", 4, 1, t_file); + + write_le48(compressed_size_out, &comp_size_out[0]); + template_fwrite(comp_size_out, sizeof(comp_size_out), 1, t_file); + + write_le48(size, &uncomp_size_out[0]); + template_fwrite(uncomp_size_out, sizeof(uncomp_size_out), 1, t_file); + + template_fwrite(comp_buf, c_stream.total_out, 1, t_file); + free(comp_buf); +} + +/* Compress and flush out a buffer full of template data */ +static void flush_bz2_chunk(void *buffer, off_t size) +{ + bz_stream c_stream; /* compression stream */ + unsigned char comp_size_out[6]; + unsigned char uncomp_size_out[6]; + off_t compressed_size_out = 0; + int err = 0; + unsigned char *comp_buf = NULL; + + c_stream.bzalloc = NULL; + c_stream.bzfree = NULL; + c_stream.opaque = NULL; + + err = BZ2_bzCompressInit(&c_stream, 9, 0, 0); + comp_buf = malloc(2 * size); /* Worst case */ + c_stream.next_out = comp_buf; + c_stream.avail_out = 2 * size; + c_stream.next_in = buffer; + c_stream.avail_in = size; + + err = BZ2_bzCompress(&c_stream, BZ_FINISH); + + compressed_size_out = c_stream.total_out_lo32 + 16; + err = BZ2_bzCompressEnd(&c_stream); + + template_fwrite("BZIP", 4, 1, t_file); + + write_le48(compressed_size_out, &comp_size_out[0]); + template_fwrite(comp_size_out, sizeof(comp_size_out), 1, t_file); + + write_le48(size, &uncomp_size_out[0]); + template_fwrite(uncomp_size_out, sizeof(uncomp_size_out), 1, t_file); + + template_fwrite(comp_buf, c_stream.total_out_lo32, 1, t_file); + free(comp_buf); +} + +static void flush_compressed_chunk(void *buffer, off_t size) +{ + if (jte_template_compression == JTE_TEMP_BZIP2) + flush_bz2_chunk(buffer, size); + else + flush_gzip_chunk(buffer, size); +} + +/* Append to an existing data buffer, and compress/flush it if + necessary */ +static void write_compressed_chunk(unsigned char *buffer, size_t size) +{ + static unsigned char *uncomp_buf = NULL; + static size_t uncomp_size = 0; + static size_t uncomp_buf_used = 0; + + if (!uncomp_buf) + { + if (jte_template_compression == JTE_TEMP_BZIP2) + uncomp_size = 900 * 1024; + else + uncomp_size = 1024 * 1024; + uncomp_buf = malloc(uncomp_size); + if (!uncomp_buf) + { +#ifdef USE_LIBSCHILY + comerr("failed to allocate %d bytes for template compression buffer\n", uncomp_size); +#else + fprintf(stderr, "failed to allocate %d bytes for template compression buffer\n", uncomp_size); + exit(1); +#endif + } + } + + if ((uncomp_buf_used + size) > uncomp_size) + { + flush_compressed_chunk(uncomp_buf, uncomp_buf_used); + uncomp_buf_used = 0; + } + + if (!size) /* Signal a flush before we start writing the DESC entry */ + { + flush_compressed_chunk(uncomp_buf, uncomp_buf_used); + return; + } + + if (!uncomp_buf_used) + memset(uncomp_buf, 0, uncomp_size); + + while (size > uncomp_size) + { + flush_compressed_chunk(buffer, uncomp_size); + buffer += uncomp_size; + size -= uncomp_size; + } + memcpy(&uncomp_buf[uncomp_buf_used], buffer, size); + uncomp_buf_used += size; +} + +/* Loop through the list of DESC entries that we've built up and + append them to the template file */ +static void write_template_desc_entries(off_t image_len) +{ + entry_t *entry = entry_list; + off_t desc_len = 0; + unsigned char out_len[6]; + jigdo_image_entry_t jimage; + + desc_len = 16 /* DESC + length twice */ + + (sizeof(jigdo_file_entry_t) * num_matches) + + (sizeof(jigdo_chunk_entry_t) * num_chunks) + + sizeof(jigdo_image_entry_t); + + write_le48(desc_len, &out_len[0]); + write_compressed_chunk(NULL, 0); + template_fwrite("DESC", 4, 1, t_file); + template_fwrite(out_len, sizeof(out_len), 1, t_file); + + while (entry) + { + switch (entry->entry_type) + { + case JTET_FILE_MATCH: + { + jigdo_file_entry_t jfile; + jfile.type = 6; /* Matched file */ + write_le48(entry->data.file.file_length, &jfile.fileLen[0]); + write_le64(entry->data.file.rsyncsum, &jfile.fileRsync[0]); + memcpy(jfile.fileMD5, entry->data.file.md5, sizeof(jfile.fileMD5)); + template_fwrite(&jfile, sizeof(jfile), 1, t_file); + break; + } + case JTET_NOMATCH: + { + jigdo_chunk_entry_t jchunk; + jchunk.type = 2; /* Raw data, compressed */ + write_le48(entry->data.chunk.uncompressed_length, &jchunk.skipLen[0]); + template_fwrite(&jchunk, sizeof(jchunk), 1, t_file); + break; + } + } + entry = entry->next; + } + + jimage.type = 5; + write_le48(image_len, &jimage.imageLen[0]); + checksum_copy(iso_context, CHECK_MD5, &jimage.imageMD5[0]); + write_le32(MIN_JIGDO_FILE_SIZE, &jimage.blockLen[0]); + template_fwrite(&jimage, sizeof(jimage), 1, t_file); + template_fwrite(out_len, sizeof(out_len), 1, t_file); +} + +/* Dump a buffer in jigdo-style "base64" */ +static char *base64_dump(unsigned char *buf, size_t buf_size) +{ + const char *b64_enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + int value = 0; + unsigned int i; + int bits = 0; + static char output_buffer[2048]; + char *p = output_buffer; + + memset(output_buffer, 0, sizeof(output_buffer)); + if (buf_size >= (sizeof(output_buffer) * 6/8)) + { + fprintf(stderr, "base64_dump: Buffer too small!\n"); + exit(1); + } + + for (i = 0; i < buf_size ; i++) + { + value = (value << 8) | buf[i]; + bits += 2; + p += sprintf(p, "%c", b64_enc[(value >> bits) & 63U]); + if (bits >= 6) { + bits -= 6; + p += sprintf(p, "%c", b64_enc[(value >> bits) & 63U]); + } + } + if (bits > 0) + { + value <<= 6 - bits; + p += sprintf(p, "%c", b64_enc[value & 63U]); + } + return output_buffer; +} + +/* Write the .jigdo file to match the .template we've just finished. */ +static void write_jigdo_file(void) +{ + unsigned char template_md5sum[16]; + entry_t *entry = entry_list; + struct path_mapping *map = map_list; + int i = 0; + struct checksum_info *info = NULL; + + checksum_final(template_context); + checksum_copy(template_context, CHECK_MD5, &template_md5sum[0]); + + fprintf(j_file, "# JigsawDownload\n"); + fprintf(j_file, "# See <http://atterer.org/jigdo/> for details about jigdo\n"); + fprintf(j_file, "# See <http://www.einval.com/~steve/software/CD/JTE/> for details about JTE\n\n"); + + fprintf(j_file, "[Jigdo]\n"); + fprintf(j_file, "Version=%s\n", JIGDO_TEMPLATE_VERSION); + fprintf(j_file, "Generator=%s/%d.%d\n\n", JTE_NAME, JTE_VER_MAJOR, JTE_VER_MINOR); + + fprintf(j_file, "[Image]\n"); + fprintf(j_file, "Filename=%s\n", file_base_name(outfile)); + fprintf(j_file, "Template=http://localhost/%s\n", jtemplate_out); + + fprintf(j_file, "Template-MD5Sum=%s \n", + base64_dump(&template_md5sum[0], sizeof(template_md5sum))); + + for (i = 0; i < NUM_CHECKSUMS; i++) + { + if (checksum_algo_tmpl & (1 << i)) + { + info = checksum_information(i); + fprintf(j_file, "# Template Hex %sSum %s\n", info->name, checksum_hex(template_context, i)); + } + } + fprintf(j_file, "# Template size %lld bytes\n", template_size); + + for (i = 0; i < NUM_CHECKSUMS; i++) + { + if (checksum_algo_iso & (1 << i)) + { + info = checksum_information(i); + fprintf(j_file, "# Image Hex %sSum %s\n", info->name, checksum_hex(iso_context, i)); + } + } + + fprintf(j_file, "# Image size %lld bytes\n\n", image_size); + + fprintf(j_file, "[Parts]\n"); + while (entry) + { + if (JTET_FILE_MATCH == entry->entry_type) + { + char *new_name = remap_filename(entry->data.file.filename); + fprintf(j_file, "%s=%s\n", + base64_dump(&entry->data.file.md5[0], sizeof(entry->data.file.md5)), + new_name); + free(new_name); + } + entry = entry->next; + } + + fprintf(j_file, "\n[Servers]\n"); + fflush(j_file); +} + +/* Finish and flush state; for now: + + 1. Dump the DESC blocks and the footer information in the jigdo template file + 2. Write the jigdo .jigdo file containing file pointers +*/ +void write_jt_footer(void) +{ + /* Finish calculating the image's checksum */ + checksum_final(iso_context); + + /* And calculate the image size */ + image_size = (unsigned long long)SECTOR_SIZE * last_extent_written; + + write_template_desc_entries(image_size); + + write_jigdo_file(); +} + +/* Add a raw data entry to the list of extents; no file to match */ +static void add_unmatched_entry(int uncompressed_length) +{ + entry_t *new_entry = NULL; + + /* Can we extend a previous non-match entry? */ + if (entry_last && (JTET_NOMATCH == entry_last->entry_type)) + { + entry_last->data.chunk.uncompressed_length += uncompressed_length; + return; + } + + new_entry = calloc(1, sizeof(entry_t)); + new_entry->entry_type = JTET_NOMATCH; + new_entry->next = NULL; + new_entry->data.chunk.uncompressed_length = uncompressed_length; + + /* Add to the end of the list */ + if (NULL == entry_last) + { + entry_last = new_entry; + entry_list = new_entry; + } + else + { + entry_last->next = new_entry; + entry_last = new_entry; + } + num_chunks++; +} + +/* Add a file match entry to the list of extents */ +static void add_file_entry(char *filename, off_t size, unsigned char *md5, + unsigned long long rsyncsum) +{ + entry_t *new_entry = NULL; + + new_entry = calloc(1, sizeof(entry_t)); + new_entry->entry_type = JTET_FILE_MATCH; + new_entry->next = NULL; + memcpy(new_entry->data.file.md5, md5, sizeof(new_entry->data.file.md5)); + new_entry->data.file.file_length = size; + new_entry->data.file.rsyncsum = rsyncsum; + new_entry->data.file.filename = strdup(filename); + + /* Add to the end of the list */ + if (NULL == entry_last) + { + entry_last = new_entry; + entry_list = new_entry; + } + else + { + entry_last->next = new_entry; + entry_last = new_entry; + } + num_matches++; +} + +/* Cope with an unmatched block in the .iso file: + + 1. Write a compressed data chunk in the jigdo template file + 2. Add an entry in our list of unmatched chunks for later */ +void jtwrite(buffer, size, count, submode, islast) + void *buffer; + int size; + int count; + int submode; + BOOL islast; +{ +#ifdef JTWRITE_DEBUG + if (count != 1 || (size % 2048) != 0) + error("Count: %d, size: %d\n", count, size); +#endif + + if (!jtemplate_out) + return; + + /* Update the global image checksum */ + checksum_update(iso_context, buffer, size * count); +// mk_MD5Update(&iso_context, buffer, size*count); + + /* Write a compressed version of the data to the template file, + and add a reference on the state list so we can write that + later. */ + write_compressed_chunk(buffer, size*count); + add_unmatched_entry(size*count); +} + +/* Cope with a file entry in the .iso file: + + 1. Read the file for the image's md5 checksum + 2. Add an entry in our list of files to be written into the .jigdo later +*/ +void write_jt_match_record(char *filename, char *mirror_name, int sector_size, off_t size, unsigned char md5[16]) +{ + unsigned long long tmp_size = 0; + char buf[32768]; + off_t remain = size; + FILE *infile = NULL; + int use = 0; + unsigned long long rsync64_sum = 0; + int first_block = 1; + + memset(buf, 0, sizeof(buf)); + + if ((infile = fopen(filename, "rb")) == NULL) { +#ifdef USE_LIBSCHILY + comerr("cannot open '%s'\n", filename); +#else +#ifndef HAVE_STRERROR + fprintf(stderr, "cannot open '%s': (%d)\n", + filename, errno); +#else + fprintf(stderr, "cannot open '%s': %s\n", + filename, strerror(errno)); +#endif + exit(1); +#endif + } + + while (remain > 0) + { + use = remain; + if (remain > sizeof(buf)) + use = sizeof(buf); + if (fread(buf, 1, use, infile) == 0) + { +#ifdef USE_LIBSCHILY + comerr("cannot read from '%s'\n", filename); +#else + fprintf(stderr, "cannot read from '%s'\n", filename); + exit(1); +#endif + } + if (first_block) + rsync64_sum = rsync64(buf, MIN_JIGDO_FILE_SIZE); + checksum_update(iso_context, buf, use); +// mk_MD5Update(&iso_context, buf, use); + remain -= use; + first_block = 0; + } + + fclose(infile); + + /* Update the image checksum with any necessary padding data */ + if (size % sector_size) + { + int pad_size = sector_size - (size % sector_size); + memset(buf, 0, pad_size); + checksum_update(iso_context, buf, pad_size); +// mk_MD5Update(&iso_context, buf, pad_size); + } + + add_file_entry(mirror_name, size, &md5[0], rsync64_sum); + if (size % sector_size) + { + int pad_size = sector_size - (size % sector_size); + write_compressed_chunk(buf, pad_size); + add_unmatched_entry(pad_size); + } +} diff --git a/genisoimage/jte.h b/genisoimage/jte.h new file mode 100644 index 0000000..4469452 --- /dev/null +++ b/genisoimage/jte.h @@ -0,0 +1,39 @@ +/* + * jte.c + * + * Copyright (c) 2004-2006 Steve McIntyre <steve@einval.com> + * + * Prototypes and declarations for JTE + * + * GNU GPL v2 + */ + +extern char *jtemplate_out; +extern char *jjigdo_out; +extern char *jmd5_list; +extern FILE *jthelper; +extern FILE *jtjigdo; +extern FILE *jttemplate; +extern int jte_min_size; +extern int checksum_algo_iso; +extern int checksum_algo_tmpl; + +extern void write_jt_header(FILE *template_file, FILE *jigdo_file); +extern void write_jt_footer(void); +extern void jtwrite(void *buffer, int size, int count, int submode, BOOL islast); +extern void write_jt_match_record(char *filename, char *mirror_name, int sector_size, off_t size, unsigned char md5[16]); +extern int list_file_in_jigdo(char *filename, off_t size, char **realname, unsigned char md5[16]); +extern int jte_add_exclude(char *pattern); +extern int jte_add_include(char *pattern); +extern int jte_add_mapping(char *arg); + +typedef enum _jtc_e +{ + JTE_TEMP_GZIP = 0, + JTE_TEMP_BZIP2 +} jtc_t; + +extern jtc_t jte_template_compression; + + +#define MIN_JIGDO_FILE_SIZE 1024 diff --git a/genisoimage/mac_label.c b/genisoimage/mac_label.c new file mode 100644 index 0000000..f43aafc --- /dev/null +++ b/genisoimage/mac_label.c @@ -0,0 +1,425 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)mac_label.c 1.9 04/03/05 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */ +/* + * Copyright (c) 1997, 1998, 1999, 2000 James Pearson + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * mac_label.c: generate Mactintosh partition maps and label + * + * Taken from "mkisofs 1.05 PLUS" by Andy Polyakov <appro@fy.chalmers.se> + * (see http://fy.chalmers.se/~appro/mkisofs_plus.html for details) + * + * The format of the HFS driver file: + * + * HFS CD Label Block 512 bytes + * Driver Partition Map (for 2048 byte blocks) 512 bytes + * Driver Partition Map (for 512 byte blocks) 512 bytes + * Empty 512 bytes + * Driver Partition N x 2048 bytes + * HFS Partition Boot Block 1024 bytes + * + * File of the above format can be extracted from a CD using + * apple_driver.c + * + * James Pearson 16/5/98 + */ + +/* PREP_BOOT Troy Benjegerdes 2/4/99 */ + +#include <mconfig.h> +#include "genisoimage.h" +#include "mac_label.h" +#include "apple.h" + +#ifdef PREP_BOOT +void gen_prepboot_label(unsigned char *ml); + +#endif /* PREP_BOOT */ +int gen_mac_label(defer * mac_boot); +int autostart(void); + +#ifdef PREP_BOOT +void +gen_prepboot_label(unsigned char *ml) +{ + struct directory_entry *de; + int i = 0; + int block; + int size; + MacLabel *mac_label = (MacLabel *) ml; + + if (verbose > 1) { + fprintf(stderr, "Creating %d PReP boot partition(s)\n", + use_prep_boot + use_chrp_boot); + } + mac_label->fdiskMagic[0] = fdiskMagic0; + mac_label->fdiskMagic[1] = fdiskMagic1; + + if (use_chrp_boot) { + fprintf(stderr, "CHRP boot partition 1\n"); + + mac_label->image[i].boot = 0x80; + + mac_label->image[i].CHSstart[0] = 0xff; + mac_label->image[i].CHSstart[1] = 0xff; + mac_label->image[i].CHSstart[2] = 0xff; + + mac_label->image[i].type = chrpPartType; /* 0x96 */ + + mac_label->image[i].CHSend[0] = 0xff; + mac_label->image[i].CHSend[1] = 0xff; + mac_label->image[i].CHSend[2] = 0xff; + + mac_label->image[i].startSect[0] = 0; + mac_label->image[i].startSect[1] = 0; + mac_label->image[i].startSect[2] = 0; + mac_label->image[i].startSect[3] = 0; + + size = (last_extent - session_start) * 2048 / 512; + mac_label->image[i].size[0] = size & 0xff; + mac_label->image[i].size[1] = (size >> 8) & 0xff; + mac_label->image[i].size[2] = (size >> 16) & 0xff; + mac_label->image[i].size[3] = (size >> 24) & 0xff; + + i++; + } + + for (; i < use_prep_boot + use_chrp_boot; i++) { + de = search_tree_file(root, prep_boot_image[i - use_chrp_boot]); + if (!de) { + fprintf(stderr, + "Uh oh, I cant find the boot image \"%s\"!\n", + prep_boot_image[i - use_chrp_boot]); + exit(1); + } + /* get size and block in 512-byte blocks */ + block = get_733(de->isorec.extent) * 2048 / 512; + size = get_733(de->isorec.size) / 512 + 1; + fprintf(stderr, "PReP boot partition %d is \"%s\"\n", + i + 1, prep_boot_image[i - use_chrp_boot]); + + mac_label->image[i].boot = 0x80; + + mac_label->image[i].CHSstart[0] = 0xff; + mac_label->image[i].CHSstart[1] = 0xff; + mac_label->image[i].CHSstart[2] = 0xff; + + mac_label->image[i].type = prepPartType; /* 0x41 */ + + mac_label->image[i].CHSend[0] = 0xff; + mac_label->image[i].CHSend[1] = 0xff; + mac_label->image[i].CHSend[2] = 0xff; + + /* deal with endianess */ + mac_label->image[i].startSect[0] = block & 0xff; + mac_label->image[i].startSect[1] = (block >> 8) & 0xff; + mac_label->image[i].startSect[2] = (block >> 16) & 0xff; + mac_label->image[i].startSect[3] = (block >> 24) & 0xff; + + mac_label->image[i].size[0] = size & 0xff; + mac_label->image[i].size[1] = (size >> 8) & 0xff; + mac_label->image[i].size[2] = (size >> 16) & 0xff; + mac_label->image[i].size[3] = (size >> 24) & 0xff; + } + for (; i < 4; i++) { + mac_label->image[i].CHSstart[0] = 0xff; + mac_label->image[i].CHSstart[1] = 0xff; + mac_label->image[i].CHSstart[2] = 0xff; + + mac_label->image[i].CHSend[0] = 0xff; + mac_label->image[i].CHSend[1] = 0xff; + mac_label->image[i].CHSend[2] = 0xff; + } +} + +#endif /* PREP_BOOT */ + +int +gen_mac_label(defer *mac_boot) +{ + FILE *fp; + MacLabel *mac_label; + MacPart *mac_part; + char *buffer = (char *) hce->hfs_map; + int block_size; + int have_hfs_boot = 0; + char tmp[SECTOR_SIZE]; + struct stat stat_buf; + mac_partition_table mpm[2]; + int mpc = 0; + int i; + + /* If we have a boot file, then open and check it */ + if (mac_boot->name) { + if (stat(mac_boot->name, &stat_buf) < 0) { + sprintf(hce->error, "unable to stat HFS boot file %s", + mac_boot->name); + return (-1); + } + if ((fp = fopen(mac_boot->name, "rb")) == NULL) { + sprintf(hce->error, "unable to open HFS boot file %s", + mac_boot->name); + return (-1); + } + if (fread(tmp, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) { + sprintf(hce->error, "unable to read HFS boot file %s", + mac_boot->name); + return (-1); + } + /* check we have a bootable partition */ + mac_part = (MacPart *) (tmp + HFS_BLOCKSZ); + + if (!(IS_MAC_PART(mac_part) && + strncmp((char *) mac_part->pmPartType, pmPartType_2, 12) == 0)) { + sprintf(hce->error, "%s is not a HFS boot file", + mac_boot->name); + return (-1); + } + /* check we have a boot block as well - last 2 blocks of file */ + + if (fseek(fp, (off_t)-2 * HFS_BLOCKSZ, SEEK_END) != 0) { + sprintf(hce->error, "unable to seek HFS boot file %s", + mac_boot->name); + return (-1); + } + /* overwrite (empty) boot block for our HFS volume */ + if (fread(hce->hfs_hdr, 2, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ) { + sprintf(hce->error, "unable to read HFS boot block %s", + mac_boot->name); + return (-1); + } + fclose(fp); + + /* check boot block is valid */ + if (d_getw((unsigned char *) hce->hfs_hdr) != HFS_BB_SIGWORD) { + sprintf(hce->error, + "%s does not contain a valid boot block", + mac_boot->name); + return (-1); + } + /* + * collect info about boot file for later user + * - skip over the bootfile header + */ + mac_boot->size = stat_buf.st_size - SECTOR_SIZE - 2*HFS_BLOCKSZ; + mac_boot->off = SECTOR_SIZE; + mac_boot->pad = 0; + + /* + * get size in SECTOR_SIZE blocks + * - shouldn't need to round up + */ + mpm[mpc].size = ISO_BLOCKS(mac_boot->size); + + mpm[mpc].ntype = PM2; + mpm[mpc].type = (char *) mac_part->pmPartType; + mpm[mpc].start = mac_boot->extent = last_extent; + mpm[mpc].name = 0; + + /* flag that we have a boot file */ + have_hfs_boot++; + + /* add boot file size to the total size */ + last_extent += mpm[mpc].size; + hfs_extra += mpm[mpc].size; + + mpc++; + } + /* set info about our hybrid volume */ + mpm[mpc].ntype = PM4; + mpm[mpc].type = pmPartType_4; + mpm[mpc].start = hce->hfs_map_size / HFS_BLK_CONV; + mpm[mpc].size = last_extent - mpm[mpc].start - + ISO_BLOCKS(mac_boot->size); + mpm[mpc].name = volume_id; + + mpc++; + + if (verbose > 1) + fprintf(stderr, "Creating HFS Label %s %s\n", mac_boot->name ? + "with boot file" : "", + mac_boot->name ? mac_boot->name : ""); + + /* for a bootable CD, block size is SECTOR_SIZE */ + block_size = have_hfs_boot ? SECTOR_SIZE : HFS_BLOCKSZ; + + /* create the CD label */ + mac_label = (MacLabel *) buffer; + mac_label->sbSig[0] = 'E'; + mac_label->sbSig[1] = 'R'; + set_722((char *) mac_label->sbBlkSize, block_size); + set_732((char *) mac_label->sbBlkCount, + last_extent * (SECTOR_SIZE / block_size)); + set_722((char *) mac_label->sbDevType, 1); + set_722((char *) mac_label->sbDevId, 1); + + /* create the partition map entry */ + mac_part = (MacPart *) (buffer + block_size); + mac_part->pmSig[0] = 'P'; + mac_part->pmSig[1] = 'M'; + set_732((char *) mac_part->pmMapBlkCnt, mpc + 1); + set_732((char *) mac_part->pmPyPartStart, 1); + set_732((char *) mac_part->pmPartBlkCnt, mpc + 1); + strncpy((char *) mac_part->pmPartName, "Apple", + sizeof (mac_part->pmPartName)); + strncpy((char *) mac_part->pmPartType, "Apple_partition_map", + sizeof (mac_part->pmPartType)); + set_732((char *) mac_part->pmLgDataStart, 0); + set_732((char *) mac_part->pmDataCnt, mpc + 1); + set_732((char *) mac_part->pmPartStatus, PM_STAT_DEFAULT); + + /* create partition map entries for our partitions */ + for (i = 0; i < mpc; i++) { + mac_part = (MacPart *) (buffer + (i + 2) * block_size); + if (mpm[i].ntype == PM2) { + /* get driver label and patch it */ + memcpy((char *) mac_label, tmp, HFS_BLOCKSZ); + set_732((char *) mac_label->sbBlkCount, + last_extent * (SECTOR_SIZE / block_size)); + set_732((char *) mac_label->ddBlock, + (mpm[i].start) * (SECTOR_SIZE / block_size)); + memcpy((char *) mac_part, tmp + HFS_BLOCKSZ, + HFS_BLOCKSZ); + set_732((char *) mac_part->pmMapBlkCnt, mpc + 1); + set_732((char *) mac_part->pmPyPartStart, + (mpm[i].start) * (SECTOR_SIZE / block_size)); + } else { + mac_part->pmSig[0] = 'P'; + mac_part->pmSig[1] = 'M'; + set_732((char *) mac_part->pmMapBlkCnt, mpc + 1); + set_732((char *) mac_part->pmPyPartStart, + mpm[i].start * (SECTOR_SIZE / HFS_BLOCKSZ)); + set_732((char *) mac_part->pmPartBlkCnt, + mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ)); + strncpy((char *) mac_part->pmPartName, mpm[i].name, + sizeof (mac_part->pmPartName)); + strncpy((char *) mac_part->pmPartType, mpm[i].type, + sizeof (mac_part->pmPartType)); + set_732((char *) mac_part->pmLgDataStart, 0); + set_732((char *) mac_part->pmDataCnt, + mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ)); + set_732((char *) mac_part->pmPartStatus, + PM_STAT_DEFAULT); + } + } + + if (have_hfs_boot) { /* generate 512 partition table as well */ + mac_part = (MacPart *) (buffer + HFS_BLOCKSZ); + if (mpc < 3) { /* don't have to interleave with 2048 table */ + mac_part->pmSig[0] = 'P'; + mac_part->pmSig[1] = 'M'; + set_732((char *) mac_part->pmMapBlkCnt, mpc + 1); + set_732((char *) mac_part->pmPyPartStart, 1); + set_732((char *) mac_part->pmPartBlkCnt, mpc + 1); + strncpy((char *) mac_part->pmPartName, "Apple", + sizeof (mac_part->pmPartName)); + strncpy((char *) mac_part->pmPartType, + "Apple_partition_map", + sizeof (mac_part->pmPartType)); + set_732((char *) mac_part->pmLgDataStart, 0); + set_732((char *) mac_part->pmDataCnt, mpc + 1); + set_732((char *) mac_part->pmPartStatus, + PM_STAT_DEFAULT); + mac_part++; /* +HFS_BLOCKSZ */ + } + for (i = 0; i < mpc; i++, mac_part++) { + if (mac_part == (MacPart *) (buffer + SECTOR_SIZE)) + mac_part++; /* jump over 2048 partition */ + /* entry */ + if (mpm[i].ntype == PM2) { + memcpy((char *) mac_part, tmp + HFS_BLOCKSZ * 2, + HFS_BLOCKSZ); + if (!IS_MAC_PART(mac_part)) { + mac_part--; + continue; + } + set_732((char *) mac_part->pmMapBlkCnt, mpc+1); + set_732((char *) mac_part->pmPyPartStart, + mpm[i].start * (SECTOR_SIZE / HFS_BLOCKSZ)); + } else { + mac_part->pmSig[0] = 'P'; + mac_part->pmSig[1] = 'M'; + set_732((char *) mac_part->pmMapBlkCnt, mpc+1); + set_732((char *) mac_part->pmPyPartStart, + mpm[i].start * (SECTOR_SIZE / HFS_BLOCKSZ)); + set_732((char *) mac_part->pmPartBlkCnt, + mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ)); + strncpy((char *) mac_part->pmPartName, + mpm[i].name, sizeof (mac_part->pmPartName)); + strncpy((char *) mac_part->pmPartType, + mpm[i].type, sizeof (mac_part->pmPartType)); + set_732((char *) mac_part->pmLgDataStart, 0); + set_732((char *) mac_part->pmDataCnt, + mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ)); + set_732((char *) mac_part->pmPartStatus, + PM_STAT_DEFAULT); + } + } + } + return (0); +} + +/* + * autostart: make the HFS CD use the QuickTime 2.0 Autostart feature. + * + * based on information from Eric Eisenhart <eric@sonic.net> and + * http://developer.apple.com/qa/qtpc/qtpc12.html and + * http://developer.apple.com/dev/techsupport/develop/issue26/macqa.html + * + * The name of the AutoStart file is stored in the area allocated for + * the Clipboard name. This area begins 106 bytes into the sector of + * block 0, with the first four bytes at that offset containing the + * hex value 0x006A7068. This value indicates that an AutoStart + * filename follows. After this 4-byte tag, 12 bytes remain, starting + * at offset 110. In these 12 bytes, the name of the AutoStart file is + * stored as a Pascal string, giving you up to 11 characters to identify + * the file. The file must reside in the root directory of the HFS + * volume or partition. + */ + +int +autostart() +{ + int len; + int i; + + if ((len = strlen(autoname)) > 11) + return (-1); + + hce->hfs_hdr[106] = 0x00; + hce->hfs_hdr[107] = 0x6A; + hce->hfs_hdr[108] = 0x70; + hce->hfs_hdr[109] = 0x68; + hce->hfs_hdr[110] = len; + + for (i = 0; i < len; i++) + hce->hfs_hdr[111 + i] = autoname[i]; + + return (0); +} diff --git a/genisoimage/mac_label.h b/genisoimage/mac_label.h new file mode 100644 index 0000000..ada860f --- /dev/null +++ b/genisoimage/mac_label.h @@ -0,0 +1,169 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)mac_label.h 1.3 04/03/01 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */ +/* + * Copyright (c) 1997, 1998, 1999, 2000 James Pearson + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * mac_label.h: defines Macintosh partition maps and label + * + * Taken from "genisoimage 1.05 PLUS" by Andy Polyakov <appro@fy.chalmers.se> + * (see http://fy.chalmers.se/~appro/genisoimage_plus.html for details) + * + * Much of this is already defined in the libhfs code, but to keep + * things simple we stick with these. + */ + +#ifndef _MAC_LABEL_H +#define _MAC_LABEL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PREP_BOOT +struct fdiskPartition { +#define prepPartType 0x41 +#define chrpPartType 0x96 + unsigned char boot; /* bootable flag; not used */ + unsigned char CHSstart[3]; /* start CHS; not used */ + unsigned char type; /* Partition type, = 0x41 (PReP bootable) */ + unsigned char CHSend[3]; /* end CHS; not used */ + unsigned char startSect[4]; /* start sector (really start of boot image on CD */ + unsigned char size[4]; /* size of partition (or boot image ;) ) */ +}; +typedef struct fdiskPartition fdiskPartition; +#endif + +/* Driver Descriptor Map */ +#define sbSigMagic "ER" +struct MacLabel { + unsigned char sbSig[2]; /* unique value for SCSI block 0 */ + unsigned char sbBlkSize[2]; /* block size of device */ + unsigned char sbBlkCount[4]; /* number of blocks on device */ + unsigned char sbDevType[2]; /* device type */ + unsigned char sbDevId[2]; /* device id */ + unsigned char sbData[4]; /* not used */ + unsigned char sbDrvrCount[2]; /* driver descriptor count */ + unsigned char ddBlock[4]; /* 1st driver's starting block */ + unsigned char ddSize[2]; /* size of 1st driver (512-byte blks) */ + unsigned char ddType[2]; /* system type (1 for Mac+) */ +#ifndef PREP_BOOT + unsigned char ddPad[486]; /* ARRAY[0..242] OF INTEGER; not used */ +#else +#define fdiskMagic0 0x55 +#define fdiskMagic1 0xAA + unsigned char pad1[420]; /* not used */ + fdiskPartition image[4]; /* heh heh heh, we can have up to 4 */ + /* different boot images */ + unsigned char fdiskMagic[2]; /* PReP uses fdisk partition map */ +#endif /* PREP_BOOT */ +}; +typedef struct MacLabel MacLabel; + +#define IS_MAC_LABEL(d) (((MacLabel*)(d))->sbSig[0] == 'E' && \ + ((MacLabel*)(d))->sbSig[1] == 'R') + +/* Partition Map Entry */ +#define pmSigMagic "PM" + +#define pmPartType_1 "Apple_partition_map" +#define pmPartName_11 "Apple" + +#define pmPartType_2 "Apple_Driver" +#define pmPartType_21 "Apple_Driver43" + +#define pmPartType_3 "Apple_UNIX_SVR2" +#define pmPartName_31 "A/UX Root" +#define pmPartName_32 "A/UX Usr" +#define pmPartName_33 "Random A/UX fs" +#define pmPartName_34 "Swap" + +#define pmPartType_4 "Apple_HFS" +#define pmPartName_41 "MacOS" + +#define pmPartType_5 "Apple_Free" +#define pmPartName_51 "Extra" + +#define PM2 2 +#define PM4 4 + +struct MacPart { + unsigned char pmSig[2]; /* unique value for map entry blk */ + unsigned char pmSigPad[2]; /* currently unused */ + unsigned char pmMapBlkCnt[4]; /* # of blks in partition map */ + unsigned char pmPyPartStart[4]; /* physical start blk of partition */ + unsigned char pmPartBlkCnt[4]; /* # of blks in this partition */ + unsigned char pmPartName[32]; /* ASCII partition name */ + unsigned char pmPartType[32]; /* ASCII partition type */ + unsigned char pmLgDataStart[4]; /* log. # of partition's 1st data blk */ + unsigned char pmDataCnt[4]; /* # of blks in partition's data area */ + unsigned char pmPartStatus[4]; /* bit field for partition status */ + unsigned char pmLgBootStart[4]; /* log. blk of partition's boot code */ + unsigned char pmBootSize[4]; /* number of bytes in boot code */ + unsigned char pmBootAddr[4]; /* memory load address of boot code */ + unsigned char pmBootAddr2[4]; /* currently unused */ + unsigned char pmBootEntry[4]; /* entry point of boot code */ + unsigned char pmBootEntry2[4]; /* currently unused */ + unsigned char pmBootCksum[4]; /* checksum of boot code */ + unsigned char pmProcessor[16]; /* ASCII for the processor type */ + unsigned char pmPad[376]; /* ARRAY[0..187] OF INTEGER; not used */ +}; +typedef struct MacPart MacPart; + +#define IS_MAC_PART(d) (((MacPart*)(d))->pmSig[0] == 'P' && \ + ((MacPart*)(d))->pmSig[1] == 'M') + +#define PM_STAT_VALID 0x01 /* Set if a valid partition map entry */ +#define PM_STAT_ALLOC 0x02 /* Set if partition is already allocated; clear if available */ +#define PM_STAT_INUSE 0x04 /* Set if partition is in use; may be cleared after a system reset */ +#define PM_STAT_BOOTABLE 0x08 /* Set if partition contains valid boot information */ +#define PM_STAT_READABLE 0x10 /* Set if partition allows reading */ +#define PM_STAT_WRITABLE 0x20 /* Set if partition allows writing */ +#define PM_STAT_BOOT_PIC 0x40 /* Set if boot code is position-independent */ +#define PM_STAT_UNUSED 0x80 /* Unused */ +#define PM_STAT_DEFAULT PM_STAT_VALID|PM_STAT_ALLOC|PM_STAT_READABLE|PM_STAT_WRITABLE + +typedef struct { + char *name; /* Partition name */ + char *type; /* Partition type */ + int ntype; /* Partition type (numeric) */ + int start; /* start extent (SECTOR_SIZE blocks) */ + int size; /* extents (SECTOR_SIZE blocks) */ +} mac_partition_table; + +/* from libhfs */ +#define HFS_BB_SIGWORD 0x4c4b + +typedef struct deferred_write defer; + +#ifdef __cplusplus +} +#endif + +#endif /* _MAC_LABEL_H */ diff --git a/genisoimage/mactypes.h b/genisoimage/mactypes.h new file mode 100644 index 0000000..01e1085 --- /dev/null +++ b/genisoimage/mactypes.h @@ -0,0 +1,65 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)mactypes.h 1.3 04/03/01 joerg */ + +#ifndef _MACTYPES_H +#define _MACTYPES_H + +/* + * Various types of HFS files stored on Unix systems + */ +#define TYPE_NONE 0 /* Unknown file type (ordinary Unix file) */ +#define TYPE_CAP 1 /* AUFS CAP */ +#define TYPE_NETA 2 /* Netatalk */ +#define TYPE_DBL 3 /* AppleDouble */ +#define TYPE_ESH 4 /* Helios EtherShare */ +#define TYPE_FEU 5 /* PC Exchange (Upper case) */ +#define TYPE_FEL 6 /* PC Exchange (Lower case) */ +#define TYPE_SGI 7 /* SGI */ +#define TYPE_MBIN 8 /* MacBinary */ +#define TYPE_SGL 9 /* AppleSingle */ +#define TYPE_DAVE 10 /* DAVE (AppleDouble type) */ +#define TYPE_SFM 11 /* NTFS Services for Macintosh */ +#define TYPE_XDBL 12 /* MacOS X AppleDouble */ +#define TYPE_XHFS 13 /* MacOS X HFS */ + +/* + * above encoded in a bit map + */ +#define DO_NONE (1 << TYPE_NONE) +#define DO_CAP (1 << TYPE_CAP) +#define DO_NETA (1 << TYPE_NETA) +#define DO_DBL (1 << TYPE_DBL) +#define DO_ESH (1 << TYPE_ESH) +#define DO_FEU (1 << TYPE_FEU) +#define DO_FEL (1 << TYPE_FEL) +#define DO_SGI (1 << TYPE_SGI) +#define DO_MBIN (1 << TYPE_MBIN) +#define DO_SGL (1 << TYPE_SGL) +#define DO_DAVE (1 << TYPE_DAVE) +#define DO_SFM (1 << TYPE_SFM) +#define DO_XDBL (1 << TYPE_XDBL) +#define DO_XHFS (1 << TYPE_XHFS) + +/* + * flags describing how the data/rsrc/info files are stored + * in the whole file name + */ +#define INSERT 0x0 /* rsrc/info is inserted in name (default) */ +#define PROBE 0x1 /* need to probe file for type */ +#define NOPEND 0x2 /* info data in one file for all files */ +#define APPEND 0x4 /* rsrc/info appended to file name */ +#define NORSRC 0x8 /* rsrc for file may not exist */ +#define NOINFO 0x10 /* info file dosen't exist */ + +#endif /* _MACTYPES_H */ diff --git a/genisoimage/magic b/genisoimage/magic new file mode 100644 index 0000000..387727c --- /dev/null +++ b/genisoimage/magic @@ -0,0 +1,81 @@ +# +# Example magic file for mkhybrid +# +# The "message" for the offset MUST be 4 characters for the CREATOR +# and 4 characters for the TYPE - white space is optional between them. +# Any other characters on this line are ignored. Continuation lines (starting +# with '>') are also ignored i.e. only the initial offset lines are used. +# +# The continuation lines are given here, but they do not need to exist. + +# +# James Pearson 20/5/98 + +# off type test message + +# GIF +0 string GIF8 8BIM GIFf +>4 string 7a \b, version 8%s, +>4 string 9a \b, version 8%s, +>6 leshort >0 %hd x +>8 leshort >0 %hd, +#>10 byte &0x80 color mapped, +#>10 byte&0x07 =0x00 2 colors +#>10 byte&0x07 =0x01 4 colors +#>10 byte&0x07 =0x02 8 colors +#>10 byte&0x07 =0x03 16 colors +#>10 byte&0x07 =0x04 32 colors +#>10 byte&0x07 =0x05 64 colors +#>10 byte&0x07 =0x06 128 colors +#>10 byte&0x07 =0x07 256 colors + +# JPEG images +# +0 ubeshort 0xffd8 8BIM JPEG image data + +# StuffIt +# +0 string SIT! SIT!SIT! + +# standard unix compress +0 string \037\235 LZIV ZIVU +>2 byte&0x80 >0 block compressed +>2 byte&0x1f x %d bits + +# gzip (GNU zip, not to be confused with Info-ZIP or PKWARE zip archiver) +0 string \037\213 GNUz ZIVU gzip compressed data +>2 byte <8 \b, reserved method, +>2 byte 8 \b, deflated, +>3 byte &0x01 ASCII, +>3 byte &0x02 continuation, +>3 byte &0x04 extra field, +>3 byte &0x08 original filename, +>3 byte &0x10 comment, +>3 byte &0x20 encrypted, +>4 ledate x last modified: %s, +>8 byte 2 max compression, +>8 byte 4 max speed, +>9 byte =0x00 os: MS-DOS +>9 byte =0x01 os: Amiga +>9 byte =0x02 os: VMS +>9 byte =0x03 os: Unix +>9 byte =0x05 os: Atari +>9 byte =0x06 os: OS/2 +>9 byte =0x07 os: MacOS +>9 byte =0x0A os: Tops/20 +>9 byte =0x0B os: Win/32 + +# Postscript +0 string %! ASPSTEXT +>2 string PS-Adobe- conforming +>>11 string >\0 at level %.3s +>>>15 string EPS - type %s +>>>15 string Query - type %s +>>>15 string ExitServer - type %s +# Some PCs have the annoying habit of adding a ^D as a document separator +0 string \004%! ASPS TEXT PostScript document text +>3 string PS-Adobe- conforming +>>12 string >\0 at level %.3s +>>>16 string EPS - type %s +>>>16 string Query - type %s +>>>16 string ExitServer - type %s diff --git a/genisoimage/mapping b/genisoimage/mapping new file mode 100644 index 0000000..c108a44 --- /dev/null +++ b/genisoimage/mapping @@ -0,0 +1,8 @@ +# Example filename mapping file +# +# EXTN XLate CREATOR TYPE Comment +.tif Raw '8BIM' 'TIFF' "Photoshop TIFF image" +.hqx Ascii 'BnHq' 'TEXT' "BinHex file" +.doc Raw 'MSWD' 'WDBN' "Word file" +.mov Raw 'TVOD' 'MooV' "QuickTime Movie" +* Ascii 'ttxt' 'TEXT' "Text file" diff --git a/genisoimage/match.c b/genisoimage/match.c new file mode 100644 index 0000000..6762e89 --- /dev/null +++ b/genisoimage/match.c @@ -0,0 +1,290 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)match.c 1.18 04/05/23 joerg */ +/* + * 27-Mar-96: Jan-Piet Mens <jpm@mens.de> + * added 'match' option (-m) to specify regular expressions NOT to be included + * in the CD image. + * + * Re-written 13-Apr-2000 James Pearson + * now uses a generic set of routines + */ + +#include <mconfig.h> +#include <stdio.h> +#include <stdxlib.h> +#include <unixstd.h> +#include <strdefs.h> +#include <standard.h> +#include <schily.h> +#include <libport.h> +#include "match.h" + +struct match { + struct match *next; + char *name; +}; + +typedef struct match match; + +static match *mats[MAX_MAT]; + +static char *mesg[MAX_MAT] = { + "excluded", + "excluded ISO-9660", + "excluded Joliet", + "hidden attribute ISO-9660", +#ifdef APPLE_HYB + "excluded HFS", +#endif /* APPLE_HYB */ +}; + +#ifdef SORTING +struct sort_match { + struct sort_match *next; + char *name; + int val; +}; + +typedef struct sort_match sort_match; + +static sort_match *s_mats; + +int +add_sort_match(char *fn, int val) +{ + sort_match *s_mat; + + s_mat = (sort_match *)malloc(sizeof (sort_match)); + if (s_mat == NULL) { +#ifdef USE_LIBSCHILY + errmsg("Can't allocate memory for sort filename\n"); +#else + fprintf(stderr, "Can't allocate memory for sort filename\n"); +#endif + return (0); + } + + if ((s_mat->name = strdup(fn)) == NULL) { +#ifdef USE_LIBSCHILY + errmsg("Can't allocate memory for sort filename\n"); +#else + fprintf(stderr, "Can't allocate memory for sort filename\n"); +#endif + return (0); + } + + /* need to reserve the minimum value for other uses */ + if (val == NOT_SORTED) + val++; + + s_mat->val = val; + s_mat->next = s_mats; + s_mats = s_mat; + + return (1); +} + +void +add_sort_list(char *file) +{ + FILE *fp; + char name[4096]; + char *p; + int val; + + if ((fp = fopen(file, "r")) == NULL) { +#ifdef USE_LIBSCHILY + comerr("Can't open sort file list %s\n", file); +#else + fprintf(stderr, "Can't open hidden/exclude file list %s\n", file); + exit(1); +#endif + } + + while (fgets(name, sizeof (name), fp) != NULL) { + /* + * look for the last space or tab character + */ + if ((p = strrchr(name, ' ')) == NULL) + p = strrchr(name, '\t'); + else if (strrchr(p, '\t') != NULL) /* Tab after space? */ + p = strrchr(p, '\t'); + + if (p == NULL) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Incorrect sort file format\n\t%s", name); +#else + fprintf(stderr, "Incorrect sort file format\n\t%s", name); +#endif + continue; + } else { + *p = '\0'; + val = atoi(++p); + } + if (!add_sort_match(name, val)) { + fclose(fp); + return; + } + } + + fclose(fp); +} + +int +sort_matches(char *fn, int val) +{ + register sort_match *s_mat; + + for (s_mat = s_mats; s_mat; s_mat = s_mat->next) { + if (fnmatch(s_mat->name, fn, FNM_FILE_NAME) != FNM_NOMATCH) { + return (s_mat->val); /* found sort value */ + } + } + return (val); /* not found - default sort value */ +} + +void +del_sort() +{ + register sort_match * s_mat, *s_mat1; + + s_mat = s_mats; + while (s_mat) { + s_mat1 = s_mat->next; + + free(s_mat->name); + free(s_mat); + + s_mat = s_mat1; + } + + s_mats = 0; +} + +#endif /* SORTING */ + + +int +gen_add_match(char *fn, int n) +{ + match *mat; + + if (n >= MAX_MAT) + return (0); + + mat = (match *)malloc(sizeof (match)); + if (mat == NULL) { +#ifdef USE_LIBSCHILY + errmsg("Can't allocate memory for %s filename\n", mesg[n]); +#else + fprintf(stderr, "Can't allocate memory for %s filename\n", mesg[n]); +#endif + return (0); + } + + if ((mat->name = strdup(fn)) == NULL) { +#ifdef USE_LIBSCHILY + errmsg("Can't allocate memory for %s filename\n", mesg[n]); +#else + fprintf(stderr, "Can't allocate memory for %s filename\n", mesg[n]); +#endif + return (0); + } + + mat->next = mats[n]; + mats[n] = mat; + + return (1); +} + +void +gen_add_list(char *file, int n) +{ + FILE *fp; + char name[4096]; + int len; + + if ((fp = fopen(file, "r")) == NULL) { +#ifdef USE_LIBSCHILY + comerr("Can't open %s file list %s\n", mesg[n], file); +#else + fprintf(stderr, "Can't open %s file list %s\n", mesg[n], file); + exit(1); +#endif + } + + while (fgets(name, sizeof (name), fp) != NULL) { + /* + * strip of '\n' + */ + len = strlen(name); + if (name[len - 1] == '\n') { + name[len - 1] = '\0'; + } + if (!gen_add_match(name, n)) { + fclose(fp); + return; + } + } + + fclose(fp); +} + +int +gen_matches(char *fn, int n) +{ + register match * mat; + + if (n >= MAX_MAT) + return (0); + + for (mat = mats[n]; mat; mat = mat->next) { + if (fnmatch(mat->name, fn, FNM_FILE_NAME) != FNM_NOMATCH) { + return (1); /* found -> excluded filename */ + } + } + return (0); /* not found -> not excluded */ +} + +int +gen_ishidden(int n) +{ + if (n >= MAX_MAT) + return (0); + + return ((int)(mats[n] != 0)); +} + +void +gen_del_match(int n) +{ + register match *mat; + register match *mat1; + + if (n >= MAX_MAT) + return; + + mat = mats[n]; + + while (mat) { + mat1 = mat->next; + + free(mat->name); + free(mat); + + mat = mat1; + } + + mats[n] = 0; +} diff --git a/genisoimage/match.h b/genisoimage/match.h new file mode 100644 index 0000000..2894af9 --- /dev/null +++ b/genisoimage/match.h @@ -0,0 +1,91 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)match.h 1.9 04/05/23 joerg */ +/* + * 27th March 1996. Added by Jan-Piet Mens for matching regular expressions + * in paths. + * + */ + +#include "fnmatch.h" + +#ifdef SORTING +#include <limits.h> +#define NOT_SORTED INT_MIN + +#ifdef MAX /* May be defined in param.h */ +#undef MAX +#endif +#define MAX(A, B) (A) > (B) ? (A) : (B) +#endif + +#define EXCLUDE 0 /* Exclude file completely */ +#define I_HIDE 1 /* ISO9660/Rock Ridge hide */ +#define J_HIDE 2 /* Joliet hide */ +#define H_HIDE 3 /* ISO9660 hidden bit set */ + +#ifdef APPLE_HYB +#define HFS_HIDE 4 /* HFS hide */ +#define MAX_MAT 5 +#else +#define MAX_MAT 4 +#endif /* APPLE_HYB */ + +extern int gen_add_match(char *fn, int n); +extern int gen_matches(char *fn, int n); +extern void gen_add_list(char *fn, int n); +extern int gen_ishidden(int n); +extern void gen_del_match(int n); + +#ifdef SORTING +extern int add_sort_match(char *fn, int val); +extern void add_sort_list(char *fn); +extern int sort_matches(char *fn, int val); +extern void del_sort(void); +#endif /* SORTING */ + +/* + * The following are for compatiblity with the separate routines - the + * main code should be changed to call the generic routines directly + */ + +/* filenames to be excluded */ +#define add_match(FN) gen_add_match((FN), EXCLUDE) +#define add_list(FN) gen_add_list((FN), EXCLUDE) +#define matches(FN) gen_matches((FN), EXCLUDE) + +/* ISO9660/Rock Ridge filenames to be hidden */ +#define i_add_match(FN) gen_add_match((FN), I_HIDE) +#define i_add_list(FN) gen_add_list((FN), I_HIDE) +#define i_matches(FN) gen_matches((FN), I_HIDE) +#define i_ishidden() gen_ishidden(I_HIDE) + +/* Joliet filenames to be hidden */ +#define j_add_match(FN) gen_add_match((FN), J_HIDE) +#define j_add_list(FN) gen_add_list((FN), J_HIDE) +#define j_matches(FN) gen_matches((FN), J_HIDE) +#define j_ishidden() gen_ishidden(J_HIDE) + +/* ISO9660 "hidden" files */ +#define h_add_match(FN) gen_add_match((FN), H_HIDE) +#define h_add_list(FN) gen_add_list((FN), H_HIDE) +#define h_matches(FN) gen_matches((FN), H_HIDE) +#define h_ishidden() gen_ishidden(H_HIDE) + +#ifdef APPLE_HYB +/* HFS filenames to be hidden */ +#define hfs_add_match(FN) gen_add_match((FN), HFS_HIDE) +#define hfs_add_list(FN) gen_add_list((FN), HFS_HIDE) +#define hfs_matches(FN) gen_matches((FN), HFS_HIDE) +#define hfs_ishidden() gen_ishidden(HFS_HIDE) +#endif /* APPLE_HYB */ diff --git a/genisoimage/md5.c b/genisoimage/md5.c new file mode 100644 index 0000000..353ae5a --- /dev/null +++ b/genisoimage/md5.c @@ -0,0 +1,401 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to + not require an integer type which is exactly 32 bits. This work + draws on the changes for the same purpose by Tatu Ylonen + <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use + that code, there is no copyright issue. I hereby disclaim + copyright in any changes I have made; this code remains in the + public domain. */ + +/* Note regarding cvs_* namespace: this avoids potential conflicts + with libraries such as some versions of Kerberos. No particular + need to worry about whether the system supplies an MD5 library, as + this file is only about 3k of object code. */ + +/* Steve McIntyre, 2004/05/31: borrowed this code from the CVS + library. s/cvs_/mk_/ across the source */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> /* for memcpy() and memset() */ +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> + +#include "md5.h" + +/* Little-endian byte-swapping routines. Note that these do not + depend on the size of datatypes such as mk_uint32, nor do they require + us to detect the endianness of the machine we are running on. It + is possible they should be macros for speed, but I would be + surprised if they were a performance bottleneck for MD5. */ + +static mk_uint32 +getu32 (const unsigned char *addr) +{ + return (((((unsigned long)addr[3] << 8) | addr[2]) << 8) + | addr[1]) << 8 | addr[0]; +} + +static void +putu32 (mk_uint32 data, unsigned char *addr) +{ + addr[0] = (unsigned char)data; + addr[1] = (unsigned char)(data >> 8); + addr[2] = (unsigned char)(data >> 16); + addr[3] = (unsigned char)(data >> 24); +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void +mk_MD5Init (struct mk_MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void +mk_MD5Update (struct mk_MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + mk_uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = (t + ((mk_uint32)len << 3)) & 0xffffffff) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if ( t ) { + unsigned char *p = ctx->in + t; + + t = 64-t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + mk_MD5Transform (ctx->buf, ctx->in); + buf += t; + len -= t; + } + + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + mk_MD5Transform (ctx->buf, ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void +mk_MD5Final (unsigned char digest[16], struct mk_MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + mk_MD5Transform (ctx->buf, ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count-8); + } + + /* Append length in bits and transform */ + putu32(ctx->bits[0], ctx->in + 56); + putu32(ctx->bits[1], ctx->in + 60); + + mk_MD5Transform (ctx->buf, ctx->in); + putu32(ctx->buf[0], digest); + putu32(ctx->buf[1], digest + 4); + putu32(ctx->buf[2], digest + 8); + putu32(ctx->buf[3], digest + 12); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void +mk_MD5Transform (mk_uint32 buf[4], const unsigned char inraw[64]) +{ + register mk_uint32 a, b, c, d; + mk_uint32 in[16]; + int i; + + for (i = 0; i < 16; ++i) + in[i] = getu32 (inraw + 4 * i); + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* Read in a hex-dumped MD5 sum and parse it */ +int mk_MD5Parse(unsigned char in[33], unsigned char out[16]) +{ + int i = 0; + + for (i = 0; i < 16; i++) + { + if (in[2*i] >= '0' && in[2*i] <= '9') + in[2*i] -= '0'; + else if (in[2*i] >= 'A' && in[2*i] <= 'F') + in[2*i] += 10 - 'A'; + else if (in[2*i] >= 'a' && in[2*i] <= 'f') + in[2*i] += 10 - 'a'; + else + return 1; + if (in[1+(2*i)] >= '0' && in[1+(2*i)] <= '9') + in[1+(2*i)] -= '0'; + else if (in[1+(2*i)] >= 'A' && in[1+(2*i)] <= 'F') + in[1+(2*i)] += 10 - 'A'; + else if (in[1+(2*i)] >= 'a' && in[1+(2*i)] <= 'f') + in[1+(2*i)] += 10 - 'a'; + else + return 1; + out[i] = in[2*i] << 4 | in[1+(2*i)]; + } + return 0; +} + +/* Calculate the MD5sum of the specified file */ +int calculate_md5sum(char *filename, unsigned long long size, unsigned char out[16]) +{ + char buffer[32768]; + int i = 0; + FILE *infile = NULL; + unsigned long long remain = 0; + int use; + struct mk_MD5Context file_context; + + /* Start MD5 work for the file */ + mk_MD5Init(&file_context); + + infile = fopen(filename, "rb"); + if (!infile) + { +#ifndef HAVE_STRERROR + 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 > sizeof(buffer) ? sizeof(buffer) : remain); + if (fread(buffer, 1, use, infile) == 0) + { + fprintf(stderr, "cannot read from '%s'\n", filename); + exit(1); + } + /* Update the checksum */ + mk_MD5Update(&file_context, (unsigned char *)buffer, use); + remain -= use; + } + fclose(infile); + mk_MD5Final(&out[0], &file_context); + + return 0; +} + + +#ifdef TEST +/* Simple test program. Can use it to manually run the tests from + RFC1321 for example. */ +#include <stdio.h> + +int +main (int argc, char *argv[]) +{ + struct mk_MD5Context context; + unsigned char checksum[16]; + int i; + int j; + + if (argc < 2) + { + fprintf (stderr, "usage: %s string-to-hash\n", argv[0]); + exit (1); + } + for (j = 1; j < argc; ++j) + { + printf ("MD5 (\"%s\") = ", argv[j]); + mk_MD5Init (&context); + mk_MD5Update (&context, argv[j], strlen (argv[j])); + mk_MD5Final (checksum, &context); + for (i = 0; i < 16; i++) + { + printf ("%02x", (unsigned int) checksum[i]); + } + printf ("\n"); + } + return 0; +} +#endif /* TEST */ diff --git a/genisoimage/md5.h b/genisoimage/md5.h new file mode 100644 index 0000000..b48c05c --- /dev/null +++ b/genisoimage/md5.h @@ -0,0 +1,41 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* See md5.c for explanation and copyright information. */ + +#ifndef MD5_H +#define MD5_H + +/* Unlike previous versions of this code, uint32 need not be exactly + 32 bits, merely 32 bits or more. Choosing a data type which is 32 + bits instead of 64 is not important; speed is considerably more + important. ANSI guarantees that "unsigned long" will be big enough, + and always using it seems to have few disadvantages. */ +typedef unsigned long mk_uint32; + +struct mk_MD5Context { + mk_uint32 buf[4]; + mk_uint32 bits[2]; + unsigned char in[64]; +}; + +void mk_MD5Init (struct mk_MD5Context *context); +void mk_MD5Update (struct mk_MD5Context *context, + unsigned char const *buf, unsigned len); +void mk_MD5Final (unsigned char digest[16], + struct mk_MD5Context *context); +void mk_MD5Transform (mk_uint32 buf[4], const unsigned char in[64]); +int mk_MD5Parse(unsigned char in[33], unsigned char out[16]); +int calculate_md5sum(char *filename, unsigned long long size, unsigned char out[16]); + + +#endif /* !MD5_H */ diff --git a/genisoimage/mkhybrid.8 b/genisoimage/mkhybrid.8 new file mode 100644 index 0000000..075bc0a --- /dev/null +++ b/genisoimage/mkhybrid.8 @@ -0,0 +1,2 @@ +.so man8/genisoimage.8 +.\" %Z%%M% %I% %E% joerg diff --git a/genisoimage/more.mapping b/genisoimage/more.mapping new file mode 100644 index 0000000..a18daa3 --- /dev/null +++ b/genisoimage/more.mapping @@ -0,0 +1,282 @@ +# +# Mapping file converted from Internet Config +# by Bob Nestor <rnestor@metronet.com> +# +# EXTN Xlate Creator Type Application - description (mime type) +# +.1st Ascii 'ttxt' 'TEXT' "SimpleText - Text Readme (application/text)" +.669 Raw 'SNPL' '6669' "PlayerPro - 669 MOD Music" +.8med Raw 'SCPL' 'STrk' "SoundApp - Amiga OctaMed music" +.8svx Raw 'SCPL' '8SVX' "SoundApp - Amiga 8-bit sound" +.a Ascii 'MPS ' 'TEXT' "MPW Shell - Assembly Source" +.aif Raw 'SCPL' 'AIFF' "SoundApp - AIFF Sound (audio/x-aiff)" +.aifc Raw 'SCPL' 'AIFC' "SoundApp - AIFF Sound Compressed (audio/x-aiff)" +.aiff Raw 'SCPL' 'AIFF' "SoundApp - AIFF Sound (audio/x-aiff)" +.al Raw 'SCPL' 'ALAW' "SoundApp - ALAW Sound" +.ani Raw 'GKON' 'ANIi' "GraphicConverter - Animated NeoChrome" +.apd Ascii 'ALD3' 'TEXT' "Aldus PageMaker - Aldus Printer Description" +.arc Raw 'arc*' 'mArc' "ArcMac - PC ARChive" +.arj Raw 'DArj' 'BINA' "DeArj - ARJ Archive" +.arr Raw 'GKON' 'ARR ' "GraphicConverter - Amber ARR image" +.art Raw 'GKON' 'ART ' "GraphicConverter - First Publisher" +.asc Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/plain)" +.ascii Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/plain)" +.asm Ascii 'MPS ' 'TEXT' "MPW Shell - Assembly Source" +.au Raw 'SCPL' 'ULAW' "SoundApp - Sun Sound (audio/basic)" +.avi Raw 'AVIC' 'VfW ' "AVI to QT Utility - AVI Movie (video/avi)" +.bar Raw 'S691' 'BARF' "SunTar - Unix BAR Archive" +.bas Ascii 'TBB6' 'TEXT' "TexEdit - BASIC Source" +.bat Ascii 'ttxt' 'TEXT' "SimpleText - MS-DOS Batch File" +.bga Raw 'JVWR' 'BMPp' "JPEGView - OS/2 Bitmap" +.bib Ascii '*TEX' 'TEXT' "Textures - BibTex Bibliography" +.bin Raw 'MB2P' 'BINA' "MacBinary II+ - MacBinary (application/macbinary)" +.binary Raw 'hDmp' 'BINA' "HexEdit - Untyped Binary Data (application/octet-stream)" +.bmp Raw 'JVWR' 'BMPp' "JPEGView - Windows Bitmap" +.boo Ascii 'TBB6' 'TEXT' "TexEdit - BOO encoded" +.bst Ascii '*TEX' 'TEXT' "Textures - BibTex Style" +.bw Raw 'GKON' 'SGI ' "GraphicConverter - SGI Image" +.c Ascii 'CWIE' 'TEXT' "CodeWarrior - C Source" +.cgm Raw 'GKON' 'CGMm' "GraphicConverter - Computer Graphics Meta" +.class Raw 'CWIE' 'Clss' "CodeWarrior - Java Class File" +.clp Raw 'GKON' 'CLPp' "GraphicConverter - Windows Clipboard" +.cmd Ascii 'ttxt' 'TEXT' "SimpleText - OS/2 Batch File" +.com Raw 'SWIN' 'PCFA' "SoftWindows - MS-DOS Executable" +.cp Ascii 'CWIE' 'TEXT' "CodeWarrior - C++ Source" +.cpp Ascii 'CWIE' 'TEXT' "CodeWarrior - C++ Source" +.cpt Raw 'CPCT' 'PACT' "Compact Pro - Compact Pro Archive" +.csv Ascii 'XCEL' 'TEXT' "Excel - Comma Separated Vars" +.ct Raw 'GKON' '..CT' "GraphicConverter - Scitex-CT" +.cut Raw 'GKON' 'Halo' "GraphicConverter - Dr Halo Image" +.cvs Raw 'DAD2' 'drw2' "Canvas - Canvas Drawing" +.dbf Raw 'FOX+' 'COMP' "FoxBase+ - DBase Document" +.dcx Raw 'GKON' 'DCXx' "GraphicConverter - Some PCX Images" +.dif Ascii 'XCEL' 'TEXT' "Excel - Data Interchange Format" +.diz Ascii 'TBB6' 'TEXT' "TexEdit - BBS Descriptive Text" +.dl Raw 'AnVw' 'DL ' "MacAnim Viewer - DL Animation" +.dll Raw 'SWIN' 'PCFL' "SoftWindows - Windows DLL" +.doc Raw 'MSWD' 'WDBN' "Microsoft Word - Word Document (application/msword)" +.dot Raw 'MSWD' 'sDBN' "Microsoft Word - Word for Windows Template" +.dvi Raw 'OTEX' 'ODVI' "OzTeX - TeX DVI Document (application/x-dvi)" +.dxf Ascii 'SWVL' 'TEXT' "Swivel Pro - AutoCAD 3D Data" +.eps Raw 'vgrd' 'EPSF' "LaserWriter 8 - Postscript (application/postscript)" +.epsf Raw 'vgrd' 'EPSF' "LaserWriter 8 - Postscript (application/postscript)" +.etx Ascii 'ezVu' 'TEXT' "Easy View - SEText (text/x-setext)" +.evy Raw 'ENVY' 'EVYD' "Envoy - Envoy Document" +.exe Raw 'SWIN' 'PCFA' "SoftWindows - MS-DOS Executable" +.faq Ascii 'TBB6' 'TEXT' "TexEdit - ASCII Text (text/x-usenet-faq)" +.fit Raw 'GKON' 'FITS' "GraphicConverter - Flexible Image Transport (image/x-fits)" +.flc Raw 'AnVw' 'FLI ' "MacAnim Viewer - FLIC Animation" +.fli Raw 'AnVw' 'FLI ' "MacAnim Viewer - FLI Animation" +.fm Raw 'FMPR' 'FMPR' "FileMaker Pro - FileMaker Pro Database" +.for Ascii 'MPS ' 'TEXT' "MPW Shell - Fortran Source" +.fts Raw 'GKON' 'FITS' "GraphicConverter - Flexible Image Transport" +.gem Raw 'GKON' 'GEM-' "GraphicConverter - GEM Metafile" +.gif Raw 'JVWR' 'GIFf' "JPEGView - GIF Picture (image/gif)" +.gl Raw 'AnVw' 'GL ' "MacAnim Viewer - GL Animation" +.grp Raw 'GKON' 'GRPp' "GraphicConverter - GRP Image" +.gz Raw 'Gzip' 'Gzip' "MacGzip - Gnu ZIP Archive (application/x-gzip)" +.h Ascii 'CWIE' 'TEXT' "CodeWarrior - C Include File" +.hcom Raw 'SCPL' 'FSSD' "SoundApp - SoundEdit Sound ex SOX" +.hp Ascii 'CWIE' 'TEXT' "CodeWarrior - C Include File" +.hpgl Raw 'GKON' 'HPGL' "GraphicConverter - HP GL/2" +.hpp Ascii 'CWIE' 'TEXT' "CodeWarrior - C Include File" +.hqx Ascii 'TBB6' 'TEXT' "TexEdit - BinHex (application/mac-binhex40)" +.htm Ascii 'Um6' 'TEXT' "HTML Pro - HyperText (text/html)" +.html Ascii 'Um6' 'TEXT' "HTML Pro - HyperText (text/html)" +.i3 Ascii 'TBB6' 'TEXT' "TexEdit - Modula 3 Interface" +.ic1 Raw 'GKON' 'IMAG' "GraphicConverter - Atari Image" +.ic2 Raw 'GKON' 'IMAG' "GraphicConverter - Atari Image" +.ic3 Raw 'GKON' 'IMAG' "GraphicConverter - Atari Image" +.icn Raw 'GKON' 'ICO ' "GraphicConverter - Windows Icon" +.ico Raw 'GKON' 'ICO ' "GraphicConverter - Windows Icon" +.ief Raw 'GKON' 'IEF ' "GraphicConverter - IEF image (image/ief)" +.iff Raw 'GKON' 'ILBM' "GraphicConverter - Amiga IFF Image" +.ilbm Raw 'GKON' 'ILBM' "GraphicConverter - Amiga ILBM Image" +.image Raw 'dCpy' 'dImg' "DiskCopy - Apple DiskCopy Image" +.img Raw 'GKON' 'IMGg' "GraphicConverter - GEM bit image/XIMG" +.img Raw 'GKON' 'KONT' "GraphicConverter - KONTRON Image" +.ini Ascii 'ttxt' 'TEXT' "SimpleText - Windows INI File" +.java Ascii 'CWIE' 'TEXT' "CodeWarrior - Java Source File" +.jfif Raw 'JVWR' 'JFIF' "JPEGView - JFIF Image" +.jpe Raw 'JVWR' 'JPEG' "JPEGView - JPEG Picture (image/jpeg)" +.jpeg Raw 'JVWR' 'JPEG' "JPEGView - JPEG Picture (image/jpeg)" +.jpg Raw 'JVWR' 'JPEG' "JPEGView - JPEG Picture (image/jpeg)" +.latex Ascii 'OTEX' 'TEXT' "OzTex - Latex (application/x-latex)" +.lbm Raw 'GKON' 'ILBM' "GraphicConverter - Amiga IFF Image" +.lha Raw 'LARC' 'LHA ' "MacLHA - LHArc Archive" +.lzh Raw 'LARC' 'LHA ' "MacLHA - LHArc Archive" +.m1a Raw 'KAU1' 'MPEG' "MPEG/CD - MPEG-1 audiostream (audio/x-mpeg)" +.m1s Raw 'MPsp' 'MPEG' "MPEGSplitter - MPEG-1 systemstream" +.m1v Raw 'mMPG' 'M1V ' "Sparkle - MPEG-1 IPB videostream (video/mpeg)" +.m2 Ascii 'TBB6' 'TEXT' "TexEdit - Modula 2 Source" +.m2v Raw 'MPG2' 'MPG2' "MPEG2decoder - MPEG-2 IPB videostream" +.m3 Ascii 'TBB6' 'TEXT' "TexEdit - Modula 3 Source" +.mac Raw 'ttxt' 'PICT' "SimpleText - PICT Picture (image/x-pict)" +.mak Ascii 'TBB6' 'TEXT' "TexEdit - Makefile" +.mcw Raw 'MSWD' 'WDBN' "Microsoft Word - Mac Word Document" +.me Ascii 'ttxt' 'TEXT' "SimpleText - Text Readme" +.med Raw 'SCPL' 'STrk' "SoundApp - Amiga MED Sound" +.mf Ascii '*MF*' 'TEXT' "Metafont - Metafont" +.mid Raw 'ttxt' 'Midi' "SimpleText - MIDI Music" +.midi Raw 'ttxt' 'Midi' "SimpleText - MIDI Music" +.mif Ascii 'Fram' 'TEXT' "FrameMaker - FrameMaker MIF (application/x-mif)" +.mif Ascii 'Fram' 'TEXT' "FrameMaker - FrameMaker MIF (application/x-framemaker)" +.mime Ascii 'mPAK' 'TEXT' "Mpack - MIME Message (message/rfc822)" +.ml Ascii 'TBB6' 'TEXT' "TexEdit - ML Source" +.mod Raw 'SCPL' 'STrk' "SoundApp - MOD Music" +.mol Ascii 'RSML' 'TEXT' "RasMac - MDL Molfile" +.moov Raw 'ttxt' 'MooV' "SimpleText - QuickTime Movie (video/quicktime)" +.mov Raw 'ttxt' 'MooV' "SimpleText - QuickTime Movie (video/quicktime)" +.mp2 Raw 'KAU1' 'MPEG' "MPEG/CD - MPEG-1 audiostream (audio/x-mpeg)" +.mpa Raw 'KAU1' 'MPEG' "MPEG/CD - MPEG-1 audiostream (audio/x-mpeg)" +.mpe Raw 'mMPG' 'MPEG' "Sparkle - MPEG Movie of some sort (video/mpeg)" +.mpeg Raw 'mMPG' 'MPEG' "Sparkle - MPEG Movie of some sort (video/mpeg)" +.mpg Raw 'mMPG' 'MPEG' "Sparkle - MPEG Movie of some sort (video/mpeg)" +.msp Raw 'GKON' 'MSPp' "GraphicConverter - Microsoft Paint" +.mtm Raw 'SNPL' 'MTM ' "PlayerPro - MultiMOD Music" +.mw Raw 'MWII' 'MW2D' "MacWrite II - MacWrite Document (application/macwriteii)" +.mwii Raw 'MWII' 'MW2D' "MacWrite II - MacWrite Document (application/macwriteii)" +.neo Raw 'GKON' 'NeoC' "GraphicConverter - Atari NeoChrome" +.nfo Ascii 'ttxt' 'TEXT' "SimpleText - Info Text (application/text)" +.nst Raw 'SCPL' 'STrk' "SoundApp - MOD Music" +.obj Raw 'SWIN' 'PCFL' "SoftWindows - Object (DOS/Windows)" +.oda Raw 'ODA ' 'ODIF' "MacODA XTND Translator - ODA Document (application/oda)" +.okt Raw 'SCPL' 'OKTA' "SoundApp - Oktalyser MOD Music" +.out Raw 'hDmp' 'BINA' "HexEdit - Output File" +.ovl Raw 'SWIN' 'PCFL' "SoftWindows - Overlay (DOS/Windows)" +.p Ascii 'CWIE' 'TEXT' "CodeWarrior - Pascal Source" +.pac Raw 'GKON' 'STAD' "GraphicConverter - Atari STAD Image" +.pas Ascii 'CWIE' 'TEXT' "CodeWarrior - Pascal Source" +.pbm Raw 'GKON' 'PPGM' "GraphicConverter - Portable Bitmap (image/x-pbm)" +.pbm Raw 'GKON' 'PPGM' "GraphicConverter - Portable Bitmap (image/x-portable-bitmap)" +.pc1 Raw 'GKON' 'Dega' "GraphicConverter - Atari Degas Image" +.pc2 Raw 'GKON' 'Dega' "GraphicConverter - Atari Degas Image" +.pc3 Raw 'GKON' 'Dega' "GraphicConverter - Atari Degas Image" +.pcs Raw 'GKON' 'PICS' "GraphicConverter - Animated PICTs" +.pct Raw 'ttxt' 'PICT' "SimpleText - PICT Picture (image/x-pict)" +.pcx Raw 'GKON' 'PCXx' "GraphicConverter - PC PaintBrush" +.pdb Ascii 'RSML' 'TEXT' "RasMac - Brookhaven PDB file" +.pdf Raw 'CARO' 'PDF ' "Acrobat Reader - Portable Document Format (application/pdf)" +.pdx Ascii 'ALD5' 'TEXT' "PageMaker - Printer Description" +.pgm Raw 'GKON' 'PPGM' "GraphicConverter - Portable Graymap (image/x-pgm)" +.pgm Raw 'GKON' 'PPGM' "GraphicConverter - Portable Graymap (image/x-portable-graymap)" +.pi1 Raw 'GKON' 'Dega' "GraphicConverter - Atari Degas Image" +.pi2 Raw 'GKON' 'Dega' "GraphicConverter - Atari Degas Image" +.pi3 Raw 'GKON' 'Dega' "GraphicConverter - Atari Degas Image" +.pic Raw 'ttxt' 'PICT' "SimpleText - PICT Picture (image/x-pict)" +.pict Raw 'ttxt' 'PICT' "SimpleText - PICT Picture (image/x-macpict)" +.pit Raw 'SITx' 'PIT ' "StuffIt Expander - PackIt Archive" +.pkg Raw 'GEOL' 'HBSF' "AppleLink - AppleLink Package" +.pl Ascii 'McPL' 'TEXT' "MacPerl - Perl Source" +.plt Raw 'GKON' 'HPGL' "GraphicConverter - HP GL/2" +.pm Raw 'GKON' 'PMpm' "GraphicConverter - Bitmap from xv" +.pm3 Raw 'ALD3' 'ALB3' "PageMaker - PageMaker 3 Document" +.pm4 Raw 'ALD4' 'ALB4' "PageMaker - PageMaker 4 Document" +.pm5 Raw 'ALD5' 'ALB5' "PageMaker - PageMaker 5 Document" +.png Raw 'GKON' 'PNG ' "GraphicConverter - Portable Network Graphic" +.pntg Raw 'GKON' 'PNTG' "GraphicConverter - Macintosh Painting" +.ppd Ascii 'ALD5' 'TEXT' "PageMaker - Printer Description" +.ppm Raw 'GKON' 'PPGM' "GraphicConverter - Portable Pixmap (image/x-ppm)" +.ppm Raw 'GKON' 'PPGM' "GraphicConverter - Portable Pixmap (image/x-portable-pixmap)" +.prn Ascii 'TBB6' 'TEXT' "TexEdit - Printer Output File" +.ps Ascii 'vgrd' 'TEXT' "LaserWriter 8 - PostScript (application/postscript)" +.psd Raw '8BIM' '8BPS' "Photoshop - PhotoShop Document" +.pt4 Raw 'ALD4' 'ALT4' "PageMaker - PageMaker 4 Template" +.pt5 Raw 'ALD5' 'ALT5' "PageMaker - PageMaker 5 Template" +.pxr Raw '8BIM' 'PXR ' "Photoshop - Pixar Image" +.qdv Raw 'GKON' 'QDVf' "GraphicConverter - QDV image" +.qt Raw 'ttxt' 'MooV' "SimpleText - QuickTime Movie (video/quicktime)" +.qxd Raw 'XPR3' 'XDOC' "QuarkXpress - QuarkXpress Document" +.qxt Raw 'XPR3' 'XTMP' "QuarkXpress - QuarkXpress Template" +.ram Ascii '????' 'TEXT' "Unknown - Real Audio (audio/x-pn-realaudio)" +.raw Raw 'GKON' 'BINA' "GraphicConverter - Raw Image" +.readme Ascii 'TBB6' 'TEXT' "TexEdit - Text Readme (application/text)" +.rgb Raw 'GKON' 'SGI ' "GraphicConverter - SGI Image (image/x-rgb)" +.rgba Raw 'GKON' 'SGI ' "GraphicConverter - SGI Image (image/x-rgb)" +.rib Ascii 'RINI' 'TEXT' "Renderman - Renderman 3D Data" +.rif Raw 'GKON' 'RIFF' "GraphicConverter - RIFF Graphic" +.rle Raw 'GKON' 'RLE ' "GraphicConverter - RLE image" +.rme Ascii 'ttxt' 'TEXT' "SimpleText - Text Readme" +.rpl Raw 'REP!' 'FRL!' "Replica - Replica Document" +.rsc Raw 'RSED' 'rsrc' "ResEdit - Resource File" +.rsrc Raw 'RSED' 'rsrc' "ResEdit - Resource File" +.rtf Ascii 'MSWD' 'TEXT' "Microsoft Word - Rich Text Format (application/rtf)" +.rtx Ascii 'TBB6' 'TEXT' "TexEdit - Rich Text (text/richtext)" +.s3m Raw 'SNPL' 'S3M ' "PlayerPro - ScreamTracker 3 MOD" +.scc Raw 'GKON' 'MSX ' "GraphicConverter - MSX pitcure" +.usal Raw 'GKON' 'RIX3' "GraphicConverter - ColoRIX" +.sci Raw 'GKON' 'RIX3' "GraphicConverter - ColoRIX" +.scp Raw 'GKON' 'RIX3' "GraphicConverter - ColoRIX" +.scr Raw 'GKON' 'RIX3' "GraphicConverter - ColoRIX" +.scu Raw 'GKON' 'RIX3' "GraphicConverter - ColoRIX" +.sea Raw '????' 'APPL' "Self Extracting Archive - Self-Extracting Archive" +.sf Raw 'SDHK' 'IRCM' "SoundHack - IRCAM Sound" +.sgi Raw 'GKON' 'SGI ' "GraphicConverter - SGI Image" +.sha Ascii 'UnSh' 'TEXT' "UnShar - Unix Shell Archive (application/x-shar)" +.shar Ascii 'UnSh' 'TEXT' "UnShar - Unix Shell Archive (application/x-shar)" +.shp Raw 'GKON' 'SHPp' "GraphicConverter - Printmaster Icon Library" +.sit Raw 'SIT!' 'SITD' "StuffIt - StuffIt Archive" +.sithqx Ascii 'TBB6' 'TEXT' "TexEdit - BinHexed StuffIt Archive (application/mac-binhex40)" +.six Raw 'GKON' 'SIXE' "GraphicConverter - SIXEL image" +.slk Ascii 'XCEL' 'TEXT' "Excel - SYLK Spreadsheet" +.snd Raw 'SCPL' 'BINA' "SoundApp - Sound of various types" +.spc Raw 'GKON' 'Spec' "GraphicConverter - Atari Spectrum 512" +.sr Raw 'GKON' 'SUNn' "GraphicConverter - Sun Raster Image" +.sty Ascii '*TEX' 'TEXT' "Textures - TeX Style" +.sun Raw 'GKON' 'SUNn' "GraphicConverter - Sun Raster Image" +.sup Raw 'GKON' 'SCRN' "GraphicConverter - StartupScreen" +.svx Raw 'SCPL' '8SVX' "SoundApp - Amiga IFF Sound" +.syk Ascii 'XCEL' 'TEXT' "Excel - SYLK Spreadsheet" +.sylk Ascii 'XCEL' 'TEXT' "Excel - SYLK Spreadsheet" +.tar Raw 'S691' 'TARF' "SunTar - Unix Tape ARchive (application/x-tar)" +.targa Raw 'GKON' 'TPIC' "GraphicConverter - Truevision Image" +.taz Raw 'SITx' 'ZIVU' "StuffIt Expander - Compressed Tape ARchive (application/x-compress)" +.tex Ascii 'OTEX' 'TEXT' "OzTeX - TeX Document (application/x-tex)" +.texi Ascii 'OTEX' 'TEXT' "OzTeX - TeX Document" +.texinfo Ascii 'OTEX' 'TEXT' "OzTeX - TeX Document (application/x-texinfo)" +.text Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/plain)" +.tga Raw 'GKON' 'TPIC' "GraphicConverter - Truevision Image" +.tgz Raw 'Gzip' 'Gzip' "MacGzip - Gnu ZIPed Tape ARchive (application/x-gzip)" +.tif Raw 'JVWR' 'TIFF' "JPEGView - TIFF Picture (image/tiff)" +.tiff Raw 'JVWR' 'TIFF' "JPEGView - TIFF Picture (image/tiff)" +.tny Raw 'GKON' 'TINY' "GraphicConverter - Atari TINY Bitmap" +.tsv Ascii 'XCEL' 'TEXT' "Excel - Tab Separated Values (text/tab-separated-values)" +.tx8 Ascii 'ttxt' 'TEXT' "SimpleText - 8-bit ASCII Text" +.txt Ascii 'ttxt' 'TEXT' "SimpleText - ASCII Text (text/plain)" +.ul Raw 'SCPL' 'ULAW' "SoundApp - Mu-Law Sound (audio/basic)" +.url Raw 'Arch' 'AURL' "Anarchie - URL Bookmark (message/external-body)" +.uu Ascii 'TBB6' 'TEXT' "TexEdit - UUEncode" +.uue Ascii 'TBB6' 'TEXT' "TexEdit - UUEncode" +.vff Raw 'GKON' 'VFFf' "GraphicConverter - DESR VFF Greyscale Image" +.vga Raw 'JVWR' 'BMPp' "JPEGView - OS/2 Bitmap" +.voc Raw 'SCPL' 'VOC ' "SoundApp - VOC Sound" +.w51 Raw 'WPC2' '.WP5' "WordPerfect - WordPerfect PC 5.1 Doc (application/wordperfect5.1)" +.wav Raw 'SCPL' 'WAVE' "SoundApp - Windows WAV Sound (audio/x-wav)" +.wk1 Raw 'XCEL' 'XLBN' "Excel - Lotus Spreadsheet r2.1" +.wks Raw 'XCEL' 'XLBN' "Excel - Lotus Spreadsheet r1.x" +.wmf Raw 'GKON' 'WMF ' "GraphicConverter - Windows Metafile" +.wp Raw 'WPC2' '.WP5' "WordPerfect - WordPerfect PC 5.1 Doc (application/wordperfect5.1)" +.wp4 Raw 'WPC2' '.WP4' "WordPerfect - WordPerfect PC 4.2 Doc" +.wp5 Raw 'WPC2' '.WP5' "WordPerfect - WordPerfect PC 5.x Doc (application/wordperfect5.1)" +.wp6 Raw 'WPC2' '.WP6' "WordPerfect - WordPerfect PC 6.x Doc" +.wpg Raw 'GKON' 'WPGf' "GraphicConverter - WordPerfect Graphic" +.wpm Raw 'WPC2' 'WPD1' "WordPerfect - WordPerfect Mac" +.wri Raw 'MSWD' 'WDBN' "Microsoft Word - MS Write/Windows" +.wve Raw 'SCPL' 'BINA' "SoundApp - PSION sound" +.x10 Raw 'GKON' 'XWDd' "GraphicConverter - X-Windows Dump (image/x-xwd)" +.x11 Raw 'GKON' 'XWDd' "GraphicConverter - X-Windows Dump (image/x-xwd)" +.xbm Raw 'GKON' 'XBM ' "GraphicConverter - X-Windows Bitmap (image/x-xbm)" +.xbm Raw 'GKON' 'XBM ' "GraphicConverter - X-Windows Bitmap (image/x-xbitmap)" +.xl Raw 'XCEL' 'XLS ' "Excel - Excel Spreadsheet" +.xlc Raw 'XCEL' 'XLC ' "Excel - Excel Chart" +.xlm Raw 'XCEL' 'XLM ' "Excel - Excel Macro" +.xls Raw 'XCEL' 'XLS ' "Excel - Excel Spreadsheet" +.xlw Raw 'XCEL' 'XLW ' "Excel - Excel Workspace" +.xm Raw 'SNPL' 'XM ' "PlayerPro - FastTracker MOD Music" +.xpm Raw 'GKON' 'XPM ' "GraphicConverter - X-Windows Pixmap (image/x-xpm)" +.xpm Raw 'GKON' 'XPM ' "GraphicConverter - X-Windows Pixmap (image/x-xpixmap)" +.xwd Raw 'GKON' 'XWDd' "GraphicConverter - X-Windows Dump (image/x-xwd)" +# +# Add the default translation for anything not recognized +# +* Ascii 'ttxt' 'TEXT' "SimpleText - Text file" diff --git a/genisoimage/multi.c b/genisoimage/multi.c new file mode 100644 index 0000000..e069c91 --- /dev/null +++ b/genisoimage/multi.c @@ -0,0 +1,1912 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)multi.c 1.68 05/05/15 joerg */ +/* + * File multi.c - scan existing iso9660 image and merge into + * iso9660 filesystem. Used for multisession support. + * + * Written by Eric Youngdale (1996). + * Copyright (c) 1999-2003 J. Schilling + * + * 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 <mconfig.h> +#include "genisoimage.h" +#include <timedefs.h> +#include <errno.h> +#include <utypes.h> +#include <schily.h> +#include <ctype.h> /* Needed for printasc() */ + +#ifdef VMS + +#include <sys/file.h> +#include <vms/fabdef.h> +#include "vms.h" +#endif + +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#ifndef roundup +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#endif + +/* + * Cannot debug memset() with gdb on Linux, so use fillbytes() + */ +/*#define memset(s, c, n) fillbytes(s, n, c)*/ + +#define TF_CREATE 1 +#define TF_MODIFY 2 +#define TF_ACCESS 4 +#define TF_ATTRIBUTES 8 + +static int isonum_711(unsigned char *p); +static int isonum_721(unsigned char *p); +static int isonum_723(unsigned char *p); +static int isonum_731(unsigned char *p); + +static void printasc(char *txt, unsigned char *p, int len); +static void prbytes(char *txt, unsigned char *p, int len); +unsigned char *parse_xa(unsigned char *pnt, int *lenp, + struct directory_entry *dpnt); +int rr_flags(struct iso_directory_record *idr); +static int parse_rrflags(Uchar *pnt, int len, int cont_flag); +static BOOL find_rr(struct iso_directory_record *idr, Uchar **pntp, + int *lenp); +static int parse_rr(unsigned char *pnt, int len, + struct directory_entry *dpnt); +static int check_rr_dates(struct directory_entry *dpnt, + struct directory_entry *current, + struct stat *statbuf, + struct stat *lstatbuf); +static struct directory_entry ** + read_merging_directory(struct iso_directory_record *, int *); +static int free_mdinfo(struct directory_entry **, int len); +static void free_directory_entry(struct directory_entry * dirp); +static void merge_remaining_entries(struct directory *, + struct directory_entry **, int); + +static int merge_old_directory_into_tree(struct directory_entry *, + struct directory *); +static void check_rr_relocation(struct directory_entry *de); + +static int +isonum_711(unsigned char *p) +{ + return (*p & 0xff); +} + +static int +isonum_721(unsigned char *p) +{ + return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); +} + +static int +isonum_723(unsigned char *p) +{ +#if 0 + if (p[0] != p[3] || p[1] != p[2]) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "invalid format 7.2.3 number\n"); +#else + fprintf(stderr, "invalid format 7.2.3 number\n"); + exit(1); +#endif + } +#endif + return (isonum_721(p)); +} + +static int +isonum_731(unsigned char *p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +int +isonum_733(unsigned char *p) +{ + return (isonum_731(p)); +} + +FILE *in_image = NULL; + +#ifndef USE_SCG +/* + * Don't define readsecs if genisoimage is linked with + * the SCSI library. + * readsecs() will be implemented as SCSI command in this case. + * + * Use global var in_image directly in readsecs() + * the SCSI equivalent will not use a FILE* for I/O. + * + * The main point of this pointless abstraction is that Solaris won't let + * you read 2K sectors from the cdrom driver. The fact that 99.9% of the + * discs out there have a 2K sectorsize doesn't seem to matter that much. + * Anyways, this allows the use of a scsi-generics type of interface on + * Solaris. + */ +static int +readsecs(int startsecno, void *buffer, int sectorcount) +{ + int f = fileno(in_image); + + if (lseek(f, (off_t) startsecno * SECTOR_SIZE, SEEK_SET) == (off_t) - 1) { +#ifdef USE_LIBSCHILY + comerr(" Seek error on old image\n"); +#else + fprintf(stderr, " Seek error on old image\n"); + exit(10); +#endif + } + if (read(f, buffer, (sectorcount * SECTOR_SIZE)) + != (sectorcount * SECTOR_SIZE)) { +#ifdef USE_LIBSCHILY + comerr(" Read error on old image\n"); +#else + fprintf(stderr, " Read error on old image\n"); + exit(10); +#endif + } + return (sectorcount * SECTOR_SIZE); +} + +#endif + +static void +printasc(char *txt, unsigned char *p, int len) +{ + int i; + + fprintf(stderr, "%s ", txt); + for (i = 0; i < len; i++) { + if (isprint(p[i])) + fprintf(stderr, "%c", p[i]); + else + fprintf(stderr, "."); + } + fprintf(stderr, "\n"); +} + +static void +prbytes(char *txt, register Uchar *p, register int len) +{ + fprintf(stderr, "%s", txt); + while (--len >= 0) + fprintf(stderr, " %02X", *p++); + fprintf(stderr, "\n"); +} + +unsigned char * +parse_xa(unsigned char *pnt, int *lenp, struct directory_entry *dpnt) +{ + struct iso_xa_dir_record *xadp; + int len = *lenp; +static int did_xa = 0; + +/*fprintf(stderr, "len: %d\n", len);*/ + + if (len >= 14) { + xadp = (struct iso_xa_dir_record *)pnt; + +/* if (dpnt) prbytes("XA ", pnt, len);*/ + if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' && + xadp->reserved[0] == '\0') { + len -= 14; + pnt += 14; + *lenp = len; + if (!did_xa) { + did_xa = 1; + errmsgno(EX_BAD, "Found XA directory extension record.\n"); + } + } else if (pnt[2] == 0) { + char *cp = NULL; + + if (dpnt) + cp = (char *)&dpnt->isorec; + if (cp) { + prbytes("ISOREC:", (Uchar *)cp, 33+cp[32]); + printasc("ISOREC:", (Uchar *)cp, 33+cp[32]); + prbytes("XA REC:", pnt, len); + printasc("XA REC:", pnt, len); + } + if (no_rr == 0) { + errmsgno(EX_BAD, "Disabling RR / XA / AA.\n"); + no_rr = 1; + } + *lenp = 0; + if (cp) { + errmsgno(EX_BAD, "Problems with old ISO directory entry for file: '%s'.\n", &cp[33]); + } + errmsgno(EX_BAD, "Illegal extended directory attributes found (bad XA disk?).\n"); +/* errmsgno(EX_BAD, "Disabling Rock Ridge for old session.\n");*/ + comerrno(EX_BAD, "Try again using the -no-rr option.\n"); + } + } + if (len >= 4 && pnt[3] != 1 && pnt[3] != 2) { + prbytes("BAD RR ATTRIBUTES:", pnt, len); + printasc("BAD RR ATTRIBUTES:", pnt, len); + } + return (pnt); +} + +static BOOL +find_rr(struct iso_directory_record *idr, Uchar **pntp, int *lenp) +{ + struct iso_xa_dir_record *xadp; + int len; + unsigned char *pnt; + BOOL ret = FALSE; + + len = idr->length[0] & 0xff; + len -= sizeof (struct iso_directory_record); + len += sizeof (idr->name); + len -= idr->name_len[0]; + + pnt = (unsigned char *) idr; + pnt += sizeof (struct iso_directory_record); + pnt -= sizeof (idr->name); + pnt += idr->name_len[0]; + if ((idr->name_len[0] & 1) == 0) { + pnt++; + len--; + } + if (len >= 14) { + xadp = (struct iso_xa_dir_record *)pnt; + + if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' && + xadp->reserved[0] == '\0') { + len -= 14; + pnt += 14; + ret = TRUE; + } + } + *pntp = pnt; + *lenp = len; + return (ret); +} + +static int +parse_rrflags(Uchar *pnt, int len, int cont_flag) +{ + int ncount; + int cont_extent; + int cont_offset; + int cont_size; + int flag1; + int flag2; + + cont_extent = cont_offset = cont_size = 0; + + ncount = 0; + flag1 = flag2 = 0; + while (len >= 4) { + if (pnt[3] != 1 && pnt[3] != 2) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "**BAD RRVERSION (%d) for %c%c\n", + pnt[3], pnt[0], pnt[1]); +#else + fprintf(stderr, + "**BAD RRVERSION (%d) for %c%c\n", + pnt[3], pnt[0], pnt[1]); +#endif + return (0); /* JS ??? Is this right ??? */ + } + ncount++; + if (pnt[0] == 'R' && pnt[1] == 'R') + flag1 = pnt[4] & 0xff; + + if (strncmp((char *) pnt, "PX", 2) == 0) /* POSIX attributes */ + flag2 |= 1; + if (strncmp((char *) pnt, "PN", 2) == 0) /* POSIX device number */ + flag2 |= 2; + if (strncmp((char *) pnt, "SL", 2) == 0) /* Symlink */ + flag2 |= 4; + if (strncmp((char *) pnt, "NM", 2) == 0) /* Alternate Name */ + flag2 |= 8; + if (strncmp((char *) pnt, "CL", 2) == 0) /* Child link */ + flag2 |= 16; + if (strncmp((char *) pnt, "PL", 2) == 0) /* Parent link */ + flag2 |= 32; + if (strncmp((char *) pnt, "RE", 2) == 0) /* Relocated Direcotry */ + flag2 |= 64; + if (strncmp((char *) pnt, "TF", 2) == 0) /* Time stamp */ + flag2 |= 128; + if (strncmp((char *) pnt, "SP", 2) == 0) { /* SUSP record */ + flag2 |= 1024; +/* su_version = pnt[3] & 0xff;*/ + } + if (strncmp((char *) pnt, "AA", 2) == 0) { /* Apple Signature record */ + flag2 |= 2048; +/* aa_version = pnt[3] & 0xff;*/ + } + + if (strncmp((char *)pnt, "CE", 2) == 0) { /* Continuation Area */ + cont_extent = isonum_733(pnt+4); + cont_offset = isonum_733(pnt+12); + cont_size = isonum_733(pnt+20); + } + + len -= pnt[2]; + pnt += pnt[2]; + if (len <= 3 && cont_extent) { + unsigned char sector[SECTOR_SIZE]; + + readsecs(cont_extent, sector, 1); + flag2 |= parse_rrflags(§or[cont_offset], cont_size, 1); + } + } + return (flag2); +} + +int +rr_flags(struct iso_directory_record *idr) +{ + int len; + unsigned char *pnt; + int ret = 0; + + if (find_rr(idr, &pnt, &len)) + ret |= 4096; + ret |= parse_rrflags(pnt, len, 0); + return (ret); +} + +/* + * Parse the RR attributes so we can find the file name. + */ +static int +parse_rr(unsigned char *pnt, int len, struct directory_entry *dpnt) +{ + int cont_extent; + int cont_offset; + int cont_size; + char name_buf[256]; + + cont_extent = cont_offset = cont_size = 0; + + pnt = parse_xa(pnt, &len, dpnt /* 0 */); + + while (len >= 4) { + if (pnt[3] != 1 && pnt[3] != 2) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "**BAD RRVERSION (%d) for %c%c\n", + pnt[3], pnt[0], pnt[1]); +#else + fprintf(stderr, + "**BAD RRVERSION (%d) for %c%c\n", + pnt[3], pnt[0], pnt[1]); +#endif + return (-1); + } + if (strncmp((char *) pnt, "NM", 2) == 0) { + strncpy(name_buf, (char *) pnt + 5, pnt[2] - 5); + name_buf[pnt[2] - 5] = 0; + if (dpnt->name) { + size_t nlen = strlen(dpnt->name); + + /* + * append to name from previous NM records + */ + dpnt->name = realloc(dpnt->name, nlen + + strlen(name_buf) + 1); + strcpy(dpnt->name + nlen, name_buf); + } else { + dpnt->name = strdup(name_buf); + dpnt->got_rr_name = 1; + } + /* continue searching for more NM records */ + } else if (strncmp((char *) pnt, "CE", 2) == 0) { + cont_extent = isonum_733(pnt + 4); + cont_offset = isonum_733(pnt + 12); + cont_size = isonum_733(pnt + 20); + } + + len -= pnt[2]; + pnt += pnt[2]; + if (len <= 3 && cont_extent) { + unsigned char sector[SECTOR_SIZE]; + + readsecs(cont_extent, sector, 1); + if (parse_rr(§or[cont_offset], + cont_size, dpnt) == -1) + return (-1); + } + } + + /* Fall back to the iso name if no RR name found */ + if (dpnt->name == NULL) { + char *cp; + + strcpy(name_buf, dpnt->isorec.name); + cp = strchr(name_buf, ';'); + if (cp != NULL) { + *cp = '\0'; + } + dpnt->name = strdup(name_buf); + } + return (0); +}/* parse_rr */ + + +/* + * Returns 1 if the two files are identical + * Returns 0 if the two files differ + */ +static int +check_rr_dates(struct directory_entry *dpnt, + struct directory_entry *current, + struct stat *statbuf, + struct stat *lstatbuf) +{ + int cont_extent; + int cont_offset; + int cont_size; + int offset; + unsigned char *pnt; + int len; + int same_file; + int same_file_type; + mode_t mode; + char time_buf[7]; + + + cont_extent = cont_offset = cont_size = 0; + same_file = 1; + same_file_type = 1; + + pnt = dpnt->rr_attributes; + len = dpnt->rr_attr_size; + /* + * We basically need to parse the rr attributes again, and dig out the + * dates and file types. + */ + pnt = parse_xa(pnt, &len, /* dpnt */ 0); + while (len >= 4) { + if (pnt[3] != 1 && pnt[3] != 2) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "**BAD RRVERSION (%d) for %c%c\n", + pnt[3], pnt[0], pnt[1]); +#else + fprintf(stderr, + "**BAD RRVERSION (%d) for %c%c\n", + pnt[3], pnt[0], pnt[1]); +#endif + return (-1); + } + + /* + * If we have POSIX file modes, make sure that the file type is + * the same. If it isn't, then we must always write the new + * file. + */ + if (strncmp((char *) pnt, "PX", 2) == 0) { + mode = isonum_733(pnt + 4); + if ((lstatbuf->st_mode & S_IFMT) != (mode & S_IFMT)) { + same_file_type = 0; + same_file = 0; + } + } + if (strncmp((char *) pnt, "TF", 2) == 0) { + offset = 5; + if (pnt[4] & TF_CREATE) { + iso9660_date((char *) time_buf, + lstatbuf->st_ctime); + if (memcmp(time_buf, pnt + offset, 7) != 0) + same_file = 0; + offset += 7; + } + if (pnt[4] & TF_MODIFY) { + iso9660_date((char *) time_buf, + lstatbuf->st_mtime); + if (memcmp(time_buf, pnt + offset, 7) != 0) + same_file = 0; + offset += 7; + } + } + if (strncmp((char *) pnt, "CE", 2) == 0) { + cont_extent = isonum_733(pnt + 4); + cont_offset = isonum_733(pnt + 12); + cont_size = isonum_733(pnt + 20); + } + + len -= pnt[2]; + pnt += pnt[2]; + if (len <= 3 && cont_extent) { + unsigned char sector[SECTOR_SIZE]; + + readsecs(cont_extent, sector, 1); + /* + * Continue to scan the extension record. + * Note that this has not been tested yet, but it is + * definitely more correct that calling parse_rr() + * as done in Eric's old code. + */ + pnt = §or[cont_offset]; + len = cont_size; + /* + * Clear the "pending extension record" state as + * we did already read it now. + */ + cont_extent = cont_offset = cont_size = 0; + } + } + + /* + * If we have the same fundamental file type, then it is clearly safe + * to reuse the TRANS.TBL entry. + */ + if (same_file_type) { + current->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY; + } + return (same_file); +} + +static struct directory_entry ** +read_merging_directory(struct iso_directory_record *mrootp, int *nentp) +{ + unsigned char *cpnt; + unsigned char *cpnt1; + char *p; + char *dirbuff; + int i; + struct iso_directory_record *idr; + int len; + int nbytes; + int nent; + struct directory_entry **pnt; + int rlen; + struct directory_entry **rtn; + int seen_rockridge; + unsigned char *tt_buf; + int tt_extent; + int tt_size; + + static int warning_given = 0; + + /* + * This is the number of sectors we will need to read. We need to + * round up to get the last fractional sector - we are asking for the + * data in terms of a number of sectors. + */ + nbytes = roundup(isonum_733((unsigned char *) mrootp->size), + SECTOR_SIZE); + + /* + * First, allocate a buffer large enough to read in the entire + * directory. + */ + dirbuff = (char *) e_malloc(nbytes); + + readsecs(isonum_733((unsigned char *) mrootp->extent), dirbuff, + nbytes / SECTOR_SIZE); + + /* + * Next look over the directory, and count up how many entries we have. + */ + len = isonum_733((unsigned char *) mrootp->size); + i = 0; + *nentp = 0; + nent = 0; + while (i < len) { + idr = (struct iso_directory_record *) & dirbuff[i]; + if (idr->length[0] == 0) { + i = ISO_ROUND_UP(i); + continue; + } + nent++; + i += idr->length[0]; + } + + /* + * Now allocate the buffer which will hold the array we are about to + * return. + */ + rtn = (struct directory_entry **) e_malloc(nent * sizeof (*rtn)); + + /* + * Finally, scan the directory one last time, and pick out the relevant + * bits of information, and store it in the relevant bits of the + * structure. + */ + i = 0; + pnt = rtn; + tt_extent = 0; + seen_rockridge = 0; + tt_size = 0; + while (i < len) { + idr = (struct iso_directory_record *) & dirbuff[i]; + if (idr->length[0] == 0) { + i = ISO_ROUND_UP(i); + continue; + } + *pnt = (struct directory_entry *) e_malloc(sizeof (**rtn)); + (*pnt)->next = NULL; +#ifdef DEBUG + fprintf(stderr, "IDR name: '%s' ist: %d soll: %d\n", + idr->name, strlen(idr->name), idr->name_len[0]); +#endif + (*pnt)->isorec = *idr; + (*pnt)->starting_block = + isonum_733((unsigned char *) idr->extent); + (*pnt)->size = isonum_733((unsigned char *) idr->size); + (*pnt)->priority = 0; + (*pnt)->name = NULL; + (*pnt)->got_rr_name = 0; + (*pnt)->table = NULL; + (*pnt)->whole_name = NULL; + (*pnt)->filedir = NULL; + (*pnt)->parent_rec = NULL; + /* + * Set this information so that we correctly cache previous + * session bits of information. + */ + (*pnt)->inode = (*pnt)->starting_block; + (*pnt)->dev = PREV_SESS_DEV; + (*pnt)->rr_attributes = NULL; + (*pnt)->rr_attr_size = 0; + (*pnt)->total_rr_attr_size = 0; + (*pnt)->de_flags = SAFE_TO_REUSE_TABLE_ENTRY; +#ifdef APPLE_HYB + (*pnt)->assoc = NULL; + (*pnt)->hfs_ent = NULL; +#endif /* APPLE_HYB */ + + /* + * Check for and parse any RR attributes for the file. All we + * are really looking for here is the original name of the + * file. + */ + rlen = idr->length[0] & 0xff; + cpnt = (unsigned char *) idr; + + rlen -= offsetof(struct iso_directory_record, name[0]); + cpnt += offsetof(struct iso_directory_record, name[0]); + + rlen -= idr->name_len[0]; + cpnt += idr->name_len[0]; + + if ((idr->name_len[0] & 1) == 0) { + cpnt++; + rlen--; + } + + if (no_rr) + rlen = 0; + if (rlen > 0) { + (*pnt)->total_rr_attr_size = + (*pnt)->rr_attr_size = rlen; + (*pnt)->rr_attributes = e_malloc(rlen); + memcpy((*pnt)->rr_attributes, cpnt, rlen); + seen_rockridge = 1; + } +#ifdef DEBUG + fprintf(stderr, "INT name: '%s' ist: %d soll: %d\n", + (*pnt)->isorec.name, strlen((*pnt)->isorec.name), + idr->name_len[0]); +#endif + + if (idr->name_len[0] < sizeof ((*pnt)->isorec.name)) { + /* + * Now zero out the remainder of the name field. + */ + cpnt = (unsigned char *) (*pnt)->isorec.name; + cpnt += idr->name_len[0]; + memset(cpnt, 0, + sizeof ((*pnt)->isorec.name) - idr->name_len[0]); + } else { + /* + * Simple sanity work to make sure that we have no + * illegal data structures in our tree. + */ + (*pnt)->isorec.name[MAX_ISONAME] = '\0'; + (*pnt)->isorec.name_len[0] = MAX_ISONAME; + } + /* + * If the filename len from the old session is more + * then 31 chars, there is a high risk of hard violations + * if the ISO9660 standard. + * Run it through our name canonication machine.... + */ + if (idr->name_len[0] > LEN_ISONAME || check_oldnames) { + iso9660_check(idr, *pnt); + } + + if (parse_rr((*pnt)->rr_attributes, rlen, *pnt) == -1) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Cannot parse Rock Ridge attributes for '%s'.\n", + idr->name); +#else + fprintf(stderr, + "Cannot parse Rock Ridge attributes for '%s'.\n", + idr->name); + exit(1); +#endif + } + if (((*pnt)->isorec.name_len[0] == 1) && + (((*pnt)->isorec.name[0] == 0) || /* "." entry */ + ((*pnt)->isorec.name[0] == 1))) { /* ".." entry */ + + if ((*pnt)->name != NULL) { + free((*pnt)->name); + } + if ((*pnt)->whole_name != NULL) { + free((*pnt)->whole_name); + } + if ((*pnt)->isorec.name[0] == 0) { + (*pnt)->name = strdup("."); + } else { + (*pnt)->name = strdup(".."); + } + } +#ifdef DEBUG + fprintf(stderr, "got DE name: %s\n", (*pnt)->name); +#endif + + if (strncmp(idr->name, trans_tbl, strlen(trans_tbl)) == 0) { + if ((*pnt)->name != NULL) { + free((*pnt)->name); + } + if ((*pnt)->whole_name != NULL) { + free((*pnt)->whole_name); + } +/* (*pnt)->name = strdup("<translation table>");*/ + (*pnt)->name = strdup(trans_tbl); + tt_extent = isonum_733((unsigned char *) idr->extent); + tt_size = isonum_733((unsigned char *) idr->size); + if (tt_extent == 0) + tt_size = 0; + } + pnt++; + i += idr->length[0]; + } +#ifdef APPLE_HYB + /* + * If we find an associated file, check if there is a file + * with same ISO name and link it to this entry + */ + for (pnt = rtn, i = 0; i < nent; i++, pnt++) { + int j; + + rlen = isonum_711((*pnt)->isorec.name_len); + if ((*pnt)->isorec.flags[0] & ISO_ASSOCIATED) { + for (j = 0; j < nent; j++) { + if (strncmp(rtn[j]->isorec.name, + (*pnt)->isorec.name, rlen) == 0 && + (rtn[j]->isorec.flags[0] & ISO_ASSOCIATED) == 0) { + rtn[j]->assoc = *pnt; + + /* + * don't want this entry to be + * in the Joliet tree + */ + (*pnt)->de_flags |= INHIBIT_JOLIET_ENTRY; + + /* + * as we have associated files, then + * assume we are are dealing with + * Apple's extensions - if not already + * set + */ + if (apple_both == 0) { + apple_both = apple_ext = 1; + } + break; + } + } + } + } +#endif /* APPLE_HYB */ + + /* + * If there was a TRANS.TBL;1 entry, then grab it, read it, and use it + * to get the filenames of the files. Also, save the table info, just + * in case we need to use it. + * + * The entries look something like: F ISODUMP.;1 isodump + */ + if (tt_extent != 0 && tt_size != 0) { + nbytes = roundup(tt_size, SECTOR_SIZE); + tt_buf = (unsigned char *) e_malloc(nbytes); + readsecs(tt_extent, tt_buf, nbytes / SECTOR_SIZE); + + /* + * Loop through the file, examine each entry, and attempt to + * attach it to the correct entry. + */ + cpnt = tt_buf; + cpnt1 = tt_buf; + while (cpnt - tt_buf < tt_size) { + /* Skip to a line terminator, or end of the file. */ + while ((cpnt1 - tt_buf < tt_size) && + (*cpnt1 != '\n') && + (*cpnt1 != '\0')) { + cpnt1++; + } + /* Zero terminate this particular line. */ + if (cpnt1 - tt_buf < tt_size) { + *cpnt1 = '\0'; + } + /* + * Now dig through the actual directories, and try and + * find the attachment for this particular filename. + */ + for (pnt = rtn, i = 0; i < nent; i++, pnt++) { + rlen = isonum_711((*pnt)->isorec.name_len); + + /* + * If this filename is so long that it would + * extend past the end of the file, it cannot + * be the one we want. + */ + if (cpnt + 2 + rlen - tt_buf >= tt_size) { + continue; + } + /* + * Now actually compare the name, and make sure + * that the character at the end is a ' '. + */ + if (strncmp((char *) cpnt + 2, + (*pnt)->isorec.name, rlen) == 0 && + cpnt[2 + rlen] == ' ' && + (p = strchr((char *)&cpnt[2 + rlen], '\t'))) { + p++; + /* + * This is a keeper. Now determine the + * correct table entry that we will + * use on the new image. + */ + if (strlen(p) > 0) { + (*pnt)->table = + e_malloc(strlen(p) + 4); + sprintf((*pnt)->table, + "%c\t%s\n", + *cpnt, p); + } + if (!(*pnt)->got_rr_name) { + if ((*pnt)->name != NULL) { + free((*pnt)->name); + } + (*pnt)->name = strdup(p); + } + break; + } + } + cpnt = cpnt1 + 1; + cpnt1 = cpnt; + } + + free(tt_buf); + } else if (!seen_rockridge && !warning_given) { + /* + * Warn the user that iso-9660 names were used because neither + * Rock Ridge (-R) nor TRANS.TBL (-T) name translations were + * found. + */ + fprintf(stderr, + "Warning: Neither Rock Ridge (-R) nor TRANS.TBL (-T) \n"); + fprintf(stderr, + "name translations were found on previous session.\n"); + fprintf(stderr, + "ISO-9660 file names have been used instead.\n"); + warning_given = 1; + } + if (dirbuff != NULL) { + free(dirbuff); + } + *nentp = nent; + return (rtn); +}/* read_merging_directory */ + +/* + * Free any associated data related to the structures. + */ +static int +free_mdinfo(struct directory_entry **ptr, int len) +{ + int i; + struct directory_entry **p; + + p = ptr; + for (i = 0; i < len; i++, p++) { + /* + * If the tree-handling code decided that it needed an entry, it + * will have removed it from the list. Thus we must allow for + * null pointers here. + */ + if (*p == NULL) { + continue; + } + free_directory_entry(*p); + } + + free(ptr); + return (0); +} + +static void +free_directory_entry(struct directory_entry *dirp) +{ + if (dirp->name != NULL) + free(dirp->name); + + if (dirp->whole_name != NULL) + free(dirp->whole_name); + + if (dirp->rr_attributes != NULL) + free(dirp->rr_attributes); + + if (dirp->table != NULL) + free(dirp->table); + + free(dirp); +} + +/* + * Search the list to see if we have any entries from the previous + * session that match this entry. If so, copy the extent number + * over so we don't bother to write it out to the new session. + */ +int +check_prev_session(struct directory_entry **ptr, int len, + struct directory_entry *curr_entry, + struct stat *statbuf, + struct stat *lstatbuf, + struct directory_entry **odpnt) +{ + int i; + int rr; + int retcode = 0; /* Default not found */ + + for (i = 0; i < len; i++) { + if (ptr[i] == NULL) { /* Used or empty entry skip */ + continue; + } +#if 0 + if (ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1 && + ptr[i]->name[0] == '\0') { + continue; + } + if (ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1 && + ptr[i]->name[0] == 1) { + continue; + } +#else + if (ptr[i]->name != NULL && strcmp(ptr[i]->name, ".") == 0) { + continue; + } + if (ptr[i]->name != NULL && strcmp(ptr[i]->name, "..") == 0) { + continue; + } +#endif + + if (ptr[i]->name != NULL && + strcmp(ptr[i]->name, curr_entry->name) != 0) { + /* Not the same name continue */ + continue; + } + /* + * It's a directory so we must always merge it with the new + * session. Never ever reuse directory extents. See comments + * in tree.c for an explaination of why this must be the case. + */ + if ((curr_entry->isorec.flags[0] & ISO_DIRECTORY) != 0) { + retcode = 2; /* Flag directory case */ + goto found_it; + } + /* + * We know that the files have the same name. If they also + * have the same file type (i.e. file, dir, block, etc), then + * we can safely reuse the TRANS.TBL entry for this file. The + * check_rr_dates() function will do this for us. + * + * Verify that the file type and dates are consistent. If not, + * we probably have a different file, and we need to write it + * out again. + */ + retcode = 1; /* We found a non directory */ + + if (ptr[i]->rr_attributes != NULL) { + if ((rr = check_rr_dates(ptr[i], curr_entry, statbuf, + lstatbuf)) == -1) + return (-1); + + if (rr == 0) { /* Different files */ + goto found_it; + } + } + /* + * Verify size and timestamp. If rock ridge is in use, we + * need to compare dates from RR too. Directories are special, + * we calculate their size later. + */ + if (ptr[i]->size != curr_entry->size) { + /* Different files */ + goto found_it; + } + if (memcmp(ptr[i]->isorec.date, + curr_entry->isorec.date, 7) != 0) { + /* Different files */ + goto found_it; + } + /* We found it and we can reuse the extent */ + memcpy(curr_entry->isorec.extent, ptr[i]->isorec.extent, 8); + curr_entry->starting_block = isonum_733((unsigned char *)ptr[i]->isorec.extent); + curr_entry->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY; + goto found_it; + } + return (retcode); + +found_it: + if (odpnt != NULL) { + *odpnt = ptr[i]; + } else { + free(ptr[i]); + } + ptr[i] = NULL; + return (retcode); +} + +/* + * open_merge_image: Open an existing image. + */ +int +open_merge_image(char *path) +{ +#ifndef USE_SCG + in_image = fopen(path, "rb"); + if (in_image == NULL) { + return (-1); + } +#else + in_image = fopen(path, "rb"); + if (in_image == NULL) { + if (scsidev_open(path) < 0) + return (-1); + } +#endif + return (0); +} + +/* + * close_merge_image: Close an existing image. + */ +int +close_merge_image() +{ +#ifdef USE_SCG + return (scsidev_close()); +#else + return (fclose(in_image)); +#endif +} + +/* + * merge_isofs: Scan an existing image, and return a pointer + * to the root directory for this image. + */ +struct iso_directory_record * +merge_isofs(char *path) +{ + char buffer[SECTOR_SIZE]; + int file_addr; + int i; + struct iso_primary_descriptor *pri = NULL; + struct iso_directory_record *rootp; + struct iso_volume_descriptor *vdp; + + /* + * Start by searching for the volume header. Ultimately, we need to + * search for volume headers in multiple places because we might be + * starting with a multisession image. FIXME(eric). + */ + get_session_start(&file_addr); + + for (i = 0; i < 100; i++) { + if (readsecs(file_addr, buffer, + sizeof (buffer) / SECTOR_SIZE) != sizeof (buffer)) { +#ifdef USE_LIBSCHILY + comerr(" Read error on old image %s\n", path); +#else + fprintf(stderr, " Read error on old image %s\n", path); + exit(10); +#endif + } + vdp = (struct iso_volume_descriptor *) buffer; + + if ((strncmp(vdp->id, ISO_STANDARD_ID, sizeof (vdp->id)) == 0) && + (isonum_711((unsigned char *) vdp->type) == ISO_VD_PRIMARY)) { + break; + } + file_addr += 1; + } + + if (i == 100) { + return (NULL); + } + pri = (struct iso_primary_descriptor *) vdp; + + /* Check the blocksize of the image to make sure it is compatible. */ + if (isonum_723((unsigned char *) pri->logical_block_size) != SECTOR_SIZE) { + errmsgno(EX_BAD, + "Previous session has incompatible sector size %d.\n", + isonum_723((unsigned char *) pri->logical_block_size)); + return (NULL); + } + if (isonum_723((unsigned char *) pri->volume_set_size) != 1) { + errmsgno(EX_BAD, + "Previous session has volume set size %d (must be 1).\n", + isonum_723((unsigned char *) pri->volume_set_size)); + return (NULL); + } + /* Get the location and size of the root directory. */ + rootp = (struct iso_directory_record *) + e_malloc(sizeof (struct iso_directory_record)); + + memcpy(rootp, pri->root_directory_record, sizeof (*rootp)); + + return (rootp); +} + +static void +merge_remaining_entries(struct directory *this_dir, + struct directory_entry **pnt, int n_orig) +{ + int i; + struct directory_entry *s_entry; + unsigned int ttbl_extent = 0; + unsigned int ttbl_index = 0; + char whole_path[PATH_MAX]; + + /* + * Whatever is leftover in the list needs to get merged back into the + * directory. + */ + for (i = 0; i < n_orig; i++) { + if (pnt[i] == NULL) { + continue; + } + if (pnt[i]->name != NULL && pnt[i]->whole_name == NULL) { + /* Set the name for this directory. */ + strcpy(whole_path, this_dir->de_name); + strcat(whole_path, SPATH_SEPARATOR); + strcat(whole_path, pnt[i]->name); + + pnt[i]->whole_name = strdup(whole_path); + } + if (pnt[i]->name != NULL && +/* strcmp(pnt[i]->name, "<translation table>") == 0 )*/ + strcmp(pnt[i]->name, trans_tbl) == 0) { + ttbl_extent = + isonum_733((unsigned char *)pnt[i]->isorec.extent); + ttbl_index = i; + continue; + } + + /* + * Skip directories for now - these need to be treated + * differently. + */ + if ((pnt[i]->isorec.flags[0] & ISO_DIRECTORY) != 0) { + /* + * FIXME - we need to insert this directory into the + * tree, so that the path tables we generate will be + * correct. + */ + if ((strcmp(pnt[i]->name, ".") == 0) || + (strcmp(pnt[i]->name, "..") == 0)) { + free_directory_entry(pnt[i]); + pnt[i] = NULL; + continue; + } else { + merge_old_directory_into_tree(pnt[i], this_dir); + } + } + pnt[i]->next = this_dir->contents; + pnt[i]->filedir = this_dir; + this_dir->contents = pnt[i]; + pnt[i] = NULL; + } + + + /* + * If we don't have an entry for the translation table, then don't + * bother trying to copy the starting extent over. Note that it is + * possible that if we are copying the entire directory, the entry for + * the translation table will have already been inserted into the + * linked list and removed from the old entries list, in which case we + * want to leave the extent number as it was before. + */ + if (ttbl_extent == 0) { + return; + } + /* + * Finally, check the directory we are creating to see whether there + * are any new entries in it. If there are not, we can reuse the same + * translation table. + */ + for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { + /* + * Don't care about '.' or '..'. They are never in the table + * anyways. + */ + if (s_entry->name != NULL && strcmp(s_entry->name, ".") == 0) { + continue; + } + if (s_entry->name != NULL && strcmp(s_entry->name, "..") == 0) { + continue; + } +/* if (strcmp(s_entry->name, "<translation table>") == 0)*/ + if (strcmp(s_entry->name, trans_tbl) == 0) { + continue; + } + if ((s_entry->de_flags & SAFE_TO_REUSE_TABLE_ENTRY) == 0) { + return; + } + } + + /* + * Locate the translation table, and re-use the same extent. It isn't + * clear that there should ever be one in there already so for now we + * try and muddle through the best we can. + */ + for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { +/* if (strcmp(s_entry->name, "<translation table>") == 0)*/ + if (strcmp(s_entry->name, trans_tbl) == 0) { + fprintf(stderr, "Should never get here\n"); + set_733(s_entry->isorec.extent, ttbl_extent); + return; + } + } + + pnt[ttbl_index]->next = this_dir->contents; + pnt[ttbl_index]->filedir = this_dir; + this_dir->contents = pnt[ttbl_index]; + pnt[ttbl_index] = NULL; +} + + +/* + * Here we have a case of a directory that has completely disappeared from + * the face of the earth on the tree we are mastering from. Go through and + * merge it into the tree, as well as everything beneath it. + * + * Note that if a directory has been moved for some reason, this will + * incorrectly pick it up and attempt to merge it back into the old + * location. FIXME(eric). + */ +static int +merge_old_directory_into_tree(struct directory_entry *dpnt, + struct directory *parent) +{ + struct directory_entry **contents = NULL; + int i; + int n_orig; + struct directory *this_dir, + *next_brother; + char whole_path[PATH_MAX]; + + this_dir = (struct directory *) e_malloc(sizeof (struct directory)); + memset(this_dir, 0, sizeof (struct directory)); + this_dir->next = NULL; + this_dir->subdir = NULL; + this_dir->self = dpnt; + this_dir->contents = NULL; + this_dir->size = 0; + this_dir->extent = 0; + this_dir->depth = parent->depth + 1; + this_dir->parent = parent; + if (!parent->subdir) + parent->subdir = this_dir; + else { + next_brother = parent->subdir; + while (next_brother->next) + next_brother = next_brother->next; + next_brother->next = this_dir; + } + + /* Set the name for this directory. */ + strcpy(whole_path, parent->de_name); + strcat(whole_path, SPATH_SEPARATOR); + strcat(whole_path, dpnt->name); + this_dir->de_name = strdup(whole_path); + this_dir->whole_name = strdup(whole_path); + + /* + * Now fill this directory using information from the previous session. + */ + contents = read_merging_directory(&dpnt->isorec, &n_orig); + /* + * Start by simply copying the '.', '..' and non-directory entries to + * this directory. Technically we could let merge_remaining_entries + * handle this, but it gets rather confused by the '.' and '..' entries + */ + for (i = 0; i < n_orig; i++) { + /* + * We can always reuse the TRANS.TBL in this particular case. + */ + contents[i]->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY; + + if (((contents[i]->isorec.flags[0] & ISO_DIRECTORY) != 0) && + (i >= 2)) { + continue; + } + /* If we have a directory, don't reuse the extent number. */ + if ((contents[i]->isorec.flags[0] & ISO_DIRECTORY) != 0) { + memset(contents[i]->isorec.extent, 0, 8); + + if (strcmp(contents[i]->name, ".") == 0) + this_dir->dir_flags |= DIR_HAS_DOT; + + if (strcmp(contents[i]->name, "..") == 0) + this_dir->dir_flags |= DIR_HAS_DOTDOT; + } + /* + * for regilar files, we do it here. + * If it has CL or RE attributes, remember its extent + */ + check_rr_relocation(contents[i]); + + /* + * Set the whole name for this file. + */ + strcpy(whole_path, this_dir->whole_name); + strcat(whole_path, SPATH_SEPARATOR); + strcat(whole_path, contents[i]->name); + + contents[i]->whole_name = strdup(whole_path); + + contents[i]->next = this_dir->contents; + contents[i]->filedir = this_dir; + this_dir->contents = contents[i]; + contents[i] = NULL; + } + + /* + * and for directories, we do it here. + * If it has CL or RE attributes, remember its extent + */ + check_rr_relocation(dpnt); + + /* + * Zero the extent number for ourselves. + */ + memset(dpnt->isorec.extent, 0, 8); + + /* + * Anything that is left are other subdirectories that need to be + * merged. + */ + merge_remaining_entries(this_dir, contents, n_orig); + free_mdinfo(contents, n_orig); +#if 0 + /* + * This is no longer required. The post-scan sort will handle all of + * this for us. + */ + sort_n_finish(this_dir); +#endif + + return (0); +} + + +char *cdrecord_data = NULL; + +int +get_session_start(int *file_addr) +{ + char *pnt; + +#ifdef CDRECORD_DETERMINES_FIRST_WRITABLE_ADDRESS + /* + * FIXME(eric). We need to coordinate with cdrecord to obtain the + * parameters. For now, we assume we are writing the 2nd session, so + * we start from the session that starts at 0. + */ + if (file_addr != NULL) + *file_addr = 16; + + /* + * We need to coordinate with cdrecord to get the next writable address + * from the device. Here is where we use it. + */ + session_start = last_extent = last_extent_written = cdrecord_result(); +#else + + if (file_addr != NULL) + *file_addr = 0L; + session_start = last_extent = last_extent_written = 0L; + if (check_session && cdrecord_data == NULL) + return (0); + + if (cdrecord_data == NULL) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Special parameters for cdrecord not specified with -C\n"); +#else + fprintf(stderr, + "Special parameters for cdrecord not specified with -C\n"); + exit(1); +#endif + } + /* + * Next try and find the ',' in there which delimits the two numbers. + */ + pnt = strchr(cdrecord_data, ','); + if (pnt == NULL) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Malformed cdrecord parameters\n"); +#else + fprintf(stderr, "Malformed cdrecord parameters\n"); + exit(1); +#endif + } + + *pnt = '\0'; + if (file_addr != NULL) { + *file_addr = atol(cdrecord_data); + } + pnt++; + + session_start = last_extent = last_extent_written = atol(pnt); + + pnt--; + *pnt = ','; + +#endif + return (0); +} + +/* + * 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 +merge_previous_session(struct directory *this_dir, + struct iso_directory_record *mrootp, + char *reloc_root, + char *reloc_old_root) +{ + struct directory_entry **orig_contents = NULL; + struct directory_entry *odpnt = NULL; + int n_orig; + struct directory_entry *s_entry; + int status; + int lstatus; + struct stat statbuf, + lstatbuf; + int retcode; + + /* skip leading slash */ + while (reloc_old_root && reloc_old_root[0] == PATH_SEPARATOR) { + reloc_old_root++; + } + while (reloc_root && reloc_root[0] == PATH_SEPARATOR) { + reloc_root++; + } + + /* + * Parse the same directory in the image that we are merging for + * multisession stuff. + */ + orig_contents = read_merging_directory(mrootp, &n_orig); + if (orig_contents == NULL) { + if (reloc_old_root) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Reading old session failed, cannot execute -old-root.\n"); +#else + fprintf(stderr, + "Reading old session failed, cannot execute -old-root.\n"); + exit(1); +#endif + } + return (0); + } + + if (reloc_old_root && reloc_old_root[0]) { + struct directory_entry **new_orig_contents = orig_contents; + int new_n_orig = n_orig; + + /* decend until we reach the original root */ + while (reloc_old_root[0]) { + int i; + char *next; + int last; + + for (next = reloc_old_root; *next && *next != PATH_SEPARATOR; next++); + if (*next) { + last = 0; + *next = 0; + next++; + } else { + last = 1; + } + while (*next == PATH_SEPARATOR) { + next++; + } + + for (i = 0; i < new_n_orig; i++) { + struct iso_directory_record subroot; + + if (new_orig_contents[i]->name != NULL && + strcmp(new_orig_contents[i]->name, reloc_old_root) != 0) { + /* Not the same name continue */ + continue; + } + /* + * enter directory, free old one only if not the top level, + * which is still needed + */ + subroot = new_orig_contents[i]->isorec; + if (new_orig_contents != orig_contents) { + free_mdinfo(new_orig_contents, new_n_orig); + } + new_orig_contents = read_merging_directory(&subroot, &new_n_orig); + + if (!new_orig_contents) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Reading directory %s in old session failed, cannot execute -old-root.\n", + reloc_old_root); +#else + fprintf(stderr, + "Reading directory %s in old session failed, cannot execute -old-root.\n", + reloc_old_root); + exit(1); +#endif + } + i = -1; + break; + } + + if (i == new_n_orig) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "-old-root (sub)directory %s not found in old session.\n", + reloc_old_root); +#else + fprintf(stderr, + "-old-root (sub)directory %s not found in old session.\n", + reloc_old_root); + exit(1); +#endif + } + + /* restore string, proceed to next sub directory */ + if (!last) { + reloc_old_root[strlen(reloc_old_root)] = PATH_SEPARATOR; + } + reloc_old_root = next; + } + + /* + * preserve the old session, skipping those dirs/files that are found again + * in the new root + */ + for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { + status = stat_filter(s_entry->whole_name, &statbuf); + lstatus = lstat_filter(s_entry->whole_name, &lstatbuf); + + /* + * check_prev_session() will search for s_entry and remove it from + * orig_contents if found + */ + retcode = check_prev_session(orig_contents, n_orig, s_entry, + &statbuf, &lstatbuf, NULL); + if (retcode == -1) + return (-1); + } + merge_remaining_entries(this_dir, orig_contents, n_orig); + + /* use new directory */ + free_mdinfo(orig_contents, n_orig); + orig_contents = new_orig_contents; + n_orig = new_n_orig; + + if (reloc_root && reloc_root[0]) { + /* also decend into new root before searching for files */ + this_dir = find_or_create_directory(this_dir, reloc_root, NULL, TRUE, NULL); + if (!this_dir) { + return (-1); + } + } + } + + + /* + * Now we scan the directory itself, and look at what is inside of it. + */ + for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { + status = stat_filter(s_entry->whole_name, &statbuf); + lstatus = lstat_filter(s_entry->whole_name, &lstatbuf); + + /* + * We always should create an entirely new directory tree + * whenever we generate a new session, unless there were + * *no* changes whatsoever to any of the directories, in which + * case it would be kind of pointless to generate a new + * session. + * I believe it is possible to rigorously prove that any change + * anywhere in the filesystem will force the entire tree to be + * regenerated because the modified directory will get a new + * extent number. Since each subdirectory of the changed + * directory has a '..' entry, all of them will need to be + * rewritten too, and since the parent directory of the + * modified directory will have an extent pointer to the + * directory it too will need to be rewritten. Thus we will + * never be able to reuse any directory information when + * writing new sessions. + * + * We still check the previous session so we can mark off the + * equivalent entry in the list we got from the original disc, + * however. + */ + + /* + * The check_prev_session function looks for an identical + * entry in the previous session. If we see it, then we copy + * the extent number to s_entry, and cross it off the list. + * It returns 2 if it's a directory + */ + retcode = check_prev_session(orig_contents, n_orig, s_entry, + &statbuf, &lstatbuf, &odpnt); + if (retcode == -1) + return (-1); + + if (retcode == 2 && odpnt != NULL) { + int dflag; + + if (strcmp(s_entry->name, ".") != 0 && + strcmp(s_entry->name, "..") != 0) { + struct directory *child; + + /* + * XXX It seems that the tree that has been + * XXX read from the previous session does not + * XXX carry whole_name entries. We provide a + * XXX hack in + * XXX multi.c:find_or_create_directory() + * XXX that should be removed when a + * XXX reasonable method could be found. + */ + child = find_or_create_directory(this_dir, + s_entry->whole_name, + s_entry, 1, NULL); + dflag = merge_previous_session(child, + &odpnt->isorec, + NULL, reloc_old_root); + if (dflag == -1) { + return (-1); + } + free(odpnt); + odpnt = NULL; + } + } + } + + if (!reloc_old_root) { + /* + * Whatever is left over, are things which are no longer in the tree on + * disk. We need to also merge these into the tree. + */ + merge_remaining_entries(this_dir, orig_contents, n_orig); + } + free_mdinfo(orig_contents, n_orig); + return (1); +} + +/* + * This code deals with relocated directories which may exist + * in the previous session. + */ +struct dir_extent_link { + unsigned int extent; + struct directory_entry *de; + struct dir_extent_link *next; +}; + +static struct dir_extent_link *cl_dirs = NULL; +static struct dir_extent_link *re_dirs = NULL; + +static void +check_rr_relocation(struct directory_entry *de) +{ + unsigned char sector[SECTOR_SIZE]; + unsigned char *pnt = de->rr_attributes; + int len = de->rr_attr_size; + int cont_extent = 0, + cont_offset = 0, + cont_size = 0; + + pnt = parse_xa(pnt, &len, /* dpnt */ 0); + while (len >= 4) { + if (pnt[3] != 1 && pnt[3] != 2) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "**BAD RRVERSION (%d) for %c%c\n", pnt[3], pnt[0], pnt[1]); +#else + fprintf(stderr, "**BAD RRVERSION (%d) for %c%c\n", pnt[3], pnt[0], pnt[1]); +#endif + } + if (strncmp((char *) pnt, "CL", 2) == 0) { + struct dir_extent_link *dlink = e_malloc(sizeof (*dlink)); + + dlink->extent = isonum_733(pnt + 4); + dlink->de = de; + dlink->next = cl_dirs; + cl_dirs = dlink; + + } else if (strncmp((char *) pnt, "RE", 2) == 0) { + struct dir_extent_link *dlink = e_malloc(sizeof (*dlink)); + + dlink->extent = de->starting_block; + dlink->de = de; + dlink->next = re_dirs; + re_dirs = dlink; + + } else if (strncmp((char *) pnt, "CE", 2) == 0) { + cont_extent = isonum_733(pnt + 4); + cont_offset = isonum_733(pnt + 12); + cont_size = isonum_733(pnt + 20); + + } else if (strncmp((char *) pnt, "ST", 2) == 0) { + len = pnt[2]; + } + len -= pnt[2]; + pnt += pnt[2]; + if (len <= 3 && cont_extent) { + /* ??? What if cont_offset+cont_size > SECTOR_SIZE */ + readsecs(cont_extent, sector, 1); + pnt = sector + cont_offset; + len = cont_size; + cont_extent = cont_offset = cont_size = 0; + } + } + +} + +void +match_cl_re_entries() +{ + struct dir_extent_link *re = re_dirs; + + /* for each relocated directory */ + for (; re; re = re->next) { + struct dir_extent_link *cl = cl_dirs; + + for (; cl; cl = cl->next) { + /* find a place where it was relocated from */ + if (cl->extent == re->extent) { + /* set link to that place */ + re->de->parent_rec = cl->de; + re->de->filedir = cl->de->filedir; + + /* + * see if it is in rr_moved + */ + if (reloc_dir != NULL) { + struct directory_entry *rr_moved_e = reloc_dir->contents; + + for (; rr_moved_e; rr_moved_e = rr_moved_e->next) { + /* yes it is */ + if (re->de == rr_moved_e) { + /* forget it */ + re->de = NULL; + } + } + } + break; + } + } + } +} + +void +finish_cl_pl_for_prev_session() +{ + struct dir_extent_link *re = re_dirs; + + /* for those that were relocated, but NOT to rr_moved */ + re = re_dirs; + for (; re; re = re->next) { + if (re->de != NULL) { + /* + * here we have hypothetical case when previous session + * was not created by genisoimage and contains relocations + */ + struct directory_entry *s_entry = re->de; + struct directory_entry *s_entry1; + struct directory *d_entry = reloc_dir->subdir; + + /* do the same as finish_cl_pl_entries */ + if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { + continue; + } + while (d_entry) { + if (d_entry->self == s_entry) + break; + d_entry = d_entry->next; + } + if (!d_entry) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Unable to locate directory parent\n"); +#else + fprintf(stderr, "Unable to locate directory parent\n"); + exit(1); +#endif + } + + if (s_entry->filedir != NULL && s_entry->parent_rec != NULL) { + char *rr_attr; + + /* + * First fix the PL pointer in the directory in the + * rr_reloc dir + */ + s_entry1 = d_entry->contents->next; + rr_attr = find_rr_attribute(s_entry1->rr_attributes, + s_entry1->total_rr_attr_size, "PL"); + if (rr_attr != NULL) + set_733(rr_attr + 4, s_entry->filedir->extent); + + /* Now fix the CL pointer */ + s_entry1 = s_entry->parent_rec; + + rr_attr = find_rr_attribute(s_entry1->rr_attributes, + s_entry1->total_rr_attr_size, "CL"); + if (rr_attr != NULL) + set_733(rr_attr + 4, d_entry->extent); + } + } + } + /* free memory */ + re = re_dirs; + while (re) { + struct dir_extent_link *next = re->next; + + free(re); + re = next; + } + re = cl_dirs; + while (re) { + struct dir_extent_link *next = re->next; + + free(re); + re = next; + } +} diff --git a/genisoimage/name.c b/genisoimage/name.c new file mode 100644 index 0000000..c2faeb6 --- /dev/null +++ b/genisoimage/name.c @@ -0,0 +1,531 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)name.c 1.28 04/03/05 joerg */ +/* + * File name.c - map full Unix file names to unique 8.3 names that + * would be valid on DOS. + * + * + * Written by Eric Youngdale (1993). + * Almost totally rewritten by J. Schilling (2000). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * Copyright (c) 1999,2000 J. Schilling + * + * 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 <mconfig.h> +#include "genisoimage.h" +#include <standard.h> +#include <schily.h> +#include <ctype.h> + +void iso9660_check(struct iso_directory_record *idr, + struct directory_entry *ndr); +int iso9660_file_length(const char *name, + struct directory_entry *sresult, + int dirflag); + +void +iso9660_check(struct iso_directory_record *idr, + struct directory_entry *ndr) +{ + int nlen; + char schar; + char *p; + char *np; + + nlen = idr->name_len[0]; + schar = idr->name[nlen]; + + if (nlen == 1 && (idr->name[0] == '\0' || idr->name[0] == '\001')) + return; + + idr->name[nlen] = '\0'; /* Make it null terminated */ + if ((p = strrchr(idr->name, ';')) != NULL) { + *p = '\0'; /* Strip off old version # */ + } + iso9660_file_length(idr->name, ndr, + (idr->flags[0] & ISO_DIRECTORY) != 0); + + if ((np = strrchr(ndr->isorec.name, ';')) != NULL) { + *np = '\0'; /* Strip off new version # */ + } + if (strcmp(idr->name, ndr->isorec.name)) { + if (p) + *p = ';'; /* Restore old version # */ + if (np) + *np = ';'; /* Restore new version # */ + errmsgno(EX_BAD, + "Old session has illegal name '%.*s' length %d\n", + idr->name_len[0], + idr->name, + idr->name_len[0]); + errmsgno(EX_BAD, + "New session will use name '%s'\n", + ndr->isorec.name); + } + if (p) + *p = ';'; /* Restore old version # */ + if (np) + *np = ';'; /* Restore new version # */ + idr->name[nlen] = schar; /* Restore old iso record*/ +} + +/* + * Function: iso9660_file_length + * + * Purpose: Map file name to 8.3 format, return length + * of result. + * + * Arguments: name file name we need to map. + * sresult directory entry structure to contain mapped name. + * dirflag flag indicating whether this is a directory or not. + * + * Note: name being const * is a bug introduced by Eric but hard to + * fix without going through the whole source. + */ +int +iso9660_file_length(const char *name /* Not really const !!! */, + struct directory_entry *sresult, int dirflag) +{ + char c; + char *cp; + int before_dot = 8; + int after_dot = 3; + int chars_after_dot = 0; + int chars_before_dot = 0; + int current_length = 0; + int extra = 0; + int ignore = 0; + char *last_dot; + const char *pnt; + int priority = 32767; + char *result; + int ochars_after_dot; + int ochars_before_dot; + int seen_dot = 0; + int seen_semic = 0; + int tildes = 0; + + result = sresult->isorec.name; + + if (sresult->priority) + priority = sresult->priority; + + /* + * For the '.' entry, generate the correct record, and return 1 for + * the length. + */ + if (strcmp(name, ".") == 0) { + *result = 0; + return (1); + } + /* + * For the '..' entry, generate the correct record, and return 1 + * for the length. + */ + if (strcmp(name, "..") == 0) { + *result++ = 1; + *result++ = 0; + return (1); + } + /* + * Now scan the directory one character at a time, and figure out + * what to do. + */ + pnt = name; + + /* + * Find the '.' that we intend to use for the extension. + * Usually this is the last dot, but if we have . followed by nothing + * or a ~, we would consider this to be unsatisfactory, and we keep + * searching. + */ + last_dot = strrchr(pnt, '.'); + if ((last_dot != NULL) && + ((last_dot[1] == '~') || (last_dot[1] == '\0'))) { + cp = last_dot; + *cp = '\0'; + last_dot = strrchr(pnt, '.'); + *cp = '.'; + /* + * If we found no better '.' back up to the last match. + */ + if (last_dot == NULL) + last_dot = cp; + } + + if (last_dot != NULL) { + ochars_after_dot = strlen(last_dot); /* dot counts */ + ochars_before_dot = last_dot - pnt; + } else { + ochars_before_dot = 128; + ochars_after_dot = 0; + } + /* + * If we have full names, the names we generate will not work + * on a DOS machine, since they are not guaranteed to be 8.3. + * Nonetheless, in many cases this is a useful option. We + * still only allow one '.' character in the name, however. + */ + if (full_iso9660_filenames || iso9660_level > 1) { + before_dot = iso9660_namelen; + after_dot = before_dot - 1; + + if (!dirflag) { + if (ochars_after_dot > ((iso9660_namelen/2)+1)) { + /* + * The minimum number of characters before + * the dot is 3 to allow renaming. + * Let us allow to have 15 characters after + * dot to give more rational filenames. + */ + before_dot = iso9660_namelen/2; + after_dot = ochars_after_dot; + } else { + before_dot -= ochars_after_dot; /* dot counts */ + after_dot = ochars_after_dot; + } + } + } + + while (*pnt) { +#ifdef VMS + if (strcmp(pnt, ".DIR;1") == 0) { + break; + } +#endif + +#ifdef Eric_code_does_not_work + /* + * XXX If we make this code active we get corrupted direcrory + * XXX trees with infinite loops. + */ + /* + * This character indicates a Unix style of backup file + * generated by some editors. Lower the priority of the file. + */ + if (iso_translate && *pnt == '#') { + priority = 1; + pnt++; + continue; + } + /* + * This character indicates a Unix style of backup file + * generated by some editors. Lower the priority of the file. + */ + if (iso_translate && *pnt == '~') { + priority = 1; + tildes++; + pnt++; + continue; + } +#endif + /* + * This might come up if we had some joker already try and put + * iso9660 version numbers into the file names. This would be + * a silly thing to do on a Unix box, but we check for it + * anyways. If we see this, then we don't have to add our own + * version number at the end. UNLESS the ';' is part of the + * filename and no valid version number is following. + */ + if (use_fileversion && *pnt == ';' && seen_dot) { + /* + * Check if a valid version number follows. + * The maximum valid version number is 32767. + */ + for (c = 1, cp = (char *)&pnt[1]; c < 6 && *cp; c++, cp++) { + if (*cp < '0' || *cp > '9') + break; + } + if (c <= 6 && *cp == '\0' && atoi(&pnt[1]) <= 32767) + seen_semic++; + } + /* + * If we have a name with multiple '.' characters, we ignore + * everything after we have gotten the extension. + */ + if (ignore) { + pnt++; + continue; + } + if (current_length >= iso9660_namelen) { +#ifdef nono + /* + * Does not work as we may truncate before the dot. + */ + fprintf(stderr, "Truncating '%s' to '%.*s'.\n", + name, + current_length, sresult->isorec.name); + ignore++; +#endif + pnt++; + continue; + } + /* Spin past any iso9660 version number we might have. */ + if (seen_semic) { + if (seen_semic == 1) { + seen_semic++; + *result++ = ';'; + } + if (*pnt >= '0' && *pnt <= '9') { + *result++ = *pnt; + } + extra++; + pnt++; + continue; + } + + if (*pnt == '.') { + if (!allow_multidot) { + if (strcmp(pnt, ".tar.gz") == 0) + pnt = last_dot = ".tgz"; + if (strcmp(pnt, ".ps.gz") == 0) + pnt = last_dot = ".psz"; + } + + if (!chars_before_dot && !allow_leading_dots) { + /* + * DOS can't read files with dot first + */ + chars_before_dot++; + *result++ = '_'; /* Substitute underscore */ + + } else if (pnt == last_dot) { + if (seen_dot) { + ignore++; + continue; + } + *result++ = '.'; + seen_dot++; + } else if (allow_multidot) { + if (chars_before_dot < before_dot) { + chars_before_dot++; + *result++ = '.'; + } + } else { + /* + * If this isn't the dot that we use + * for the extension, then change the + * character into a '_' instead. + */ + if (chars_before_dot < before_dot) { + chars_before_dot++; + *result++ = '_'; + } + } + } else { + if ((seen_dot && (chars_after_dot < after_dot) && + ++chars_after_dot) || + (!seen_dot && (chars_before_dot < before_dot) && + ++chars_before_dot)) { + + c = *pnt; + if (c & 0x80) { + /* + * We allow 8 bit chars if -iso-level + * is at least 4 + * + * XXX We should check if the output + * XXX character set is a 7 Bit ASCI + * extension. + */ + if (iso9660_level >= 4) { + c = conv_charset(c, in_nls, out_nls); + } else { + c = '_'; + } + } else if (!allow_lowercase) { + c = islower((unsigned char)c) ? + toupper((unsigned char)c) : c; + } + if (relaxed_filenames) { + /* + * Here we allow a more relaxed syntax. + */ + if (c == '/') + c = '_'; + *result++ = c; + } else switch (c) { + /* + * Dos style filenames. + * We really restrict the names here. + */ + + default: + *result++ = c; + break; + + /* + * Descriptions of DOS's 'Parse Filename' + * (function 29H) describes V1 and V2.0+ + * separator and terminator characters. These + * characters in a DOS name make the file + * visible but un-manipulable (all useful + * operations error off. + */ + /* separators */ + case '+': + case '=': + case '%': /* not legal DOS */ + /* filename */ + case ':': + case ';': /* already handled */ + case '.': /* already handled */ + case ',': /* already handled */ + case '\t': + case ' ': + /* V1 only separators */ + case '/': + case '"': + case '[': + case ']': + /* terminators */ + case '>': + case '<': + case '|': + /* + * Other characters that are not valid ISO-9660 + * characters. + */ + case '!': +/* case '#':*/ + case '$': + case '&': + case '\'': + case '(': + case ')': + case '*': +/* case '-':*/ + case '?': + case '@': + case '\\': + case '^': + case '`': + case '{': + case '}': +/* case '~':*/ + /* + * All characters below 32 (space) are not + * allowed too. + */ + case 1: case 2: case 3: case 4: + case 5: case 6: case 7: case 8: + /* case 9: */ + case 10: case 11: case 12: + case 13: case 14: case 15: + case 16: case 17: case 18: + case 19: case 20: case 21: + case 22: case 23: case 24: + case 25: case 26: case 27: + case 28: case 29: case 30: + case 31: + + /* + * Hmm - what to do here? Skip? Win95 + * looks like it substitutes '_' + */ + *result++ = '_'; + break; + + case '#': + case '-': + case '~': + /* + * Check if we should allow these + * illegal characters used by + * Microsoft. + */ + if (iso_translate) + *result++ = '_'; + else + *result++ = c; + break; + } /* switch (*pnt) */ + } else { /* if (chars_{after,before}_dot) ... */ + pnt++; + continue; + } + } /* else *pnt == '.' */ + current_length++; + pnt++; + } /* while (*pnt) */ + + /* + * OK, that wraps up the scan of the name. Now tidy up a few other + * things. + * Look for emacs style of numbered backups, like foo.c.~3~. If we + * see this, convert the version number into the priority number. + * In case of name conflicts, this is what would end up being used as + * the 'extension'. + */ + if (tildes == 2) { + int prio1 = 0; + + pnt = name; + while (*pnt && *pnt != '~') { + pnt++; + } + if (*pnt) { + pnt++; + } + while (*pnt && *pnt != '~') { + prio1 = 10 * prio1 + *pnt - '0'; + pnt++; + } + priority = prio1; + } + /* + * If this is not a directory, force a '.' in case we haven't seen one, + * and add a version number if we haven't seen one of those either. + */ + if (!dirflag) { + if (!seen_dot && !omit_period) { + if (chars_before_dot >= (iso9660_namelen-1)) { + chars_before_dot--; + result--; + } + *result++ = '.'; + extra++; + } + if (!omit_version_number && !seen_semic) { + *result++ = ';'; + *result++ = '1'; + extra += 2; + } + } + *result++ = 0; + sresult->priority = priority; + +/*#define DEBBUG*/ +#ifdef DEBBUG + fprintf(stderr, "NAME: '%s'\n", sresult->isorec.name); + fprintf(stderr, "chars_before_dot %d chars_after_dot %d seen_dot %d extra %d\n", + chars_before_dot, chars_after_dot, seen_dot, extra); +#endif + return (chars_before_dot + chars_after_dot + seen_dot + extra); +} diff --git a/genisoimage/rock.c b/genisoimage/rock.c new file mode 100644 index 0000000..7565bae --- /dev/null +++ b/genisoimage/rock.c @@ -0,0 +1,864 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)rock.c 1.43 05/05/01 joerg */ +/* + * File rock.c - generate RRIP records for iso9660 filesystems. + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * Copyright (c) 1999,2000-2003 J. Schilling + * + * 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 <mconfig.h> +#include "genisoimage.h" +#include <device.h> +#include <schily.h> + +#define SU_VERSION 1 + +#define SL_ROOT 8 +#define SL_PARENT 4 +#define SL_CURRENT 2 +#define SL_CONTINUE 1 + +#define CE_SIZE 28 /* SUSP Continuation aerea */ +#define CL_SIZE 12 /* RR Child Link for deep dir relocation */ +#define ER_SIZE 8 /* RR Extension record for RR signature */ +#define NM_SIZE 5 /* RR Real name */ +#define PL_SIZE 12 /* RR Paren Link for deep dir relocation */ +#define PN_SIZE 20 /* RR POSIX device modes (Major/Minor) */ +#define PX_SIZE 36 /* RR POSIX Extensions (mode/nlink(uid/gid) */ +#define RE_SIZE 4 /* RR Relocated directory */ +#define RR_SIZE 5 /* RR RR Signature in every file */ +#define SL_SIZE 20 /* RR Symlink */ +#define ZF_SIZE 16 /* RR* Linux compression extension */ +#ifdef APPLE_HYB +#define AA_SIZE 14 /* size of Apple extension */ +#endif /* APPLE_HYB */ +#if defined(__QNX__) && !defined(__QNXNTO__) /* Not on Neutrino! never OK? */ +#define TF_SIZE (5 + 4 * 7) /* RR Time field */ +#else +#define TF_SIZE (5 + 3 * 7) +#endif + +static void rstrncpy(char *t, char *f, int c, + struct unls_table *inls, + struct unls_table *onls); +static void add_CE_entry(char *field, int line); +static int gen_xa_attr(mode_t attr); +static void gen_xa(struct stat *lstatbuf); +int generate_xa_rr_attributes(char *whole_name, char *name, + struct directory_entry *s_entry, + struct stat *statbuf, + struct stat *lstatbuf, + int deep_opt); +char *generate_rr_extension_record(char *id, char *descriptor, char *source, + int *size); +/* + * 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 RR_CUR_USE (CE_SIZE + currlen + (ipnt - recstart)) + +#define MAYBE_ADD_CE_ENTRY(BYTES) \ + (((int)(BYTES)) + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0) + +/* + * Buffer to build RR attributes + */ +static Uchar Rock[16384]; +static Uchar symlink_buff[PATH_MAX+1]; +static int ipnt = 0; /* Current "write" offset in Rock[] */ +static int recstart = 0; /* Start offset in Rock[] for this area */ +static int currlen = 0; /* # of non RR bytes used in this area */ +static int mainrec = 0; /* # of RR bytes use in main dir area */ +static int reclimit; /* Max. # of bytes usable in this area */ + +/* if we are using converted filenames, we don't want the '/' character */ +static void +rstrncpy(char *t, char *f, int c, struct unls_table *inls, + struct unls_table *onls) +{ + while (c-- && *f) { + *t = conv_charset(*f, inls, onls); + if (*t == '/') { + *t = '_'; + } + t++; + f++; + } +} + +static void +add_CE_entry(char *field, int line) +{ + if (MAYBE_ADD_CE_ENTRY(0)) { + errmsgno(EX_BAD, + "Panic: no space, cannot add RR CE entry (%d bytes mising) for %s line %d.\n", + (CE_SIZE + currlen + (ipnt - recstart) - reclimit), + field, line); + errmsgno(EX_BAD, "currlen: %d ipnt: %d, recstart: %d\n", + currlen, ipnt, recstart); + errmsgno(EX_BAD, "Send bug report to the maintainer.\n"); + comerrno(EX_BAD, "Aborting.\n"); + } + + 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 */ +} + +static int +gen_xa_attr(mode_t attr) +{ + int ret = 0; + + if (attr & S_IRUSR) + ret |= XA_O_READ; + if (attr & S_IXUSR) + ret |= XA_O_EXEC; + + if (attr & S_IRGRP) + ret |= XA_G_READ; + if (attr & S_IXGRP) + ret |= XA_G_EXEC; + + if (attr & S_IROTH) + ret |= XA_W_READ; + if (attr & S_IXOTH) + ret |= XA_W_EXEC; + + ret |= XA_FORM1; + + if (S_ISDIR(attr)) + ret |= XA_DIR; + + return (ret); +} + +static void +gen_xa(struct stat *lstatbuf) +{ + /* + * Group ID + */ + set_722((char *) Rock + ipnt, lstatbuf->st_gid); + ipnt += 2; + /* + * User ID + */ + set_722((char *) Rock + ipnt, lstatbuf->st_uid); + ipnt += 2; + /* + * Attributes + */ + set_722((char *) Rock + ipnt, gen_xa_attr(lstatbuf->st_mode)); + ipnt += 2; + + Rock[ipnt++] = 'X'; /* XA Signature */ + Rock[ipnt++] = 'A'; + Rock[ipnt++] = 0; /* File number (we always use '0' */ + + Rock[ipnt++] = 0; /* Reserved (5 Byte) */ + Rock[ipnt++] = 0; + Rock[ipnt++] = 0; + Rock[ipnt++] = 0; + Rock[ipnt++] = 0; + +} + +int +generate_xa_rr_attributes(char *whole_name, char *name, + struct directory_entry *s_entry, + struct stat *statbuf, + struct stat *lstatbuf, + int deep_opt) +{ + int flagpos; + int flagval; + int need_ce; + + statbuf = statbuf; /* this shuts up unreferenced compiler */ + /* warnings */ + mainrec = recstart = ipnt = 0; + + if (use_XA) { + gen_xa(lstatbuf); + } + +/* reclimit = 0xf8; XXX we now use 254 == 0xfe */ + reclimit = MAX_ISODIR; + + /* no need to fill in the RR stuff if we won't see the file */ + if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) + return (0); + + /* + * Obtain the amount of space that is currently used for the directory + * record. We may safely use the current name length; because if name + * confilcts force us to change the ISO-9660 name later, the name will + * never become longer than now. + */ + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { + s_entry->isorec.name_len[0] = 1; + } else { + s_entry->isorec.name_len[0] = strlen(s_entry->isorec.name); + } + currlen = s_entry->isorec.length[0] = s_entry->isorec.name_len[0] + + offsetof(struct iso_directory_record, name[0]); + if (currlen & 1) + s_entry->isorec.length[0] = ++currlen; + + if (currlen < 33+37) { + /* + * If the ISO-9660 name length is less than 37, we may use + * ISO-9660:1988 name rules and for this reason, the name len + * may later increase from adding e.g. ".;1"; in this case + * just use the upper limit. + */ + currlen = 33+37; + } + +#ifdef APPLE_HYB + /* if we have regular file, then add Apple extensions */ + if (S_ISREG(lstatbuf->st_mode) && apple_ext && s_entry->hfs_ent) { + if (MAYBE_ADD_CE_ENTRY(AA_SIZE)) + add_CE_entry("AA", __LINE__); + Rock[ipnt++] = 'A'; /* AppleSignature */ + Rock[ipnt++] = 'A'; + Rock[ipnt++] = AA_SIZE; /* includes AppleSignature bytes */ + Rock[ipnt++] = 0x02; /* SystemUseID */ + Rock[ipnt++] = s_entry->hfs_ent->u.file.type[0]; + Rock[ipnt++] = s_entry->hfs_ent->u.file.type[1]; + Rock[ipnt++] = s_entry->hfs_ent->u.file.type[2]; + Rock[ipnt++] = s_entry->hfs_ent->u.file.type[3]; + Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[0]; + Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[1]; + Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[2]; + Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[3]; + Rock[ipnt++] = (s_entry->hfs_ent->fdflags >> 8) & 0xff; + Rock[ipnt++] = s_entry->hfs_ent->fdflags & 0xff; + } +#endif /* APPLE_HYB */ + + if (!use_RockRidge) + goto xa_only; + + /* Identify that we are using the SUSP protocol */ + if (deep_opt & NEED_SP) { + /* + * We may not use a CE record here but we never will need to + * do so, as this SP record is only used for the "." entry + * of the root directory. + */ + Rock[ipnt++] = 'S'; + Rock[ipnt++] = 'P'; + Rock[ipnt++] = 7; + Rock[ipnt++] = SU_VERSION; + Rock[ipnt++] = 0xbe; + Rock[ipnt++] = 0xef; + if (use_XA) + Rock[ipnt++] = sizeof (struct iso_xa_dir_record); + else + Rock[ipnt++] = 0; + } + + /* First build the posix name field */ + if (MAYBE_ADD_CE_ENTRY(RR_SIZE)) + add_CE_entry("RR", __LINE__); + 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; /* Remaining name length */ + int use; /* Current name part used */ + +#ifdef APPLE_HYB + /* use the HFS name if it exists */ + if (USE_MAC_NAME(s_entry)) { + remain = strlen(s_entry->hfs_ent->name); + npnt = s_entry->hfs_ent->name; + } else { +#endif /* APPLE_HYB */ + + remain = strlen(name); + npnt = name; +#ifdef APPLE_HYB + } +#endif /* APPLE_HYB */ + + if (MAYBE_ADD_CE_ENTRY(NM_SIZE+1)) + add_CE_entry("NM", __LINE__); + while (remain) { + use = remain; + need_ce = 0; + /* Can we fit this SUSP and a CE entry? */ + if (MAYBE_ADD_CE_ENTRY(NM_SIZE+use)) { + use = reclimit - NM_SIZE - RR_CUR_USE; + need_ce++; + } + /* Only room for 256 per SUSP field */ + if (use > 0xf8) { + use = 0xf8; + need_ce++; + } + if (use < 0) { + comerrno(EX_BAD, + "Negative RR name length residual: %d\n", + use); + } + + /* 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); + + /* convert charsets as required */ +#ifdef APPLE_HYB + if (USE_MAC_NAME(s_entry)) + rstrncpy((char *) &Rock[ipnt], npnt, use, + hfs_inls, out_nls); + else +#endif /* APPLE_HYB */ + rstrncpy((char *) &Rock[ipnt], npnt, use, + in_nls, out_nls); + npnt += use; + ipnt += use; + remain -= use; + if (remain && need_ce) + add_CE_entry("NM", __LINE__); + } + } + + /* Add the posix modes */ + if (MAYBE_ADD_CE_ENTRY(PX_SIZE)) + add_CE_entry("PX", __LINE__); + 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 */ +#if defined(S_IFCHR) || defined(S_IFBLK) + /* + * The code in this if statement used to be #ifdef'd with NON_UNIXFS. + * But as statdefs.h always provides the macros S_ISCHR() & S_ISBLK() + * and device.h always provides major()/minor() it is not needed + * anymore. + */ + if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) { + if (MAYBE_ADD_CE_ENTRY(PN_SIZE)) + add_CE_entry("PN", __LINE__); + Rock[ipnt++] = 'P'; + Rock[ipnt++] = 'N'; + Rock[ipnt++] = PN_SIZE; + Rock[ipnt++] = SU_VERSION; + flagval |= (1 << 1); +#if 1 + /* This is the new and only code which uses <device.h> */ + set_733((char *) Rock + ipnt, major(lstatbuf->st_rdev)); + ipnt += 8; + set_733((char *) Rock + ipnt, minor(lstatbuf->st_rdev)); + ipnt += 8; +#else + /* + * If we don't have sysmacros.h, then we have to guess as to + * how best to pick apart the device number for major/minor. + * Note: this may very well be wrong for many systems, so it + * is always best to use the major/minor macros if the system + * supports it. + */ + if (sizeof (dev_t) <= 2) { + set_733((char *)Rock + ipnt, (lstatbuf->st_rdev >> 8)); + ipnt += 8; + set_733((char *)Rock + ipnt, lstatbuf->st_rdev & 0xff); + ipnt += 8; + } else if (sizeof (dev_t) <= 4) { + set_733((char *)Rock + ipnt, + (lstatbuf->st_rdev >> 8) >> 8); + ipnt += 8; + set_733((char *)Rock + ipnt, + lstatbuf->st_rdev & 0xffff); + ipnt += 8; + } else { + set_733((char *)Rock + ipnt, + (lstatbuf->st_rdev >> 16)>>16); + ipnt += 8; + set_733((char *)Rock + ipnt, lstatbuf->st_rdev); + ipnt += 8; + } +#endif + } +#endif /* defined(S_IFCHR) || defined(S_IFBLK) */ + + /* Check for and symbolic links. VMS does not have these. */ +#ifdef S_IFLNK + if (S_ISLNK(lstatbuf->st_mode)) { + int lenpos; + int lenval; + int j0; + int j1; + int nchar; + Uchar *cpnt; + Uchar *cpnt1; + +#ifdef HAVE_READLINK + nchar = readlink(whole_name, (char *)symlink_buff, + sizeof (symlink_buff)-1); +#else + nchar = -1; +#endif /* HAVE_READLINK */ + symlink_buff[nchar < 0 ? 0 : nchar] = 0; + nchar = strlen((char *) symlink_buff); + set_733(s_entry->isorec.size, 0); + cpnt = &symlink_buff[0]; + flagval |= (1 << 2); + + if (!split_SL_field) { + int sl_bytes = 0; + + for (cpnt1 = cpnt; *cpnt1 != '\0'; cpnt1++) { + if (*cpnt1 == '/') { + sl_bytes += 4; + } else { + sl_bytes += 1; + } + } + if (sl_bytes > 250) { + /* + * the symbolic link won't fit into one + * SL System Use Field print an error message + * and continue with splited one + */ + fprintf(stderr, + "symbolic link ``%s'' to long for one SL System Use Field, splitting", + cpnt); + } + if (MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes)) + add_CE_entry("SL+", __LINE__); + } + while (nchar) { + if (MAYBE_ADD_CE_ENTRY(SL_SIZE)) + add_CE_entry("SL", __LINE__); + 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 = (Uchar *) + 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("SL-parent", __LINE__); + if (cpnt1) { + *cpnt1 = '/'; + nchar++; + /* + * A kluge so that we + * can restart properly + */ + cpnt1 = NULL; + } + break; + } + 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("SL-current", __LINE__); + if (cpnt1) { + *cpnt1 = '/'; + nchar++; + /* + * A kluge so that we + * can restart properly + */ + cpnt1 = NULL; + } + break; + } + 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("SL-root", __LINE__); + if (cpnt1) { + *cpnt1 = '/'; + nchar++; + /* + * A kluge so that we + * can restart properly + */ + cpnt1 = NULL; + } + break; + } + 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 (split_SL_component ? + MAYBE_ADD_CE_ENTRY(6) : + MAYBE_ADD_CE_ENTRY(6 + strlen((char *) cpnt))) { + add_CE_entry("SL++", __LINE__); + if (cpnt1) { + *cpnt1 = '/'; + nchar++; + /* + * A kluge so that we + * can restart properly + */ + cpnt1 = NULL; + } + break; + } + j0 = strlen((char *) cpnt); + while (j0) { + j1 = j0; + if (j1 > 0xf8) + j1 = 0xf8; + need_ce = 0; + if (j1 + currlen + 2 + CE_SIZE + + (ipnt - recstart) > + reclimit) { + + j1 = reclimit - + (currlen + 2) - + 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; + /* + * Number we processed + * this time + */ + nchar -= j1; + j0 -= j1; + if (need_ce) { + add_CE_entry( + "SL-path-split", + __LINE__); + if (cpnt1) { + *cpnt1 = '/'; + nchar++; + /* + * A kluge so + * that we can + * restart + * properly + */ + cpnt1 = NULL; + } + break; + } + } + } + if (cpnt1) { + cpnt = cpnt1 + 1; + } else + break; + } + Rock[lenpos] = lenval; + if (nchar) { + /* We need another SL entry */ + Rock[lenpos + 2] = SL_CONTINUE; + } + } /* while nchar */ + } /* Is a symbolic link */ +#endif /* S_IFLNK */ + + /* Add in the Rock Ridge TF time field */ + if (MAYBE_ADD_CE_ENTRY(TF_SIZE)) + add_CE_entry("TF", __LINE__); + Rock[ipnt++] = 'T'; + Rock[ipnt++] = 'F'; + Rock[ipnt++] = TF_SIZE; + Rock[ipnt++] = SU_VERSION; +#if defined(__QNX__) && !defined(__QNXNTO__) /* Not on Neutrino! never OK? */ + Rock[ipnt++] = 0x0f; +#else + Rock[ipnt++] = 0x0e; +#endif + flagval |= (1 << 7); + +#if defined(__QNX__) && !defined(__QNXNTO__) /* Not on Neutrino! never OK? */ + 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 (relocated dir) field */ + if (deep_opt & NEED_RE) { + if (MAYBE_ADD_CE_ENTRY(RE_SIZE)) + add_CE_entry("RE", __LINE__); + 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("PL", __LINE__); + 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("CL", __LINE__); + 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 (and only if) it is actually a compressed file! + * This relies only on magic number, but it should in general not + * be an issue since if you're using -z odds are most of your + * files are already compressed. + * + * In the future it would be nice if genisoimage actually did the + * compression. + */ + if (transparent_compression && S_ISREG(lstatbuf->st_mode)) { + static const Uchar zisofs_magic[8] = + { 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07 }; + FILE *zffile; + unsigned int file_size; + Uchar header[16]; + int OK_flag; + int blocksize; + int headersize; + + /* + * First open file and verify that the correct algorithm was + * used + */ + file_size = 0; + OK_flag = 1; + + memset(header, 0, sizeof (header)); + + zffile = fopen(whole_name, "rb"); + if (zffile != NULL) { + if (fread(header, 1, sizeof (header), zffile) != sizeof (header)) + OK_flag = 0; + + /* Check magic number */ + if (memcmp(header, zisofs_magic, sizeof (zisofs_magic))) + OK_flag = 0; + + /* Get the real size of the file */ + file_size = get_731((char *)header+8); + + /* Get the header size (>> 2) */ + headersize = header[12]; + + /* Get the block size (log2) */ + blocksize = header[13]; + + fclose(zffile); + } else { + OK_flag = 0; + blocksize = headersize = 0; /* Make silly GCC quiet */ + } + + if (OK_flag) { + if (MAYBE_ADD_CE_ENTRY(ZF_SIZE)) + add_CE_entry("ZF", __LINE__); + Rock[ipnt++] = 'Z'; + Rock[ipnt++] = 'F'; + Rock[ipnt++] = ZF_SIZE; + Rock[ipnt++] = SU_VERSION; + Rock[ipnt++] = 'p'; /* Algorithm: "paged zlib" */ + Rock[ipnt++] = 'z'; + /* 2 bytes for algorithm-specific information */ + Rock[ipnt++] = headersize; + Rock[ipnt++] = blocksize; + 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("ER", __LINE__); + + /* + * 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); + +xa_only: + s_entry->rr_attributes = (Uchar *) 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 * +generate_rr_extension_record(char *id, char *descriptor, char *source, + int *size) +{ + int lipnt = 0; + char *pnt; + int len_id; + int len_des; + int len_src; + + len_id = strlen(id); + len_des = strlen(descriptor); + len_src = strlen(source); + Rock[lipnt++] = 'E'; + Rock[lipnt++] = 'R'; + Rock[lipnt++] = ER_SIZE + len_id + len_des + len_src; + Rock[lipnt++] = 1; + Rock[lipnt++] = len_id; + Rock[lipnt++] = len_des; + Rock[lipnt++] = len_src; + Rock[lipnt++] = 1; + + memcpy(Rock + lipnt, id, len_id); + lipnt += len_id; + + memcpy(Rock + lipnt, descriptor, len_des); + lipnt += len_des; + + memcpy(Rock + lipnt, source, len_src); + lipnt += len_src; + + if (lipnt > SECTOR_SIZE) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Extension record too long\n"); +#else + fprintf(stderr, "Extension record too long\n"); + exit(1); +#endif + } + pnt = (char *) e_malloc(SECTOR_SIZE); + memset(pnt, 0, SECTOR_SIZE); + memcpy(pnt, Rock, lipnt); + *size = lipnt; + return (pnt); +} diff --git a/genisoimage/rsync.c b/genisoimage/rsync.c new file mode 100644 index 0000000..3f7e416 --- /dev/null +++ b/genisoimage/rsync.c @@ -0,0 +1,112 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +#include "genisoimage.h" +#include "utypes.h" +#include <ctype.h> +#include <mconfig.h> + +/* Borrowed from jigdo; original notice: + + These are purely random, no patterns or anything... (I hope) + + I do not claim copyright for the actual numbers below, you may use them + for a re-implementation of the algorithm under a license of your choice. + -- Richard Atterer. */ +static UInt32_t charTable[256] = { + 0x51d65c0f, 0x083cd94b, 0x77f73dd8, 0xa0187d36, + 0x29803d07, 0x7ea8ac0e, 0xea4c16c9, 0xfc576443, + 0x6213df29, 0x1c012392, 0xb38946ae, 0x2e20ca31, + 0xe4dc532f, 0xcb281c47, 0x8508b6a5, 0xb93c210d, + 0xef02b5f3, 0x66548c74, 0x9ae2deab, 0x3b59f472, + 0x4e546447, 0x45232d1f, 0x0ac0a4b1, 0x6c4c264b, + 0x5d24ce84, 0x0f2752cc, 0xa35c7ac7, 0x3e31af51, + 0x79675a59, 0x581f0e81, 0x49053122, 0x7339c9d8, + 0xf9833565, 0xa3dbe5b3, 0xcc06eeb9, 0x92d0671c, + 0x3eb220a7, 0x64864eae, 0xca100872, 0xc50977a1, + 0xd90378e1, 0x7a36cab9, 0x15c15f4b, 0x8b9ef749, + 0xcc1432dc, 0x1ec578ed, 0x27e6e092, 0xbb06db8f, + 0x67f661ac, 0x8dd1a3db, 0x2a0ca16b, 0xb229ab84, + 0x127a3337, 0x347d846f, 0xe1ea4b50, 0x008dbb91, + 0x414c1426, 0xd2be76f0, 0x08789a39, 0xb4d93e30, + 0x61667760, 0x8871bee9, 0xab7da12d, 0xe3c58620, + 0xe9fdfbbe, 0x64fb04f7, 0x8cc5bbf0, 0xf5272d30, + 0x8f161b50, 0x11122b05, 0x7695e72e, 0xa1c5d169, + 0x1bfd0e20, 0xef7e6169, 0xf652d08e, 0xa9d0f139, + 0x2f70aa04, 0xae2c7d6d, 0xa3cb9241, 0x3ae7d364, + 0x348788f8, 0xf483b8f1, 0x55a011da, 0x189719dc, + 0xb0c5d723, 0x8b344e33, 0x300d46eb, 0xd44fe34f, + 0x1a2016c1, 0x66ce4cd7, 0xa45ea5e3, 0x55cb708a, + 0xbce430df, 0xb01ae6e0, 0x3551163b, 0x2c5b157a, + 0x574c4209, 0x430fd0e4, 0x3387e4a5, 0xee1d7451, + 0xa9635623, 0x873ab89b, 0xb96bc6aa, 0x59898937, + 0xe646c6e7, 0xb79f8792, 0x3f3235d8, 0xef1b5acf, + 0xd975b22b, 0x427acce6, 0xe47a2411, 0x75f8c1e8, + 0xa63f799d, 0x53886ad8, 0x9b2d6d32, 0xea822016, + 0xcdee2254, 0xd98bcd98, 0x2933a544, 0x961f379f, + 0x49219792, 0xc61c360f, 0x77cc0c64, 0x7b872046, + 0xb91c7c12, 0x7577154b, 0x196573be, 0xf788813f, + 0x41e2e56a, 0xec3cd244, 0x8c7401f1, 0xc2e805fe, + 0xe8872fbe, 0x9e2faf7d, 0x6766456b, 0x888e2197, + 0x28535c6d, 0x2ce45f3f, 0x24261d2a, 0xd6faab8b, + 0x7a7b42b8, 0x15f0f6fa, 0xfe1711df, 0x7e5685a6, + 0x00930268, 0x74755331, 0x1998912c, 0x7b60498b, + 0x501a5786, 0x92ace0f6, 0x1d9752fe, 0x5a731add, + 0x5b3b44fc, 0x473673f9, 0xa42c0321, 0xd82f9f18, + 0xb4b225da, 0xfc89ece2, 0x072e1130, 0x5772aae3, + 0x29010857, 0x542c970c, 0x94f67fe5, 0x71209e9b, + 0xdb97ea39, 0x2689b41b, 0xae815804, 0xfc5e2651, + 0xd4521674, 0x48ed979a, 0x2f617da3, 0xc350353d, + 0xc3accd94, 0xbd8d313a, 0xc61a8e77, 0xf34940a4, + 0x8d2c6b0f, 0x0f0e7225, 0x39e183db, 0xd19ebba9, + 0x6a0f37b9, 0xd18922f3, 0x106420c5, 0xaa5a640b, + 0x7cf0d273, 0xcf3238a7, 0x3b33204f, 0x476be7bb, + 0x09d23bca, 0xbe84b2f7, 0xb7a3bace, 0x2528cee1, + 0x3dcaa1dd, 0x900ad31a, 0xf21dea6d, 0x9ce51463, + 0xf1540bba, 0x0fab1bdd, 0x89cfb79a, 0x01a2a6e6, + 0x6f85d67c, 0xd1669ec4, 0x355db722, 0x00ebd5c4, + 0x926eb385, 0x69ead869, 0x0da2b122, 0x402779fe, + 0xdaed92d0, 0x57e9aabb, 0x3df64854, 0xfcc774b5, + 0x2e1740ed, 0xa615e024, 0xf7bac938, 0x377dfd1a, + 0xd0559d66, 0x25499be8, 0x2d8f2006, 0xfaa9e486, + 0x95e980e7, 0x82aeba67, 0x5a7f2561, 0xbc60dff6, + 0x6c8739a2, 0x7ec59a8b, 0x9998f265, 0xdfe37e5e, + 0xb47cee1e, 0x4dd8bc9e, 0x35c57e09, 0x07850b63, + 0x06eadbcb, 0x6c1f2956, 0x01685c2c, 0xf5725eef, + 0xf13b98b5, 0xaab739c2, 0x200b1da2, 0xa716b98b, + 0xd9ee3058, 0x76acf20b, 0x2f259e04, 0xed11658b, + 0x1532b331, 0x0ab43204, 0xf0beb023, 0xb1685483, + 0x58cbdc4f, 0x079384d3, 0x049b141c, 0xc38184b9, + 0xaf551d9a, 0x66222560, 0x059deeca, 0x535f99e2 +}; + +unsigned long long rsync64(unsigned char *mem, size_t size) +{ + UInt32_t a = 0; + UInt32_t b = 0; + unsigned char *limit = mem + size; + unsigned long long result = 0; + + while (mem < limit) + { + a += charTable[*mem++]; + b += a; + } + + a = a & 0xffffffff; /* Just in case uint32 can be 64 bits */ + b = b & 0xffffffff; + + result = ((unsigned long long)b << 32) | a; + + return result; +} + diff --git a/genisoimage/scsi.c b/genisoimage/scsi.c new file mode 100644 index 0000000..179cc33 --- /dev/null +++ b/genisoimage/scsi.c @@ -0,0 +1,195 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)scsi.c 1.20 05/05/01 Copyright 1997 J. Schilling */ +/* + * Copyright (c) 1997 J. Schilling + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef USE_SCG +#include <mconfig.h> + +#include <stdio.h> +#include <standard.h> +#include <stdxlib.h> +#include <unixstd.h> +#include <schily.h> + +#include "genisoimage.h" +#include <usal/scsireg.h> +#include <usal/scsitransp.h> + +#include "wodim.h" +#include "../wodim/defaults.h" + +/* + * NOTICE: You should not make BUF_SIZE more than + * the buffer size of the CD-Recorder. + * + * Do not set BUF_SIZE to be more than 126 KBytes + * if you are running cdrecord on a sun4c machine. + * + * WARNING: Philips CDD 521 dies if BUF_SIZE is to big. + */ +#define BUF_SIZE (62*1024) /* Must be a multiple of 2048 */ + +static SCSI *usalp; +static long bufsize; /* The size of the transfer buffer */ + +int readsecs(int startsecno, void *buffer, int sectorcount); +int scsidev_open(char *path); +int scsidev_close(void); + +int +readsecs(int startsecno, void *buffer, int sectorcount) +{ + int f; + int secsize; /* The drive's SCSI sector size */ + long amount; /* The number of bytes to be transfered */ + long secno; /* The sector number to read from */ + long secnum; /* The number of sectors to read */ + char *bp; + long amt; + + if (in_image == NULL) { + /* + * We are using the standard CD-ROM sectorsize of 2048 bytes + * while the drive may be switched to 512 bytes per sector. + * + * XXX We assume that secsize is no more than SECTOR_SIZE + * XXX and that SECTOR_SIZE / secsize is not a fraction. + */ + secsize = usalp->cap->c_bsize; + amount = sectorcount * SECTOR_SIZE; + secno = startsecno * (SECTOR_SIZE / secsize); + bp = buffer; + + while (amount > 0) { + amt = amount; + if (amount > bufsize) + amt = bufsize; + secnum = amt / secsize; + + if (read_scsi(usalp, bp, secno, secnum) < 0 || + usal_getresid(usalp) != 0) { +#ifdef OLD + return (-1); +#else + comerr("Read error on old image\n"); +#endif + } + + amount -= secnum * secsize; + bp += secnum * secsize; + secno += secnum; + } + return (SECTOR_SIZE * sectorcount); + } + + f = fileno(in_image); + + if (lseek(f, (off_t)startsecno * SECTOR_SIZE, SEEK_SET) == (off_t)-1) { +#ifdef USE_LIBSCHILY + comerr("Seek error on old image\n"); +#else + fprintf(stderr, "Seek error on old image\n"); + exit(10); +#endif + } + if ((amt = read(f, buffer, (sectorcount * SECTOR_SIZE))) + != (sectorcount * SECTOR_SIZE)) { +#ifdef USE_LIBSCHILY + if (amt < 0) + comerr("Read error on old image\n"); + comerrno(EX_BAD, "Short read on old image\n"); /* < secnt aber > 0 */ +#else + if (amt < 0) + fprintf(stderr, "Read error on old image\n"); + else + fprintf(stderr, "Short read on old image\n"); + + exit(10); +#endif + } + return (sectorcount * SECTOR_SIZE); +} + +int +scsidev_open(char *path) +{ + char errstr[80]; + char *buf; /* ignored, bit OS/2 ASPI layer needs memory which */ + /* has been allocated by scsi_getbuf() */ + + /* + * Call usal_remote() to force loading the remote SCSI transport library + * code that is located in librusal instead of the dummy remote routines + * that are located inside libusal. + */ + usal_remote(); + + cdr_defaults(&path, NULL, NULL, NULL); + /* path, debug, verboseopen */ + usalp = usal_open(path, errstr, sizeof (errstr), 0, 0); + if (usalp == 0) { + errmsg("%s%sCannot open SCSI driver.\n", errstr, errstr[0]?". ":""); + return (-1); + } + + bufsize = usal_bufsize(usalp, BUF_SIZE); + if ((buf = usal_getbuf(usalp, bufsize)) == NULL) { + errmsg("Cannot get SCSI I/O buffer.\n"); + usal_close(usalp); + return (-1); + } + + bufsize = (bufsize / SECTOR_SIZE) * SECTOR_SIZE; + + allow_atapi(usalp, TRUE); + + if (!wait_unit_ready(usalp, 60)) { /* Eat Unit att / Wait for drive */ + usalp->silent--; + return (-1); + } + + usalp->silent++; + read_capacity(usalp); /* Set Capacity/Sectorsize for I/O */ + usalp->silent--; + + return (1); +} + +int +scsidev_close() +{ + if (in_image == NULL) { + return (usal_close(usalp)); + } else { + return (fclose(in_image)); + } +} + +#endif /* USE_SCG */ diff --git a/genisoimage/scsi.h b/genisoimage/scsi.h new file mode 100644 index 0000000..58fc342 --- /dev/null +++ b/genisoimage/scsi.h @@ -0,0 +1,41 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)scsi.h 1.1 04/05/27 Copyright 1997-2004 J. Schilling */ +/* + * Copyright (c) 1997-2004 J. Schilling + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SCSI_H +#define _SCSI_H + +#ifdef USE_SCG +extern int readsecs(int startsecno, void *buffer, int sectorcount); +extern int scsidev_open(char *path); +extern int scsidev_close(void); +#endif + +#endif /* _SCSI_H */ diff --git a/genisoimage/sha1.c b/genisoimage/sha1.c new file mode 100644 index 0000000..ae410ac --- /dev/null +++ b/genisoimage/sha1.c @@ -0,0 +1,415 @@ +/* sha1.c - Functions to compute SHA1 message digest of files or + memory blocks according to the NIST specification FIPS-180-1. + + Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Scott G. Miller + Credits: + Robert Klep <robert@ilse.nl> -- Expansion function fix +*/ + +#include "sha1.h" + +#include <stddef.h> +#include <string.h> + +/* SWAP does an endian swap on architectures that are little-endian, + as SHA1 needs some data in a big-endian form. */ + +#ifdef WORDS_BIGENDIAN +# define SWAP(n) (n) +#else +# define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +#endif + +#define BLOCKSIZE 4096 +#if BLOCKSIZE % 64 != 0 +# error "invalid BLOCKSIZE" +#endif + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* + Takes a pointer to a 160 bit block of data (five 32 bit ints) and + intializes it to the start constants of the SHA1 algorithm. This + must be called before using hash in the call to sha1_hash. +*/ +void +sha1_init_ctx (struct sha1_ctx *ctx) +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + ctx->E = 0xc3d2e1f0; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Put result from CTX in first 20 bytes following RESBUF. The result + must be in little endian byte order. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf) +{ + ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); + ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); + ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); + ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); + ((md5_uint32 *) resbuf)[4] = SWAP (ctx->E); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf) +{ + /* Take yet unprocessed bytes into account. */ + md5_uint32 bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3); + *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); + + /* Process last bytes. */ + sha1_process_block (ctx->buffer, bytes + pad + 8, ctx); + + return sha1_read_ctx (ctx, resbuf); +} + +/* Compute SHA1 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +int +sha1_stream (FILE *stream, void *resblock) +{ + struct sha1_ctx ctx; + char buffer[BLOCKSIZE + 72]; + size_t sum; + + /* Initialize the computation context. */ + sha1_init_ctx (&ctx); + + /* Iterate over full file contents. */ + while (1) + { + /* We read the file in blocks of BLOCKSIZE bytes. One call of the + computation function processes the whole buffer so that with the + next round of the loop another block can be read. */ + size_t n; + sum = 0; + + /* Read block. Take care for partial reads. */ + while (1) + { + n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); + + sum += n; + + if (sum == BLOCKSIZE) + break; + + if (n == 0) + { + /* Check for the error flag IFF N == 0, so that we don't + exit the loop after a partial read due to e.g., EAGAIN + or EWOULDBLOCK. */ + if (ferror (stream)) + return 1; + goto process_partial_block; + } + + /* We've read at least one byte, so ignore errors. But always + check for EOF, since feof may be true even though N > 0. + Otherwise, we could end up calling fread after EOF. */ + if (feof (stream)) + goto process_partial_block; + } + + /* Process buffer with BLOCKSIZE bytes. Note that + BLOCKSIZE % 64 == 0 + */ + sha1_process_block (buffer, BLOCKSIZE, &ctx); + } + + process_partial_block:; + + /* Process any remaining bytes. */ + if (sum > 0) + sha1_process_bytes (buffer, sum, &ctx); + + /* Construct result in desired memory. */ + sha1_finish_ctx (&ctx, resblock); + return 0; +} + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +sha1_buffer (const char *buffer, size_t len, void *resblock) +{ + struct sha1_ctx ctx; + + /* Initialize the computation context. */ + sha1_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + sha1_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return sha1_finish_ctx (&ctx, resblock); +} + +void +sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx) +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) + { +#if !_STRING_ARCH_unaligned +# define alignof(type) offsetof (struct { char c; type x; }, x) +# define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0) + if (UNALIGNED_P (buffer)) + while (len > 64) + { + sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else +#endif + { + sha1_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + sha1_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + memcpy (ctx->buffer, &ctx->buffer[64], left_over); + } + ctx->buflen = left_over; + } +} + +/* --- Code below is the primary difference between md5.c and sha1.c --- */ + +/* SHA1 round constants */ +#define K1 0x5a827999L +#define K2 0x6ed9eba1L +#define K3 0x8f1bbcdcL +#define K4 0xca62c1d6L + +/* Round functions. Note that F2 is the same as F4. */ +#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) ) +#define F2(B,C,D) (B ^ C ^ D) +#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) ) +#define F4(B,C,D) (B ^ C ^ D) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. + Most of this code comes from GnuPG's cipher/sha1.c. */ + +void +sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx) +{ + const md5_uint32 *words = buffer; + size_t nwords = len / sizeof (md5_uint32); + const md5_uint32 *endp = words + nwords; + md5_uint32 x[16]; + md5_uint32 a = ctx->A; + md5_uint32 b = ctx->B; + md5_uint32 c = ctx->C; + md5_uint32 d = ctx->D; + md5_uint32 e = ctx->E; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + +#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + +#define M(I) ( tm = x[I&0x0f] ^ x[(I-14)&0x0f] \ + ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \ + , (x[I&0x0f] = rol(tm, 1)) ) + +#define R(A,B,C,D,E,F,K,M) do { E += rol( A, 5 ) \ + + F( B, C, D ) \ + + K \ + + M; \ + B = rol( B, 30 ); \ + } while(0) + + while (words < endp) + { + md5_uint32 tm; + int t; + for (t = 0; t < 16; t++) + { + x[t] = SWAP (*words); + words++; + } + + R( a, b, c, d, e, F1, K1, x[ 0] ); + R( e, a, b, c, d, F1, K1, x[ 1] ); + R( d, e, a, b, c, F1, K1, x[ 2] ); + R( c, d, e, a, b, F1, K1, x[ 3] ); + R( b, c, d, e, a, F1, K1, x[ 4] ); + R( a, b, c, d, e, F1, K1, x[ 5] ); + R( e, a, b, c, d, F1, K1, x[ 6] ); + R( d, e, a, b, c, F1, K1, x[ 7] ); + R( c, d, e, a, b, F1, K1, x[ 8] ); + R( b, c, d, e, a, F1, K1, x[ 9] ); + R( a, b, c, d, e, F1, K1, x[10] ); + R( e, a, b, c, d, F1, K1, x[11] ); + R( d, e, a, b, c, F1, K1, x[12] ); + R( c, d, e, a, b, F1, K1, x[13] ); + R( b, c, d, e, a, F1, K1, x[14] ); + R( a, b, c, d, e, F1, K1, x[15] ); + R( e, a, b, c, d, F1, K1, M(16) ); + R( d, e, a, b, c, F1, K1, M(17) ); + R( c, d, e, a, b, F1, K1, M(18) ); + R( b, c, d, e, a, F1, K1, M(19) ); + R( a, b, c, d, e, F2, K2, M(20) ); + R( e, a, b, c, d, F2, K2, M(21) ); + R( d, e, a, b, c, F2, K2, M(22) ); + R( c, d, e, a, b, F2, K2, M(23) ); + R( b, c, d, e, a, F2, K2, M(24) ); + R( a, b, c, d, e, F2, K2, M(25) ); + R( e, a, b, c, d, F2, K2, M(26) ); + R( d, e, a, b, c, F2, K2, M(27) ); + R( c, d, e, a, b, F2, K2, M(28) ); + R( b, c, d, e, a, F2, K2, M(29) ); + R( a, b, c, d, e, F2, K2, M(30) ); + R( e, a, b, c, d, F2, K2, M(31) ); + R( d, e, a, b, c, F2, K2, M(32) ); + R( c, d, e, a, b, F2, K2, M(33) ); + R( b, c, d, e, a, F2, K2, M(34) ); + R( a, b, c, d, e, F2, K2, M(35) ); + R( e, a, b, c, d, F2, K2, M(36) ); + R( d, e, a, b, c, F2, K2, M(37) ); + R( c, d, e, a, b, F2, K2, M(38) ); + R( b, c, d, e, a, F2, K2, M(39) ); + R( a, b, c, d, e, F3, K3, M(40) ); + R( e, a, b, c, d, F3, K3, M(41) ); + R( d, e, a, b, c, F3, K3, M(42) ); + R( c, d, e, a, b, F3, K3, M(43) ); + R( b, c, d, e, a, F3, K3, M(44) ); + R( a, b, c, d, e, F3, K3, M(45) ); + R( e, a, b, c, d, F3, K3, M(46) ); + R( d, e, a, b, c, F3, K3, M(47) ); + R( c, d, e, a, b, F3, K3, M(48) ); + R( b, c, d, e, a, F3, K3, M(49) ); + R( a, b, c, d, e, F3, K3, M(50) ); + R( e, a, b, c, d, F3, K3, M(51) ); + R( d, e, a, b, c, F3, K3, M(52) ); + R( c, d, e, a, b, F3, K3, M(53) ); + R( b, c, d, e, a, F3, K3, M(54) ); + R( a, b, c, d, e, F3, K3, M(55) ); + R( e, a, b, c, d, F3, K3, M(56) ); + R( d, e, a, b, c, F3, K3, M(57) ); + R( c, d, e, a, b, F3, K3, M(58) ); + R( b, c, d, e, a, F3, K3, M(59) ); + R( a, b, c, d, e, F4, K4, M(60) ); + R( e, a, b, c, d, F4, K4, M(61) ); + R( d, e, a, b, c, F4, K4, M(62) ); + R( c, d, e, a, b, F4, K4, M(63) ); + R( b, c, d, e, a, F4, K4, M(64) ); + R( a, b, c, d, e, F4, K4, M(65) ); + R( e, a, b, c, d, F4, K4, M(66) ); + R( d, e, a, b, c, F4, K4, M(67) ); + R( c, d, e, a, b, F4, K4, M(68) ); + R( b, c, d, e, a, F4, K4, M(69) ); + R( a, b, c, d, e, F4, K4, M(70) ); + R( e, a, b, c, d, F4, K4, M(71) ); + R( d, e, a, b, c, F4, K4, M(72) ); + R( c, d, e, a, b, F4, K4, M(73) ); + R( b, c, d, e, a, F4, K4, M(74) ); + R( a, b, c, d, e, F4, K4, M(75) ); + R( e, a, b, c, d, F4, K4, M(76) ); + R( d, e, a, b, c, F4, K4, M(77) ); + R( c, d, e, a, b, F4, K4, M(78) ); + R( b, c, d, e, a, F4, K4, M(79) ); + + a = ctx->A += a; + b = ctx->B += b; + c = ctx->C += c; + d = ctx->D += d; + e = ctx->E += e; + } +} diff --git a/genisoimage/sha1.h b/genisoimage/sha1.h new file mode 100644 index 0000000..51891d0 --- /dev/null +++ b/genisoimage/sha1.h @@ -0,0 +1,88 @@ +/* Declarations of functions and data types used for SHA1 sum + library functions. + Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef SHA1_H +# define SHA1_H 1 + +# include <stdio.h> + +typedef unsigned int md5_uint32; + +/* Structure to save state of computation between the single steps. */ +struct sha1_ctx +{ + md5_uint32 A; + md5_uint32 B; + md5_uint32 C; + md5_uint32 D; + md5_uint32 E; + + md5_uint32 total[2]; + md5_uint32 buflen; + char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); +}; + + +/* Initialize structure containing state of computation. */ +extern void sha1_init_ctx (struct sha1_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void sha1_process_block (const void *buffer, size_t len, + struct sha1_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void sha1_process_bytes (const void *buffer, size_t len, + struct sha1_ctx *ctx); + +/* Process the remaining bytes in the buffer and put result from CTX + in first 20 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF be correctly + aligned for a 32 bits value. */ +extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf); + + +/* Put result from CTX in first 20 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf); + + +/* Compute SHA1 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 20 bytes + beginning at RESBLOCK. */ +extern int sha1_stream (FILE *stream, void *resblock); + +/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *sha1_buffer (const char *buffer, size_t len, void *resblock); + +#endif diff --git a/genisoimage/sha256.c b/genisoimage/sha256.c new file mode 100644 index 0000000..f7558b2 --- /dev/null +++ b/genisoimage/sha256.c @@ -0,0 +1,307 @@ +/* Functions to compute SHA256 message digest of files or memory blocks. + according to the definition of SHA256 in FIPS 180-2. + Copyright (C) 2007 Free Software Foundation, Inc. + + Copied here from the GNU C Library version 2.7 on the 10 May 2009 + by Steve McIntyre <93sam@debian.org>. This code was under LGPL v2.1 + in glibc, and that license gives us the option to use and + distribute the code under the terms of the GPL v2 instead. I'm + taking that option. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Ulrich Drepper <drepper@redhat.com>, 2007. */ + +#include <endian.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +#include "sha256.h" + +#if __BYTE_ORDER == __LITTLE_ENDIAN +# ifdef _LIBC +# include <byteswap.h> +# define SWAP(n) bswap_32 (n) +# else +# define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +# endif +#else +# define SWAP(n) (n) +#endif + + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (FIPS 180-2:5.1.1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Constants for SHA256 from FIPS 180-2:4.2.2. */ +static const uint32_t K[64] = + { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ +static void +sha256_process_block (const void *buffer, size_t len, struct sha256_ctx *ctx) +{ + const uint32_t *words = buffer; + size_t nwords = len / sizeof (uint32_t); + uint32_t a = ctx->H[0]; + uint32_t b = ctx->H[1]; + uint32_t c = ctx->H[2]; + uint32_t d = ctx->H[3]; + uint32_t e = ctx->H[4]; + uint32_t f = ctx->H[5]; + uint32_t g = ctx->H[6]; + uint32_t h = ctx->H[7]; + + /* First increment the byte count. FIPS 180-2 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (nwords > 0) + { + uint32_t W[64]; + uint32_t a_save = a; + uint32_t b_save = b; + uint32_t c_save = c; + uint32_t d_save = d; + uint32_t e_save = e; + uint32_t f_save = f; + uint32_t g_save = g; + uint32_t h_save = h; + + unsigned int t; + + /* Operators defined in FIPS 180-2:4.1.2. */ +#define Ch(x, y, z) ((x & y) ^ (~x & z)) +#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) +#define S0(x) (CYCLIC (x, 2) ^ CYCLIC (x, 13) ^ CYCLIC (x, 22)) +#define S1(x) (CYCLIC (x, 6) ^ CYCLIC (x, 11) ^ CYCLIC (x, 25)) +#define R0(x) (CYCLIC (x, 7) ^ CYCLIC (x, 18) ^ (x >> 3)) +#define R1(x) (CYCLIC (x, 17) ^ CYCLIC (x, 19) ^ (x >> 10)) + + /* It is unfortunate that C does not provide an operator for + cyclic rotation. Hope the C compiler is smart enough. */ +#define CYCLIC(w, s) ((w >> s) | (w << (32 - s))) + + /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */ + for (t = 0; t < 16; ++t) + { + W[t] = SWAP (*words); + ++words; + } + for (t = 16; t < 64; ++t) + W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16]; + + /* The actual computation according to FIPS 180-2:6.2.2 step 3. */ + for (t = 0; t < 64; ++t) + { + uint32_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t]; + uint32_t T2 = S0 (a) + Maj (a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + /* Add the starting values of the context according to FIPS 180-2:6.2.2 + step 4. */ + a += a_save; + b += b_save; + c += c_save; + d += d_save; + e += e_save; + f += f_save; + g += g_save; + h += h_save; + + /* Prepare for the next round. */ + nwords -= 16; + } + + /* Put checksum in context given as argument. */ + ctx->H[0] = a; + ctx->H[1] = b; + ctx->H[2] = c; + ctx->H[3] = d; + ctx->H[4] = e; + ctx->H[5] = f; + ctx->H[6] = g; + ctx->H[7] = h; +} + + +/* Initialize structure containing state of computation. + (FIPS 180-2:5.3.2) */ +void +sha256_init_ctx (ctx) + struct sha256_ctx *ctx; +{ + ctx->H[0] = 0x6a09e667; + ctx->H[1] = 0xbb67ae85; + ctx->H[2] = 0x3c6ef372; + ctx->H[3] = 0xa54ff53a; + ctx->H[4] = 0x510e527f; + ctx->H[5] = 0x9b05688c; + ctx->H[6] = 0x1f83d9ab; + ctx->H[7] = 0x5be0cd19; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +sha256_finish_ctx (ctx, resbuf) + struct sha256_ctx *ctx; + void *resbuf; +{ + /* Take yet unprocessed bytes into account. */ + uint32_t bytes = ctx->buflen; + size_t pad; + unsigned int i; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(uint32_t *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3); + *(uint32_t *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); + + /* Process last bytes. */ + sha256_process_block (ctx->buffer, bytes + pad + 8, ctx); + + /* Put result from CTX in first 32 bytes following RESBUF. */ + for (i = 0; i < 8; ++i) + ((uint32_t *) resbuf)[i] = SWAP (ctx->H[i]); + + return resbuf; +} + + +void +sha256_process_bytes (buffer, len, ctx) + const void *buffer; + size_t len; + struct sha256_ctx *ctx; +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + sha256_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) + { +#if !_STRING_ARCH_unaligned +/* To check alignment gcc has an appropriate operator. Other + compilers don't. */ +# if __GNUC__ >= 2 +# define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint32_t) != 0) +# else +# define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint32_t) != 0) +# endif + if (UNALIGNED_P (buffer)) + while (len > 64) + { + sha256_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else +#endif + { + sha256_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes into internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + sha256_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + memcpy (ctx->buffer, &ctx->buffer[64], left_over); + } + ctx->buflen = left_over; + } +} diff --git a/genisoimage/sha256.h b/genisoimage/sha256.h new file mode 100644 index 0000000..e7f4cb9 --- /dev/null +++ b/genisoimage/sha256.h @@ -0,0 +1,62 @@ +/* Declaration of functions and data types used for SHA256 sum computing + library functions. + Copyright (C) 2007 Free Software Foundation, Inc. + + Copied here from the GNU C Library version 2.7 on the 10 May 2009 + by Steve McIntyre <93sam@debian.org>. This code was under GPL v2.1 + in glibc, and that license gives us the option to use and + distribute the code under the terms of the GPL v2 instead. I'm + taking that option. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _SHA256_H +#define _SHA256_H 1 + +#include <limits.h> +#include <stdint.h> +#include <stdio.h> + + +/* Structure to save state of computation between the single steps. */ +struct sha256_ctx +{ + uint32_t H[8]; + + uint32_t total[2]; + uint32_t buflen; + char buffer[128] __attribute__ ((__aligned__ (__alignof__ (uint32_t)))); +}; + +/* Initialize structure containing state of computation. + (FIPS 180-2: 5.3.2) */ +extern void sha256_init_ctx (struct sha256_ctx *ctx) __THROW; + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void sha256_process_bytes (const void *buffer, size_t len, + struct sha256_ctx *ctx) __THROW; + +/* Process the remaining bytes in the buffer and put result from CTX + in first 32 bytes following RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *sha256_finish_ctx (struct sha256_ctx *ctx, void *resbuf) + __THROW; + +#endif /* sha256.h */ diff --git a/genisoimage/sha512.c b/genisoimage/sha512.c new file mode 100644 index 0000000..c4987ce --- /dev/null +++ b/genisoimage/sha512.c @@ -0,0 +1,338 @@ +/* Functions to compute SHA512 message digest of files or memory blocks. + according to the definition of SHA512 in FIPS 180-2. + Copyright (C) 2007 Free Software Foundation, Inc. + + Copied here from the GNU C Library version 2.7 on the 10 May 2009 + by Steve McIntyre <93sam@debian.org>. This code was under LGPL v2.1 + in glibc, and that license gives us the option to use and + distribute the code under the terms of the GPL v2 instead. I'm + taking that option. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Ulrich Drepper <drepper@redhat.com>, 2007. */ + +#include <endian.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +#include "sha512.h" + +#if __BYTE_ORDER == __LITTLE_ENDIAN +# ifdef _LIBC +# include <byteswap.h> +# define SWAP(n) bswap_64 (n) +# else +# define SWAP(n) \ + (((n) << 56) \ + | (((n) & 0xff00) << 40) \ + | (((n) & 0xff0000) << 24) \ + | (((n) & 0xff000000) << 8) \ + | (((n) >> 8) & 0xff000000) \ + | (((n) >> 24) & 0xff0000) \ + | (((n) >> 40) & 0xff00) \ + | ((n) >> 56)) +# endif +#else +# define SWAP(n) (n) +#endif + + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (FIPS 180-2:5.1.2) */ +static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Constants for SHA512 from FIPS 180-2:4.2.3. */ +static const uint64_t K[80] = + { + UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd), + UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc), + UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019), + UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118), + UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe), + UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2), + UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1), + UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694), + UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3), + UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65), + UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483), + UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5), + UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210), + UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4), + UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725), + UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70), + UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926), + UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df), + UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8), + UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b), + UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001), + UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30), + UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910), + UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8), + UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53), + UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8), + UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb), + UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3), + UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60), + UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec), + UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9), + UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b), + UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207), + UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178), + UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6), + UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b), + UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493), + UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c), + UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a), + UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817) + }; + + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 128 == 0. */ +static void +sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx) +{ + const uint64_t *words = buffer; + size_t nwords = len / sizeof (uint64_t); + uint64_t a = ctx->H[0]; + uint64_t b = ctx->H[1]; + uint64_t c = ctx->H[2]; + uint64_t d = ctx->H[3]; + uint64_t e = ctx->H[4]; + uint64_t f = ctx->H[5]; + uint64_t g = ctx->H[6]; + uint64_t h = ctx->H[7]; + + /* First increment the byte count. FIPS 180-2 specifies the possible + length of the file up to 2^128 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 128 bytes in each round of + the loop. */ + while (nwords > 0) + { + uint64_t W[80]; + uint64_t a_save = a; + uint64_t b_save = b; + uint64_t c_save = c; + uint64_t d_save = d; + uint64_t e_save = e; + uint64_t f_save = f; + uint64_t g_save = g; + uint64_t h_save = h; + unsigned int t; + + /* Operators defined in FIPS 180-2:4.1.2. */ +#define Ch(x, y, z) ((x & y) ^ (~x & z)) +#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) +#define S0(x) (CYCLIC (x, 28) ^ CYCLIC (x, 34) ^ CYCLIC (x, 39)) +#define S1(x) (CYCLIC (x, 14) ^ CYCLIC (x, 18) ^ CYCLIC (x, 41)) +#define R0(x) (CYCLIC (x, 1) ^ CYCLIC (x, 8) ^ (x >> 7)) +#define R1(x) (CYCLIC (x, 19) ^ CYCLIC (x, 61) ^ (x >> 6)) + + /* It is unfortunate that C does not provide an operator for + cyclic rotation. Hope the C compiler is smart enough. */ +#define CYCLIC(w, s) ((w >> s) | (w << (64 - s))) + + /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */ + for (t = 0; t < 16; ++t) + { + W[t] = SWAP (*words); + ++words; + } + for (t = 16; t < 80; ++t) + W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16]; + + /* The actual computation according to FIPS 180-2:6.3.2 step 3. */ + for (t = 0; t < 80; ++t) + { + uint64_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t]; + uint64_t T2 = S0 (a) + Maj (a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + /* Add the starting values of the context according to FIPS 180-2:6.3.2 + step 4. */ + a += a_save; + b += b_save; + c += c_save; + d += d_save; + e += e_save; + f += f_save; + g += g_save; + h += h_save; + + /* Prepare for the next round. */ + nwords -= 16; + } + + /* Put checksum in context given as argument. */ + ctx->H[0] = a; + ctx->H[1] = b; + ctx->H[2] = c; + ctx->H[3] = d; + ctx->H[4] = e; + ctx->H[5] = f; + ctx->H[6] = g; + ctx->H[7] = h; +} + + +/* Initialize structure containing state of computation. + (FIPS 180-2:5.3.3) */ +void +sha512_init_ctx (ctx) + struct sha512_ctx *ctx; +{ + ctx->H[0] = UINT64_C (0x6a09e667f3bcc908); + ctx->H[1] = UINT64_C (0xbb67ae8584caa73b); + ctx->H[2] = UINT64_C (0x3c6ef372fe94f82b); + ctx->H[3] = UINT64_C (0xa54ff53a5f1d36f1); + ctx->H[4] = UINT64_C (0x510e527fade682d1); + ctx->H[5] = UINT64_C (0x9b05688c2b3e6c1f); + ctx->H[6] = UINT64_C (0x1f83d9abfb41bd6b); + ctx->H[7] = UINT64_C (0x5be0cd19137e2179); + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +sha512_finish_ctx (ctx, resbuf) + struct sha512_ctx *ctx; + void *resbuf; +{ + /* Take yet unprocessed bytes into account. */ + uint64_t bytes = ctx->buflen; + size_t pad; + unsigned int i; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 112 ? 128 + 112 - bytes : 112 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 128-bit file length in *bits* at the end of the buffer. */ + *(uint64_t *) &ctx->buffer[bytes + pad + 8] = SWAP (ctx->total[0] << 3); + *(uint64_t *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 61)); + + /* Process last bytes. */ + sha512_process_block (ctx->buffer, bytes + pad + 16, ctx); + + /* Put result from CTX in first 64 bytes following RESBUF. */ + for (i = 0; i < 8; ++i) + ((uint64_t *) resbuf)[i] = SWAP (ctx->H[i]); + + return resbuf; +} + + +void +sha512_process_bytes (buffer, len, ctx) + const void *buffer; + size_t len; + struct sha512_ctx *ctx; +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 256 - left_over > len ? len : 256 - left_over; + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 128) + { + sha512_process_block (ctx->buffer, ctx->buflen & ~127, ctx); + + ctx->buflen &= 127; + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~127], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 128) + { +#if !_STRING_ARCH_unaligned +/* To check alignment gcc has an appropriate operator. Other + compilers don't. */ +# if __GNUC__ >= 2 +# define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint64_t) != 0) +# else +# define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint64_t) != 0) +# endif + if (UNALIGNED_P (buffer)) + while (len > 128) + { + sha512_process_block (memcpy (ctx->buffer, buffer, 128), 128, + ctx); + buffer = (const char *) buffer + 128; + len -= 128; + } + else +#endif + { + sha512_process_block (buffer, len & ~127, ctx); + buffer = (const char *) buffer + (len & ~127); + len &= 127; + } + } + + /* Move remaining bytes into internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 128) + { + sha512_process_block (ctx->buffer, 128, ctx); + left_over -= 128; + memcpy (ctx->buffer, &ctx->buffer[128], left_over); + } + ctx->buflen = left_over; + } +} diff --git a/genisoimage/sha512.h b/genisoimage/sha512.h new file mode 100644 index 0000000..7298355 --- /dev/null +++ b/genisoimage/sha512.h @@ -0,0 +1,62 @@ +/* Declaration of functions and data types used for SHA512 sum computing + library functions. + Copyright (C) 2007 Free Software Foundation, Inc. + + Copied here from the GNU C Library version 2.7 on the 10 May 2009 + by Steve McIntyre <93sam@debian.org>. This code was under GPL v2.1 + in glibc, and that license gives us the option to use and + distribute the code under the terms of the GPL v2 instead. I'm + taking that option. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _SHA512_H +#define _SHA512_H 1 + +#include <limits.h> +#include <stdint.h> +#include <stdio.h> + + +/* Structure to save state of computation between the single steps. */ +struct sha512_ctx +{ + uint64_t H[8]; + + uint64_t total[2]; + uint64_t buflen; + char buffer[256] __attribute__ ((__aligned__ (__alignof__ (uint64_t)))); +}; + +/* Initialize structure containing state of computation. + (FIPS 180-2: 5.3.3) */ +extern void sha512_init_ctx (struct sha512_ctx *ctx) __THROW; + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 128. */ +extern void sha512_process_bytes (const void *buffer, size_t len, + struct sha512_ctx *ctx) __THROW; + +/* Process the remaining bytes in the buffer and put result from CTX + in first 64 bytes following RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 64 bits value. */ +extern void *sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf) + __THROW; + +#endif /* sha512.h */ diff --git a/genisoimage/stream.c b/genisoimage/stream.c new file mode 100644 index 0000000..f59c1e3 --- /dev/null +++ b/genisoimage/stream.c @@ -0,0 +1,272 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)stream.c 1.3 04/03/04 Copyright 2002-2003 J. Schilling */ +/* Parts from @(#)stream.c 1.9 07/02/17 Copyright 2002-2007 J. Schilling */ +/* + * ISO-9660 stream (pipe) file module for genisoimage + * + * Copyright (c) 2002-2003 J. Schilling + * Implemented after an idea from M.H. Voase + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <mconfig.h> +#include "genisoimage.h" +#include "iso9660.h" + +static int size_str_file(int starting_extent); +static int size_str_dir(int starting_extent); +static int size_str_path(int starting_extent); + +static int gen_str_path(void); + +static int write_str_file(FILE *outfile); +static int write_str_dir(FILE *outfile); +static int write_str_path(FILE *outfile); + +extern struct directory *root; +extern unsigned int session_start; +extern int stream_media_size; +extern char *stream_filename; +extern time_t begun; +extern int volume_sequence_number; + +static unsigned int avail_extent; +static unsigned int stream_extent; +static unsigned int stream_size; +static unsigned int stream_pad; +static char *l_path; +static char *m_path; +static struct iso_directory_record s_dir; +static int stream_finished = 0; + +/* + * Compute the size of the file + */ +static int +size_str_file(int starting_extent) +{ + int n; +extern int dopad; + + stream_extent = last_extent; /* Start of stream file content */ + + avail_extent = stream_media_size; + n = last_extent; /* Room for FS blocks before file */ + n += 1; /* Room for the directory block */ + stream_pad = 0; + if (n < 50) { + stream_pad = 50 - n; + n = 50; /* Make net. size easy to compute */ + } + if (dopad) + n += 150; /* Room for final padding */ + avail_extent -= n; + + last_extent += avail_extent + stream_pad; + + return (0); +} + +/* + * The size of the directory record - one sector + */ +static int +size_str_dir(int starting_extent) +{ + root->extent = last_extent; + last_extent += 1; + return (0); +} + +/* + * The size of the path tables - two sectors + */ +static int +size_str_path(int starting_extent) +{ + path_table[0] = starting_extent; + path_table[1] = 0; + path_table[2] = path_table[0] + 1; + path_table[3] = 0; + last_extent += 2 * 1; + return (0); +} + +/* + * Generate the path table data + */ +static int +gen_str_path() +{ + /* + * Basically add the root directory entry + */ + l_path = (char *)e_malloc(SECTOR_SIZE); + m_path = (char *)e_malloc(SECTOR_SIZE); + memset(l_path, 0, SECTOR_SIZE); + memset(m_path, 0, SECTOR_SIZE); + l_path[0] = 1; + m_path[0] = 1; + set_731(l_path + 2, root->extent); + set_732(m_path + 2, root->extent); + set_721(l_path + 6, 1); + set_722(m_path + 6, 1); + l_path[8] = '\0'; l_path[9] = '\0'; + m_path[8] = '\0'; m_path[9] = '\0'; + return (0); +} + +/* + * Write the file content + */ +static int +write_str_file(FILE *outfile) +{ + unsigned int idx = 0; + unsigned int iso_blocks; + int count; + char *buf; + + buf = e_malloc(SECTOR_SIZE); + stream_size = 0; + while ((idx + SECTOR_SIZE) < (avail_extent * SECTOR_SIZE)) { + memset(buf, 0, SECTOR_SIZE); + count = fread(buf, 1, SECTOR_SIZE, stdin); + if (count <= 0) { + stream_finished = 1; + break; + } + idx += count; + jtwrite(buf, count, 1, 0, FALSE); + xfwrite(buf, count, 1, outfile, 0, FALSE); + } + + stream_size = idx; + iso_blocks = ISO_BLOCKS(idx); + memset(buf, 0, SECTOR_SIZE); + if (SECTOR_SIZE * iso_blocks - idx) + { + jtwrite(buf, SECTOR_SIZE * iso_blocks - idx, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE * iso_blocks - idx, 1, outfile, 0, FALSE); + } + /* + * If we didn't fill the available area, pad to directory block + */ + for (count = 0; count < (avail_extent - iso_blocks); count++) + { + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE); + } + for (count = 0; count < stream_pad; count++) + { + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE); + } + + last_extent_written += avail_extent + stream_pad; + return (0); +} + +/* + * Generate and write the directory record data + */ +static int +write_str_dir(FILE *outfile) +{ + int to_write; + char *buf; + + buf = e_malloc(SECTOR_SIZE); memset(buf, 0, SECTOR_SIZE); + memset(&s_dir, 0, sizeof (struct iso_directory_record)); + s_dir.length[0] = 34; /* BAD: Hardcoded - Will fix, MHV */ + s_dir.ext_attr_length[0] = 0; + set_733((char *)s_dir.extent, root->extent); + set_733((char *)s_dir.size, SECTOR_SIZE); + iso9660_date(s_dir.date, begun); + s_dir.flags[0] = ISO_DIRECTORY; + s_dir.file_unit_size[0] = 0; + s_dir.interleave[0] = 0; + set_723((char *)s_dir.volume_sequence_number, volume_sequence_number); + s_dir.name_len[0] = 1; + s_dir.name[0] = 0; /* "." */ + jtwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, 0, FALSE); + xfwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, outfile, 0, FALSE); + s_dir.name[0] = 1; /* ".." */ + jtwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, 0, FALSE); + xfwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, outfile, 0, FALSE); + memset(&s_dir, 0, sizeof (struct iso_directory_record)); + s_dir.length[0] = 34 + strlen(stream_filename); + s_dir.ext_attr_length[0] = 0; + set_733((char *) s_dir.extent, stream_extent); + set_733((char *) s_dir.size, stream_size); + iso9660_date(s_dir.date, begun); + s_dir.flags[0] = 0; + s_dir.file_unit_size[0] = 0; + set_723((char *)s_dir.volume_sequence_number, volume_sequence_number); + s_dir.name_len[0] = strlen(stream_filename); + memcpy(s_dir.name, stream_filename, s_dir.name_len[0]); + jtwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + + s_dir.name_len[0], 1, 0, FALSE); + xfwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + + s_dir.name_len[0], 1, outfile, 0, FALSE); + + /* + * This calc is: 2 single char directory entries (34) + an additional entry + * with filename length stream_filename + round up for even lenght count + */ + to_write = (s_dir.name_len[0] % 2) ? 0 : 1; + jtwrite(buf, SECTOR_SIZE - ((3 * 34) + s_dir.name_len[0]) + + to_write, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE - ((3 * 34) + s_dir.name_len[0]) + + to_write, 1, outfile, 0, FALSE); + free(buf); + last_extent_written++; + return (0); +} + +/* + * Generate the path table data + */ +static int +write_str_path(FILE *outfile) +{ + jtwrite(l_path, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(l_path, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + jtwrite(m_path, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(m_path, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + free(l_path); + free(m_path); + path_table_l = NULL; + path_table_m = NULL; + return (0); +} + +struct output_fragment strfile_desc = { NULL, size_str_file, NULL, write_str_file, "Stream File" }; +struct output_fragment strdir_desc = { NULL, size_str_dir, NULL, write_str_dir, "Stream File Directory" }; +struct output_fragment strpath_desc = { NULL, size_str_path, gen_str_path, write_str_path, "Stream File Path table" }; diff --git a/genisoimage/sunlabel.h b/genisoimage/sunlabel.h new file mode 100644 index 0000000..243e9bb --- /dev/null +++ b/genisoimage/sunlabel.h @@ -0,0 +1,206 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)sunlabel.h 1.5 03/12/28 Copyright 1999-2003 J. Schilling */ +/* + * Support for Sun disk label + * + * Copyright (c) 1999-2003 J. Schilling + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#ifndef roundup +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#endif + +#define NDKMAP 8 /* # of sparc partitions */ +#define NX86MAP 16 /* # if x86 partitions */ +#define DKL_MAGIC 0xDABE /* magic number */ +#define DKL_MAGIC_0 0xDA /* magic number high byte */ +#define DKL_MAGIC_1 0xBE /* magic number low byte */ + +#define CD_DEFLABEL "CD-ROM Disc with Sun sparc boot created by genisoimage" +#define CD_X86LABEL "CD-ROM Disc with Sun x86 boot created by genisoimage" + +/* + * Define a virtual geometry for the CD disk label. + * The current values are stolen from Sun install disks and do not seem to be + * a good idea as they limit the size of the CD to 327680 sectors which is less + * than 74 minutes. + * There are 84 minute CD's with 378000 sectors and there will be DVD's with + * even more. + */ +#define CD_RPM 350 +#define CD_PCYL 2048 +#define CD_APC 0 +#define CD_INTRLV 1 +#define CD_NCYL 2048 +#define CD_ACYL 0 +#define CD_NHEAD 1 +#define CD_NSECT 640 + +/* + * NOTE: The virtual cylinder size on CD must be a mutiple of 2048. + * This is true if CD_NSECT is a multiple of 4. + */ +#define CD_CYLSIZE (CD_NSECT*CD_NHEAD*512) + +#define V_VERSION 1 /* The VTOC version */ +#define VTOC_SANE 0x600DDEEE /* Indicates a sane VTOC */ + +#define V_ROOT 0x02 /* Root partiton */ +#define V_USR 0x04 /* Usr partiton */ + +#define V_RONLY 0x10 /* Read only */ + +/* + * The Sun sparc disk label (at offset 0 on a disk) + */ +struct sun_label { + char dkl_ascilabel[128]; + struct dk_vtoc { + Uchar v_version[4]; /* layout version */ + char v_volume[8]; /* volume name */ + Uchar v_nparts[2]; /* number of partitions */ + struct dk_map2 { + Uchar p_tag[2]; /* ID tag of partition */ + Uchar p_flag[2]; /* permission flag */ + + } v_part[NDKMAP]; + Uchar v_xxpad[2]; /* To come over Sun's alignement problem */ + Uchar v_bootinfo[3*4]; /* info for mboot */ + Uchar v_sanity[4]; /* to verify vtoc sanity */ + Uchar v_reserved[10*4]; + Uchar v_timestamp[NDKMAP*4]; + + } dkl_vtoc; /* vtoc inclusions from AT&T SVr4 */ + char dkl_pad[512-(128+sizeof (struct dk_vtoc)+NDKMAP*8+14*2)]; + Uchar dkl_rpm[2]; /* rotations per minute */ + Uchar dkl_pcyl[2]; /* # physical cylinders */ + Uchar dkl_apc[2]; /* alternates per cylinder */ + Uchar dkl_obs1[2]; /* obsolete */ + Uchar dkl_obs2[2]; /* obsolete */ + Uchar dkl_intrlv[2]; /* interleave factor */ + Uchar dkl_ncyl[2]; /* # of data cylinders */ + Uchar dkl_acyl[2]; /* # of alternate cylinders */ + Uchar dkl_nhead[2]; /* # of heads in this partition */ + Uchar dkl_nsect[2]; /* # of 512 byte sectors per track */ + Uchar dkl_obs3[2]; /* obsolete */ + Uchar dkl_obs4[2]; /* obsolete */ + + struct dk_map { /* logical partitions */ + Uchar dkl_cylno[4]; /* starting cylinder */ + Uchar dkl_nblk[4]; /* number of blocks */ + } dkl_map[NDKMAP]; /* logical partition headers */ + + Uchar dkl_magic[2]; /* identifies this label format */ + Uchar dkl_cksum[2]; /* xor checksum of sector */ +}; + +/* + * The Sun x86 / AT&T disk label (at offset 512 on a fdisk partition) + */ +struct x86_label { + struct x86_vtoc { + Uchar v_bootinfo[3*4]; /* unsupported */ + Uchar v_sanity[4]; /* to verify vtoc sanity */ + Uchar v_version[4]; /* layout version */ + char v_volume[8]; /* volume name */ + Uchar v_sectorsz[2]; /* # of bytes in a sector */ + Uchar v_nparts[2]; /* # of partitions */ + Uchar v_reserved[10*4]; + struct dkl_partition { + Uchar p_tag[2]; /* ID tag of partition */ + Uchar p_flag[2]; /* permission flag */ + Uchar p_start[4]; /* starting sector */ + Uchar p_size[4]; /* number of blocks */ + } v_part[NX86MAP]; + Uchar timestamp[NX86MAP][4]; + char v_asciilabel[128]; + } dkl_vtoc; /* vtoc inclusions from AT&T SVr4 */ + Uchar dkl_pcyl[4]; /* # physical cylinders */ + Uchar dkl_ncyl[4]; /* # of data cylinders */ + Uchar dkl_acyl[2]; /* # of alternate cylinders */ + Uchar dkl_bcyl[2]; + Uchar dkl_nhead[4]; /* # of heads in this partition */ + Uchar dkl_nsect[4]; /* # of 512 byte sectors per track */ + Uchar dkl_intrlv[2]; /* interleave factor */ + Uchar dkl_skew[2]; + Uchar dkl_apc[2]; /* alternates per cylinder */ + Uchar dkl_rpm[2]; /* rotations per minute */ + Uchar dkl_write_reinstruct[2]; + Uchar dkl_read_reinstruct[2]; + Uchar dkl_extra[4*2]; /* for later expansions */ + char dkl_pad[512-(sizeof (struct x86_vtoc)+4*4+14*2)]; + Uchar dkl_magic[2]; /* identifies this label format */ + Uchar dkl_cksum[2]; /* xor checksum of sector */ +}; + +/* + * One x86 PC fdisk partition record. + */ +struct pc_pr { + Uchar pr_status; /* Boot status */ + Uchar pr_head; /* Starting head # */ + char pr_sec_cyl[2]; /* Starting sec+cyl # */ + Uchar pr_type; /* Partition type */ + Uchar pr_e_head; /* Ending head # */ + char pr_e_sec_cyl[2]; /* Ending sec+cyl # */ + char pr_partoff[4]; /* Partition start sector # */ + char pr_nsect[4]; /* # of sectors in partition */ +}; + +/* + * Flags and macros for above partition record. + */ +#define SEC_MASK 0x3F +#define GET_SEC(a) ((a) & SEC_MASK) +#define GET_CYL(a) ((((a) & 0xFF) >> 8) | (((a) & 0xC0) << 2)) + +#define STATUS_INACT 0 /* Marked non bootable */ +#define STATUS_ACTIVE 0x80 /* Marked as bootable */ + +#define TYPE_FREE 0 /* Unused partition */ +#define TYPE_DOS12 0x01 /* FAT12 fileystem */ +#define TYPE_XENIX 0x02 /* XENIX root */ +#define TYPE_XENIX2 0x03 /* XENIX usr */ +#define TYPE_DOS16 0x04 /* FAT16 filesystem */ +#define TYPE_XDOS 0x05 /* Extended DOS part */ +#define TYPE_DOS4 0x06 /* FAT16 >= 32 MB */ +#define TYPE_SOLARIS 0x82 /* Solaris x86 */ +#define TYPE_SOLARIS_BOOT 0xBE /* Solaris boot */ +#define TYPE_CDOS4 0xDB /* CPM */ + +/* + * The first sector on a disk from a x86 PC (at offset 0 on a disk) + */ +struct pc_part { + char bootcode[0x1BE]; /* Master boot record */ + struct pc_pr part[4]; /* The 4 primary partitions */ + Uchar magic[2]; /* Fixed at 0x55 0xAA */ +}; diff --git a/genisoimage/tree.c b/genisoimage/tree.c new file mode 100644 index 0000000..7805888 --- /dev/null +++ b/genisoimage/tree.c @@ -0,0 +1,2696 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)tree.c 1.82 04/06/12 joerg */ +/* + * File tree.c - scan directory tree and build memory structures for iso9660 + * filesystem + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * Copyright (c) 1999,2000-2004 J. Schilling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ + +/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */ + +#include <mconfig.h> +#include "genisoimage.h" +#include "match.h" +#include "udf.h" +#include "exclude.h" +#include <timedefs.h> +#include <errno.h> +#include <fctldefs.h> +#include <device.h> +#include <schily.h> + +extern int allow_limited_size; + +#ifdef VMS +#include <sys/file.h> +#include <vms/fabdef.h> +#include "vms.h" +#endif + +/* + * Autoconf should be able to figure this one out for us and let us know + * whether the system has memmove or not. + */ +#ifndef HAVE_MEMMOVE +#define memmove(d, s, n) bcopy((s), (d), (n)) +#endif + +static Uchar symlink_buff[PATH_MAX+1]; + +static char *filetype(int t); +static char *rstr(char *s1, char *s2); +static void stat_fix(struct stat * st); +int stat_filter(char *path, struct stat *st); +int lstat_filter(char *path, struct stat *st); +static int sort_n_finish(struct directory *this_dir); +static void generate_reloc_directory(void); +static void attach_dot_entries(struct directory *dirnode, struct stat *dir_stat, + struct stat *parent_stat); +static void update_nlink(struct directory_entry *s_entry, int value); +static void increment_nlink(struct directory_entry *s_entry); +char *find_rr_attribute(unsigned char *pnt, int len, char *attr_type); +void finish_cl_pl_entries(void); +int scan_directory_tree(struct directory *this_dir, char *path, + struct directory_entry *de); +#ifdef APPLE_HYB +int insert_file_entry(struct directory *this_dir, + char *whole_path, + char *short_name, + int have_rsrc); +#else +int insert_file_entry(struct directory *this_dir, + char *whole_path, + char *short_name); +#endif +void generate_iso9660_directories(struct directory *node, + FILE *outfile); +struct directory *find_or_create_directory(struct directory *parent, + const char *path, + struct directory_entry *de, + int flag, + struct stat* stat_template); +static void delete_directory(struct directory *parent, + struct directory *child); +int sort_tree(struct directory *node); +void dump_tree(struct directory *node); +void update_nlink_field(struct directory *node); +struct directory_entry *search_tree_file(struct directory *node, + char *filename); +void init_fstatbuf(void); + +extern int verbose; +struct stat fstatbuf; /* We use this for the artificial */ + /* entries we create */ +struct stat root_statbuf; /* Stat buffer for root directory */ +struct directory *reloc_dir; + +static char * +filetype(int t) +{ + static char unkn[32]; + + if (S_ISFIFO(t)) /* 1 */ + return ("fifo"); + if (S_ISCHR(t)) /* 2 */ + return ("chr"); + if (S_ISMPC(t)) /* 3 */ + return ("multiplexed chr"); + if (S_ISDIR(t)) /* 4 */ + return ("dir"); + if (S_ISNAM(t)) /* 5 */ + return ("named file"); + if (S_ISBLK(t)) /* 6 */ + return ("blk"); + if (S_ISMPB(t)) /* 7 */ + return ("multiplexed blk"); + if (S_ISREG(t)) /* 8 */ + return ("regular file"); + if (S_ISCNT(t)) /* 9 */ + return ("contiguous file"); + if (S_ISLNK(t)) /* 10 */ + return ("symlink"); + if (S_ISSHAD(t)) /* 11 */ + return ("Solaris shadow inode"); + if (S_ISSOCK(t)) /* 12 */ + return ("socket"); + if (S_ISDOOR(t)) /* 13 */ + return ("door"); + if (S_ISWHT(t)) /* 14 */ + return ("whiteout"); + if (S_ISEVC(t)) /* 15 */ + return ("event count"); + + /* + * Needs to be last in case somebody makes this + * a supported file type. + */ + if ((t & S_IFMT) == 0) /* 0 (unallocated) */ + return ("unallocated"); + + sprintf(unkn, "octal '%o'", t & S_IFMT); + return (unkn); +} + +/* + * Check if s1 ends in strings s2 + */ +static char * +rstr(char *s1, char *s2) +{ + int l1; + int l2; + + l1 = strlen(s1); + l2 = strlen(s2); + if (l2 > l1) + return ((char *) NULL); + + if (strcmp(&s1[l1 - l2], s2) == 0) + return (&s1[l1 - l2]); + return ((char *) NULL); +} + +static void +stat_fix(struct stat *st) +{ + int adjust_modes = 0; + + if (S_ISREG(st->st_mode)) + adjust_modes = rationalize_filemode; + else if (S_ISDIR(st->st_mode)) + adjust_modes = rationalize_dirmode; + else + adjust_modes = (rationalize_filemode || rationalize_dirmode); + + /* + * If rationalizing, override the uid and gid, since the + * originals will only be useful on the author's system. + */ + if (rationalize_uid) + st->st_uid = uid_to_use; + if (rationalize_gid) + st->st_gid = gid_to_use; + + if (adjust_modes) { + + if (S_ISREG(st->st_mode) && (filemode_to_use != 0)) { + st->st_mode = filemode_to_use | S_IFREG; + } else if (S_ISDIR(st->st_mode) && (dirmode_to_use != 0)) { + st->st_mode = dirmode_to_use | S_IFDIR; + } else { + /* + * Make sure the file modes make sense. Turn + * on all read bits. Turn on all exec/search + * bits if any exec/search bit is set. Turn + * off all write bits, and all special mode + * bits (on a r/o fs lock bits are useless, + * and with uid+gid 0 don't want set-id bits, + * either). + */ + + st->st_mode |= 0444; +#if !defined(_WIN32) && !defined(__DJGPP__) /* make all file "executable" */ + if (st->st_mode & 0111) +#endif + st->st_mode |= 0111; + st->st_mode &= ~07222; + } + } +} + +int +stat_filter(char *path, struct stat *st) +{ + int result = stat(path, st); + + if (result >= 0 && rationalize) + stat_fix(st); + return (result); +} + +int +lstat_filter(char *path, struct stat *st) +{ + int result = lstat(path, st); + + if (result >= 0 && rationalize) + stat_fix(st); + return (result); +} + +static int +sort_n_finish(struct directory *this_dir) +{ + struct directory_entry *s_entry; + struct directory_entry *s_entry1; + struct directory_entry *table; + int count; + int d1; + int d2; + int d3; + register int new_reclen; + char *c; + int status = 0; + int tablesize = 0; + char newname[MAX_ISONAME+1]; + char rootname[MAX_ISONAME+1]; + char extname[MAX_ISONAME+1]; + + /* + * Here we can take the opportunity to toss duplicate entries from the + * directory. + */ + /* ignore if it's hidden */ + if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY) { + return (0); + } + table = NULL; + + init_fstatbuf(); + + /* + * If we had artificially created this directory, then we might be + * missing the required '.' entries. Create these now if we need + * them. + */ + if ((this_dir->dir_flags & (DIR_HAS_DOT | DIR_HAS_DOTDOT)) != + (DIR_HAS_DOT | DIR_HAS_DOTDOT)) { + fstatbuf.st_mode = new_dir_mode | S_IFDIR; + fstatbuf.st_nlink = 2; + attach_dot_entries(this_dir, &fstatbuf, &fstatbuf); + } + flush_file_hash(); + s_entry = this_dir->contents; + while (s_entry) { + /* ignore if it's hidden */ + if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { + s_entry = s_entry->next; + continue; + } + /* 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; + } +#ifdef APPLE_HYB + /* + * if the pair are associated, then skip (as they have the + * same name!) + */ + if (apple_both && s_entry1->assoc && + s_entry1->assoc == s_entry) { + s_entry = s_entry->next; + continue; + } +#endif /* APPLE_HYB */ + + if (s_entry1 == s_entry) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Fatal goof, file '%s' already in hash table.\n", + s_entry->isorec.name); +#else + fprintf(stderr, + "Fatal goof, file '%s' already in hash table.\n", + s_entry->isorec.name); + exit(1); +#endif + } + /* + * OK, handle the conflicts. Try substitute names until we + * come up with a winner + */ + strcpy(rootname, s_entry->isorec.name); + /* + * Strip off the non-significant part of the name so that we + * are left with a sensible root filename. If we don't find + * a '.', then try a ';'. + */ + c = strchr(rootname, '.'); + /* + * In case we ever allow more than on dot, only modify the + * section past the last dot if the file name starts with a + * dot. + */ + if (c != NULL && c == rootname && c != strrchr(rootname, '.')) { + c = strrchr(rootname, '.'); + } + extname[0] = '\0'; /* In case we have no ext. */ + if (c) { + strcpy(extname, c); + *c = 0; /* Cut off complete ext. */ + } else { + /* + * Could not find any '.'. + */ + c = strchr(rootname, ';'); + if (c) { + *c = 0; /* Cut off version number */ + } + } + c = strchr(extname, ';'); + if (c) { + *c = 0; /* Cut off version number */ + } + d1 = strlen(rootname); + if (full_iso9660_filenames || iso9660_level > 1) { + d2 = strlen(extname); + /* + * 31/37 chars minus the 3 characters we are + * appending below to create unique filenames. + */ + if ((d1 + d2) > (iso9660_namelen - 3)) + rootname[iso9660_namelen - 3 - d2] = 0; + } else { + if (d1 > 5) + rootname[5] = 0; + } + new_reclen = strlen(rootname); + sprintf(newname, "%s000%s%s", + rootname, + extname, + ((s_entry->isorec.flags[0] & ISO_DIRECTORY) || + omit_version_number ? "" : ";1")); + + for (d1 = 0; d1 < 36; d1++) { + for (d2 = 0; d2 < 36; d2++) { + for (d3 = 0; d3 < 36; d3++) { + newname[new_reclen + 0] = + (d1 <= 9 ? '0' + d1 : 'A' + d1 - 10); + newname[new_reclen + 1] = + (d2 <= 9 ? '0' + d2 : 'A' + d2 - 10); + newname[new_reclen + 2] = + (d3 <= 9 ? '0' + d3 : 'A' + d3 - 10); + if (debug) + fprintf(stderr, "NEW name '%s'\n", newname); + +#ifdef VMS + /* Sigh. VAXCRTL seems to be broken here */ + { + int ijk = 0; + + while (newname[ijk]) { + if (newname[ijk] == ' ') + newname[ijk] = '0'; + ijk++; + } + } +#endif + + if (!find_file_hash(newname)) + goto got_valid_name; + } + } + } + + /* If we fell off the bottom here, we were in real trouble. */ +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Unable to generate unique name for file %s\n", + s_entry->name); +#else + fprintf(stderr, + "Unable to generate unique name for file %s\n", + s_entry->name); + exit(1); +#endif + +got_valid_name: + /* + * OK, now we have a good replacement name. Now decide which + * one of these two beasts should get the name changed + */ + if (s_entry->priority < s_entry1->priority) { + if (verbose > 0) { + 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 = offsetof(struct iso_directory_record, + name[0]) + + strlen(newname); + if (use_XA || 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); +#ifdef APPLE_HYB + /* has resource fork - needs new name */ + if (apple_both && s_entry->assoc) { + struct directory_entry *s_entry2 = + s_entry->assoc; + + /* + * resource fork name *should* be the same as + * the data fork + */ + s_entry2->isorec.name_len[0] = + s_entry->isorec.name_len[0]; + strcpy(s_entry2->isorec.name, + s_entry->isorec.name); + s_entry2->isorec.length[0] = new_reclen; + } +#endif /* APPLE_HYB */ + } else { + delete_file_hash(s_entry1); + if (verbose > 0) { + 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 = offsetof(struct iso_directory_record, + name[0]) + + strlen(newname); + if (use_XA || 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); +#ifdef APPLE_HYB + /* has resource fork - needs new name */ + if (apple_both && s_entry1->assoc) { + struct directory_entry *s_entry2 = + s_entry1->assoc; + + /* + * resource fork name *should* be the same as + * the data fork + */ + s_entry2->isorec.name_len[0] = + s_entry1->isorec.name_len[0]; + strcpy(s_entry2->isorec.name, + s_entry1->isorec.name); + s_entry2->isorec.length[0] = new_reclen; + } +#endif /* APPLE_HYB */ + } + add_file_hash(s_entry); + s_entry = s_entry->next; + } + + if (generate_tables && + !find_file_hash(trans_tbl) && + (reloc_dir != this_dir) && + (this_dir->extent == 0)) { + /* First we need to figure out how big this table is */ + for (s_entry = this_dir->contents; s_entry; + s_entry = s_entry->next) { + if (strcmp(s_entry->name, ".") == 0 || + strcmp(s_entry->name, "..") == 0) + continue; +#ifdef APPLE_HYB + /* skip table entry for the resource fork */ + if (apple_both && + (s_entry->isorec.flags[0] & ISO_ASSOCIATED)) + continue; +#endif /* APPLE_HYB */ + if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) + continue; + if (s_entry->table) { + /* + * Max namelen, a space before and a space + * after the iso filename. + */ + tablesize += MAX_ISONAME + 2 + + strlen(s_entry->table); + } + } + } + if (tablesize > 0) { + table = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memset(table, 0, sizeof (struct directory_entry)); + table->table = NULL; + table->next = this_dir->contents; + this_dir->contents = table; + + table->filedir = root; + table->isorec.flags[0] = ISO_FILE; + table->priority = 32768; + iso9660_date(table->isorec.date, fstatbuf.st_mtime); + table->inode = TABLE_INODE; + table->dev = (dev_t) UNCACHED_DEVICE; + set_723(table->isorec.volume_sequence_number, + volume_sequence_number); + set_733((char *) table->isorec.size, tablesize); + table->realsize = tablesize; + table->size = tablesize; + table->filedir = this_dir; + if (jhide_trans_tbl) + table->de_flags |= INHIBIT_JOLIET_ENTRY; +/* table->name = strdup("<translation table>");*/ + table->name = strdup(trans_tbl); + /* + * We use sprintf() to create the strings, for this reason + * we need to add one byte for the null character at the + * end of the string even though we don't use it. + */ + table->table = (char *) e_malloc(ISO_ROUND_UP(tablesize)+1); + memset(table->table, 0, ISO_ROUND_UP(tablesize)+1); + iso9660_file_length(trans_tbl, table, 0); + + if (use_XA || use_RockRidge) { + fstatbuf.st_mode = 0444 | S_IFREG; + fstatbuf.st_nlink = 1; + generate_xa_rr_attributes("", + trans_tbl, table, + &fstatbuf, &fstatbuf, 0); + } + } + /* + * We have now chosen the 8.3 names and we should now know the length + * of every entry in the directory. + */ + for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { + /* skip if it's hidden */ + if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { + continue; + } + new_reclen = strlen(s_entry->isorec.name); + + /* First update the path table sizes for directories. */ + if (s_entry->isorec.flags[0] & ISO_DIRECTORY) { + if (strcmp(s_entry->name, ".") != 0 && + strcmp(s_entry->name, "..") != 0) { + path_table_size += new_reclen + + offsetof(struct iso_path_table, + name[0]); + if (new_reclen & 1) + path_table_size++; + } else { + new_reclen = 1; + if (this_dir == root && strlen(s_entry->name) + == 1) { + path_table_size += new_reclen + + offsetof(struct iso_path_table, + name[0]); + } + } + } + if (path_table_size & 1) + path_table_size++; /* For odd lengths we pad */ + s_entry->isorec.name_len[0] = new_reclen; + + new_reclen += offsetof(struct iso_directory_record, name[0]); + + if (new_reclen & 1) + new_reclen++; + + new_reclen += s_entry->rr_attr_size; + + if (new_reclen & 1) + new_reclen++; + + if (new_reclen > 0xff) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Fatal error - RR overflow (reclen %d) for file %s\n", + new_reclen, + s_entry->name); +#else + fprintf(stderr, + "Fatal error - RR overflow (reclen %d) for file %s\n", + new_reclen, + s_entry->name); + exit(1); +#endif + } + s_entry->isorec.length[0] = new_reclen; + } + + status = sort_directory(&this_dir->contents, (reloc_dir == this_dir)); + if (status > 0) { + fprintf(stderr, "Unable to sort directory %s\n", + this_dir->whole_name); + if(merge_warn_msg) + fprintf(stderr, merge_warn_msg); + exit(1); + } + /* + * If we are filling out a TRANS.TBL, generate the entries that will + * go in the thing. + */ + if (table) { + count = 0; + for (s_entry = this_dir->contents; s_entry; + s_entry = s_entry->next) { + if (s_entry == table) + continue; + if (!s_entry->table) + continue; + if (strcmp(s_entry->name, ".") == 0 || + strcmp(s_entry->name, "..") == 0) + continue; +#ifdef APPLE_HYB + /* skip table entry for the resource fork */ + if (apple_both && + (s_entry->isorec.flags[0] & ISO_ASSOCIATED)) + continue; +#endif /* APPLE_HYB */ + if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) + continue; + /* + * Warning: we cannot use the return value of sprintf + * because old BSD based sprintf() implementations + * will return a pointer to the result instead of a + * count. + * Old mkiofs introduced a space after the iso + * filename to make parsing TRANS.TBL easier. + */ + sprintf(table->table + count, "%c %-*s%s", + s_entry->table[0], + MAX_ISONAME + 1, + s_entry->isorec.name, s_entry->table + 1); + count += strlen(table->table + count); + free(s_entry->table); + /* + * for a memory file, set s_entry->table to the + * correct data - which is stored in + * s_entry->whole_name + */ + if (s_entry->de_flags & MEMORY_FILE) { + s_entry->table = s_entry->whole_name; + s_entry->whole_name = NULL; + } else { + s_entry->table = NULL; + } + } + + if (count != tablesize) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Translation table size mismatch %d %d\n", + count, tablesize); +#else + fprintf(stderr, + "Translation table size mismatch %d %d\n", + count, tablesize); + exit(1); +#endif + } + } + /* + * 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) { + /* skip if it's hidden */ + if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { + s_entry = s_entry->next; + continue; + } + 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; + pnt = parse_xa(pnt, &len, 0); +/* pnt = parse_xa(pnt, &len, s_entry);*/ + + /* + * We make sure that each continuation entry record is + * not split across sectors, but each file could in + * theory have more than one CE, so we scan through + * and figure out what we need. + */ + while (len > 3) { + if (pnt[0] == 'C' && pnt[1] == 'E') { + nbytes = get_733((char *) pnt + 20); + + if ((this_dir->ce_bytes & (SECTOR_SIZE - 1)) + nbytes >= + SECTOR_SIZE) + this_dir->ce_bytes = + ISO_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; + } + return (status); +} + +static void +generate_reloc_directory() +{ + 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; + if (hide_rr_moved) { + reloc_dir->whole_name = strdup("./.rr_moved"); + reloc_dir->de_name = strdup(".rr_moved"); + } else { + reloc_dir->whole_name = strdup("./rr_moved"); + reloc_dir->de_name = strdup("rr_moved"); + } + reloc_dir->extent = 0; + + + /* 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; + + /* The rr_moved entry will not appear in the Joliet tree. */ + reloc_dir->dir_flags |= INHIBIT_JOLIET_ENTRY; + s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; + + /* Hiding RR_MOVED seems not to be possible..... */ +#ifdef HIDE_RR + reloc_dir->dir_flags |= INHIBIT_ISO9660_ENTRY; + s_entry->de_flags |= INHIBIT_ISO9660_ENTRY; +#endif + + root->contents = s_entry; + root->contents->name = strdup(reloc_dir->de_name); + root->contents->filedir = root; + root->contents->isorec.flags[0] = ISO_DIRECTORY; + 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, + volume_sequence_number); + iso9660_file_length(reloc_dir->de_name, root->contents, 1); + + init_fstatbuf(); + + if (use_XA || use_RockRidge) { + fstatbuf.st_mode = 0555 | S_IFDIR; + fstatbuf.st_nlink = 2; + generate_xa_rr_attributes("", + hide_rr_moved ? ".rr_moved" : "rr_moved", + s_entry, &fstatbuf, &fstatbuf, 0); + }; + + /* Now create the . and .. entries in rr_moved */ + /* Now create an actual directory entry */ + memset(&root_statbuf, 0x0, sizeof(struct stat)); /* be sure */ + attach_dot_entries(reloc_dir, &fstatbuf, &root_statbuf); +} + +/* + * Function: attach_dot_entries + * + * Purpose: Create . and .. entries for a new directory. + * + * Arguments: dir_stat contains the ownership/permission information + * for dirnode, and parent_stat contains + * ownership/permission information for its parent + * + * + * Notes: Only used for artificial directories that + * we are creating. + */ +static void +attach_dot_entries(struct directory *dirnode, struct stat *dir_stat, + struct stat *parent_stat) +{ + struct directory_entry *s_entry; + struct directory_entry *orig_contents; + int deep_flag = 0; + + init_fstatbuf(); + + orig_contents = dirnode->contents; + + if ((dirnode->dir_flags & DIR_HAS_DOTDOT) == 0) { + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry, dirnode->self, + sizeof (struct directory_entry)); +#ifdef APPLE_HYB + if (dirnode->self->hfs_ent) { + s_entry->hfs_ent = (hfsdirent *) + e_malloc(sizeof (hfsdirent)); + memcpy(s_entry->hfs_ent, dirnode->self->hfs_ent, + sizeof (hfsdirent)); + } +#endif + s_entry->name = strdup(".."); + s_entry->whole_name = NULL; + s_entry->isorec.name_len[0] = 1; + s_entry->isorec.flags[0] = ISO_DIRECTORY; + iso9660_file_length("..", s_entry, 1); + iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime); + set_723(s_entry->isorec.volume_sequence_number, + volume_sequence_number); + set_733(s_entry->isorec.size, SECTOR_SIZE); + s_entry->realsize = SECTOR_SIZE; + memset(s_entry->isorec.extent, 0, 8); + s_entry->filedir = dirnode->parent; + + dirnode->contents = s_entry; + dirnode->contents->next = orig_contents; + orig_contents = s_entry; + + if (use_XA || use_RockRidge) { + generate_xa_rr_attributes("", + "..", s_entry, + parent_stat, + parent_stat, 0); + } + dirnode->dir_flags |= DIR_HAS_DOTDOT; + } + if ((dirnode->dir_flags & DIR_HAS_DOT) == 0) { + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry, dirnode->self, + sizeof (struct directory_entry)); +#ifdef APPLE_HYB + if (dirnode->self->hfs_ent) { + s_entry->hfs_ent = (hfsdirent *) + e_malloc(sizeof (hfsdirent)); + memcpy(s_entry->hfs_ent, dirnode->self->hfs_ent, + sizeof (hfsdirent)); + } +#endif + s_entry->name = strdup("."); + s_entry->whole_name = NULL; + s_entry->isorec.name_len[0] = 1; + s_entry->isorec.flags[0] = ISO_DIRECTORY; + iso9660_file_length(".", s_entry, 1); + iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime); + set_723(s_entry->isorec.volume_sequence_number, + volume_sequence_number); + set_733(s_entry->isorec.size, SECTOR_SIZE); + s_entry->realsize=SECTOR_SIZE; + memset(s_entry->isorec.extent, 0, 8); + s_entry->filedir = dirnode; + + dirnode->contents = s_entry; + dirnode->contents->next = orig_contents; + + if (use_XA || use_RockRidge) { + + if (dirnode == root) { + deep_flag |= NEED_CE | NEED_SP; /* For extension record */ + } + generate_xa_rr_attributes("", ".", s_entry, + dir_stat, dir_stat, deep_flag); + } + dirnode->dir_flags |= DIR_HAS_DOT; + } +} + +static void +update_nlink(struct directory_entry *s_entry, int value) +{ + unsigned char *pnt; + int len; + + pnt = s_entry->rr_attributes; + len = s_entry->total_rr_attr_size; + pnt = parse_xa(pnt, &len, 0); + while (len >= 4) { + if (pnt[3] != 1 && pnt[3] != 2) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "**BAD RRVERSION (%d) for %c%c\n", + pnt[3], pnt[0], pnt[1]); +#else + fprintf(stderr, + "**BAD RRVERSION (%d) for %c%c\n", + pnt[3], pnt[0], pnt[1]); +#endif + } + if (pnt[0] == 'P' && pnt[1] == 'X') { + set_733((char *) pnt + 12, value); + break; + } + len -= pnt[2]; + pnt += pnt[2]; + } +} + +static void +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; + pnt = parse_xa(pnt, &len, 0); + while (len >= 4) { + if (pnt[3] != 1 && pnt[3] != 2) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "**BAD RRVERSION (%d) for %c%c\n", + pnt[3], pnt[0], pnt[1]); +#else + fprintf(stderr, + "**BAD RRVERSION (%d) for %c%c\n", + pnt[3], pnt[0], pnt[1]); +#endif + } + if (pnt[0] == 'P' && pnt[1] == 'X') { + nlink = get_733((char *) pnt + 12); + set_733((char *) pnt + 12, nlink + 1); + break; + } + len -= pnt[2]; + pnt += pnt[2]; + } +} + +char * +find_rr_attribute(unsigned char *pnt, int len, char *attr_type) +{ + pnt = parse_xa(pnt, &len, 0); + while (len >= 4) { + if (pnt[3] != 1 && pnt[3] != 2) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "**BAD RRVERSION (%d) for %c%c\n", + pnt[3], pnt[0], pnt[1]); +#else + fprintf(stderr, + "**BAD RRVERSION (%d) for %c%c\n", + pnt[3], pnt[0], pnt[1]); +#endif + } + if (strncmp((char *) pnt, attr_type, 2) == 0) + return ((char *) pnt); + else if (strncmp((char *) pnt, "ST", 2) == 0) + return (NULL); + len -= pnt[2]; + pnt += pnt[2]; + } + return (NULL); +} + +void +finish_cl_pl_entries() +{ + struct directory_entry *s_entry; + struct directory_entry *s_entry1; + struct directory *d_entry; + + /* if the reloc_dir is hidden (empty), then return */ + if (reloc_dir->dir_flags & INHIBIT_ISO9660_ENTRY) + return; + + s_entry = reloc_dir->contents; + s_entry = s_entry->next->next; /* Skip past . and .. */ + for (; s_entry; s_entry = s_entry->next) { + /* skip if it's hidden */ + if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { + continue; + } + d_entry = reloc_dir->subdir; + while (d_entry) { + if (d_entry->self == s_entry) + break; + d_entry = d_entry->next; + }; + if (!d_entry) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Unable to locate directory parent\n"); +#else + fprintf(stderr, "Unable to locate directory parent\n"); + exit(1); +#endif + }; + + if (s_entry->filedir != NULL && s_entry->parent_rec != NULL) { + char *rr_attr; + + /* + * First fix the PL pointer in the directory in the + * rr_reloc dir + */ + s_entry1 = d_entry->contents->next; + +/* set_733((char *) s_entry1->rr_attributes +*/ +/* s_entry1->total_rr_attr_size - 8,*/ +/* s_entry->filedir->extent); */ + /* + * The line above won't work when entry was read from + * the previous session, because if total_rr_attr_size + * was odd when recording previous session, now we have + * total_rr_attr_size off by 1 due to padding. + * + * So, just search for the attributes by name + */ + rr_attr = find_rr_attribute(s_entry1->rr_attributes, + s_entry1->total_rr_attr_size, "PL"); + if (rr_attr != NULL) + set_733(rr_attr + 4, s_entry->filedir->extent); + + + /* Now fix the CL pointer */ + s_entry1 = s_entry->parent_rec; + +/* set_733((char *) s_entry1->rr_attributes +*/ +/* s_entry1->total_rr_attr_size - 8, d_entry->extent); */ + rr_attr = find_rr_attribute(s_entry1->rr_attributes, + s_entry1->total_rr_attr_size, "CL"); + if (rr_attr != NULL) + set_733(rr_attr + 4, 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; + }; + + finish_cl_pl_for_prev_session(); +} + +/* + * Function: scan_directory_tree + * + * Purpose: Walk through a directory on the local machine + * filter those things we don't want to include + * and build our representation of a dir. + * + * Notes: + */ +int +scan_directory_tree(struct directory *this_dir, char *path, + struct directory_entry *de) +{ + DIR *current_dir; + char whole_path[PATH_MAX]; + struct dirent *d_entry; + struct directory *parent; + int dflag; + char *old_path; + + if (verbose > 1) { + fprintf(stderr, "Scanning %s\n", path); + } +/*#define check_needed*/ +#ifdef check_needed + /* + * Trying to use this to avoid directory loops from hard links + * or followed symlinks does not work. It would prevent us from + * implementing merge directories. + */ + if (this_dir->dir_flags & DIR_WAS_SCANNED) { + fprintf(stderr, "Already scanned directory %s\n", path); + return (1); /* It's a directory */ + } +#endif + this_dir->dir_flags |= DIR_WAS_SCANNED; + + errno = 0; /* Paranoia */ + current_dir = opendir(path); + d_entry = NULL; + + /* + * Apparently NFS sometimes allows you to open the directory, but then + * refuses to allow you to read the contents. Allow for this + */ + old_path = path; + + if (current_dir) { + errno = 0; + d_entry = readdir(current_dir); + } + + if (!current_dir || !d_entry) { + int ret = 1; + +#ifdef USE_LIBSCHILY + errmsg("Unable to open directory %s\n", path); +#else + fprintf(stderr, "Unable to open directory %s\n", path); +#endif + if (errno == ENOTDIR) { + /* Mark as not a directory */ + de->isorec.flags[0] &= ~ISO_DIRECTORY; + ret = 0; + } + if (current_dir) + closedir(current_dir); + return (ret); + } +#ifdef ABORT_DEEP_ISO_ONLY + if ((this_dir->depth > RR_relocation_depth) && !use_RockRidge) { + static BOOL did_hint = FALSE; + + errmsgno(EX_BAD, + "Directories too deep for '%s' (%d) max is %d; ignored - continuing.\n", + path, this_dir->depth, RR_relocation_depth); + if (!did_hint) { + did_hint = TRUE; + errmsgno(EX_BAD, "To include the complete directory tree,\n"); + errmsgno(EX_BAD, "use Rock Ridge extensions via -R or -r,\n"); + errmsgno(EX_BAD, "or allow deep ISO9660 directory nesting via -D.\n"); + } + closedir(current_dir); + return (1); + } +#endif + + parent = de->filedir; + /* + * Set up the struct for the current directory, and insert it into + * the tree + */ +#ifdef VMS + vms_path_fixup(path); +#endif + + /* + * if entry for this sub-directory is hidden, then hide this directory + */ + if (de->de_flags & INHIBIT_ISO9660_ENTRY) + this_dir->dir_flags |= INHIBIT_ISO9660_ENTRY; + + if (de->de_flags & INHIBIT_JOLIET_ENTRY) + this_dir->dir_flags |= INHIBIT_JOLIET_ENTRY; + +#ifdef SORTING + /* + * set any sort weighting from it's own directory entry - if a + * directory is given a weighting, then all the contents will use + * this as the default weighting + */ + this_dir->sort = de->sort; +#endif /* SORTING */ + + /* + * 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, '~') || + strchr(d_entry->d_name, '#') || + rstr(d_entry->d_name, ".bak")) { + if (verbose > 0) { + fprintf(stderr, + "Ignoring file %s\n", + d_entry->d_name); + } + continue; + } + } +#ifdef APPLE_HYB + if (apple_both) { + /* + * exclude certain HFS type files/directories for the + * time being + */ + if (hfs_exclude(d_entry->d_name)) + continue; + } +#endif /* APPLE_HYB */ + + if (strlen(path) + strlen(d_entry->d_name) + 2 > + sizeof (whole_path)) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, "Path name %s/%s too long.\n", + path, d_entry->d_name); + comerrno(EX_BAD, "Overflow of stat buffer\n"); +#else + fprintf(stderr, "Path name %s/%s too long.\n", + path, d_entry->d_name); + fprintf(stderr, "Overflow of stat buffer\n"); + exit(1); +#endif + }; + + /* 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 (matches(d_entry->d_name) || matches(whole_path)) { + if (verbose > 1) { + fprintf(stderr, + "Excluded by match: %s\n", whole_path); + } + continue; + } + if (generate_tables && + strcmp(d_entry->d_name, trans_tbl) == 0) { + /* + * Ignore this entry. We are going to be generating + * new versions of these files, and we need to ignore + * any originals that we might have found. + */ + if (verbose > 1) { + fprintf(stderr, "Excluded: %s\n", whole_path); + } + continue; + } + /* + * If we already have a '.' or a '..' entry, then don't insert + * new ones. + */ + if (strcmp(d_entry->d_name, ".") == 0 && + this_dir->dir_flags & DIR_HAS_DOT) { + continue; + } + if (strcmp(d_entry->d_name, "..") == 0 && + this_dir->dir_flags & DIR_HAS_DOTDOT) { + continue; + } +#if 0 + if (verbose > 1) + fprintf(stderr, "%s\n", whole_path); +#endif + /* This actually adds the entry to the directory in question.*/ +#ifdef APPLE_HYB + insert_file_entry(this_dir, whole_path, d_entry->d_name, 0); +#else + insert_file_entry(this_dir, whole_path, d_entry->d_name); +#endif /* APPLE_HYB */ + } + closedir(current_dir); + +#ifdef APPLE_HYB + /* + * if we cached the HFS info stuff for this directory, then delete it + */ + if (this_dir->hfs_info) { + del_hfs_info(this_dir->hfs_info); + this_dir->hfs_info = 0; + } +#endif /* APPLE_HYB */ + + return (1); +} + + +/* + * Function: insert_file_entry + * + * Purpose: Insert one entry into our directory node. + * + * Note: + * This function inserts a single entry into the directory. It + * is assumed that all filtering and decision making regarding what + * we want to include has already been made, so the purpose of this + * is to insert one entry (file, link, dir, etc), into this directory. + * Note that if the entry is a dir (or if we are following links, + * and the thing it points to is a dir), then we will scan those + * trees before we return. + */ +#ifdef APPLE_HYB +int +insert_file_entry(struct directory *this_dir, char *whole_path, + char *short_name, int have_rsrc) +#else +int +insert_file_entry(struct directory *this_dir, char *whole_path, + char *short_name) +#endif /* APPLE_HYB */ +{ + struct stat statbuf, + lstatbuf; + struct directory_entry *s_entry, + *s_entry1; + int lstatus; + int status; + int deep_flag; + int no_scandir = 0; + +#ifdef APPLE_HYB + int x_hfs = 0; + int htype = TYPE_NONE; + +#endif /* APPLE_HYB */ + + status = stat_filter(whole_path, &statbuf); + + lstatus = lstat_filter(whole_path, &lstatbuf); + + if ((status == -1) && (lstatus == -1)) { + /* + * This means that the file doesn't exist, or isn't accessible. + * Sometimes this is because of NFS permissions problems. + */ +#ifdef USE_LIBSCHILY + errmsg("Non-existent or inaccessible: %s\n", whole_path); +#else + fprintf(stderr, "Non-existent or inaccessible: %s\n", + whole_path); +#endif + return (0); + } + if (this_dir == root && strcmp(short_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(short_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 = (off_t)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) { +#ifdef USE_LIBSCHILY + /* XXX errno may be wrong! */ + errmsg("Unable to stat file %s - ignoring and continuing.\n", + whole_path); +#else + fprintf(stderr, + "Unable to stat file %s - ignoring and continuing.\n", + whole_path); +#endif + } else { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Symlink %s ignored - continuing.\n", + whole_path); +#else + fprintf(stderr, + "Symlink %s ignored - continuing.\n", + whole_path); +#endif + return (0); /* Non Rock Ridge discs */ + /* - ignore all symlinks */ + } + } + } + /* + * Here we handle a different kind of case. Here we have a + * symlink, but we want to follow symlinks. If we run across + * a directory loop, then we need to pretend that we are not + * following symlinks for this file. If this is the first + * time we have seen this, then make this seem as if there was + * no symlink there in the first place + */ + if (follow_links && + S_ISDIR(statbuf.st_mode)) { + if (strcmp(short_name, ".") && + strcmp(short_name, "..")) { + if (find_directory_hash(statbuf.st_dev, + STAT_INODE(statbuf))) { + if (!use_RockRidge) { + fprintf(stderr, + "Already cached directory seen (%s)\n", + whole_path); + return (0); + } + lstatbuf = statbuf; + /* + * XXX when this line was active, + * XXX genisoimage did not include all + * XXX files if it was called with '-f' + * XXX (follow symlinks). + * XXX Now scan_directory_tree() + * XXX checks if the directory has + * XXX already been scanned via the + * XXX DIR_WAS_SCANNED flag. + */ +/* no_scandir = 1;*/ + } else { + lstatbuf = statbuf; + add_directory_hash(statbuf.st_dev, + STAT_INODE(statbuf)); + } + } + } + /* + * For non-directories, we just copy the stat information over + * so we correctly include this file. + */ + if (follow_links && + !S_ISDIR(statbuf.st_mode)) { + lstatbuf = statbuf; + } + } + /* + * Add directories to the cache so that we don't waste space even if + * we are supposed to be following symlinks. + */ + if (follow_links && + strcmp(short_name, ".") && + strcmp(short_name, "..") && + S_ISDIR(statbuf.st_mode)) { + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + } +#ifdef VMS + if (!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX && + statbuf.st_fab_rfm != FAB$C_STMLF)) { + fprintf(stderr, + "Warning - file %s has an unsupported VMS record" + " format (%d)\n", + whole_path, statbuf.st_fab_rfm); + } +#endif + + if (S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK))) { +#ifdef USE_LIBSCHILY + errmsg("File %s is not readable - ignoring\n", + whole_path); +#else + fprintf(stderr, + "File %s is not readable (errno = %d) - ignoring\n", + whole_path, errno); +#endif + return (0); + } + /* print a warning but don't spam too much */ + if (S_ISREG(lstatbuf.st_mode) && (lstatbuf.st_size >= (off_t)0xFFFFFFFF)) { + static int udf_warned; + + if( !allow_limited_size || verbose>1) + fprintf(stderr, "File %s is larger than 4GiB-1.\n", whole_path); + if( !allow_limited_size) + { + fprintf(stderr, "-allow-limited-size was not specified. There is no way do represent this file size. Aborting.\n"); + exit(1); + } + if(verbose>=1 && ! udf_warned ) { + udf_warned++; + fprintf(stderr, "This size can only be represented in the UDF filesystem.\n" + "Make sure that your clients support and use it.\n" + "ISO9660, Joliet, RockRidge, HFS will display incorrect size.\n"); + } + } + /* + * 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(short_name, ".") && + strcmp(short_name, "..")) { + if (find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) { +#ifdef USE_LIBSCHILY +/* comerrno(EX_BAD,*/ +/* "Directory loop - fatal goof (%s %lx %lu).\n",*/ + errmsgno(EX_BAD, + "Warning: Directory loop (%s dev: %lx ino: %lu).\n", + whole_path, (unsigned long) statbuf.st_dev, + (unsigned long) STAT_INODE(statbuf)); +#else +/* fprintf(stderr,*/ +/* "Directory loop - fatal goof (%s %lx %lu).\n",*/ + fprintf(stderr, + "Warning: Directory loop (%s dev: %lx ino: %lu).\n", + whole_path, (unsigned long) statbuf.st_dev, + (unsigned long) STAT_INODE(statbuf)); +#endif + } + 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)) { + if ( ! (this_dir == root && strcmp(short_name, "..") == 0)) { + fprintf(stderr, + "Unknown file type (%s) %s - ignoring and continuing.\n", + filetype((int) lstatbuf.st_mode), whole_path); + } + return (0); + } + /* Who knows what trash this is - ignore and continue */ + + if (status) { +#ifdef USE_LIBSCHILY + errmsg("Unable to stat file %s - ignoring and continuing.\n", + whole_path); +#else + fprintf(stderr, + "Unable to stat file %s - ignoring and continuing.\n", + whole_path); +#endif + return (0); + } + /* + * Check to see if we have already seen this directory node. If so, + * then we don't create a new entry for it, but we do want to recurse + * beneath it and add any new files we do find. + */ + if (S_ISDIR(statbuf.st_mode)) { + int dflag; + + for (s_entry = this_dir->contents; s_entry; + s_entry = s_entry->next) { + if (strcmp(s_entry->name, short_name) == 0) { + break; + } + } + if (s_entry != NULL && + strcmp(short_name, ".") && + strcmp(short_name, "..")) { + struct directory *child; + + if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) { + for (s_entry = reloc_dir->contents; s_entry; + s_entry = s_entry->next) { + if (strcmp(s_entry->name, short_name) + == 0) { + break; + } + } + child = find_or_create_directory(reloc_dir, + whole_path, + s_entry, 1, NULL); + } else { + child = find_or_create_directory(this_dir, + whole_path, + s_entry, 1, NULL); + /* + * If unable to scan directory, mark this as a + * non-directory + */ + } +/* if (no_scandir)*/ + if (0) + dflag = 1; + else + dflag = scan_directory_tree(child, + whole_path, s_entry); + if (!dflag) { + lstatbuf.st_mode = + (lstatbuf.st_mode & ~S_IFMT) | S_IFREG; + } + return (0); + } + } +#ifdef APPLE_HYB + /* Should we exclude this HFS file ? - only works with -hfs */ + if (!have_rsrc && apple_hyb && strcmp(short_name, ".") && + strcmp(short_name, "..")) { + if ((x_hfs = (hfs_matches(short_name) || + hfs_matches(whole_path))) == 1) { + if (verbose > 1) { + fprintf(stderr, "Hidden from HFS tree: %s\n", + whole_path); + } + } + } + /* + * check we are a file, using Apple extensions and have a .resource + * part and not excluded + */ + if (S_ISREG(lstatbuf.st_mode) && !have_rsrc && apple_both && !x_hfs) { + char rsrc_path[PATH_MAX]; /* rsrc fork filename */ + + /* construct the resource full path */ + htype = get_hfs_rname(whole_path, short_name, rsrc_path); + /* check we can read the resouce fork */ + if (htype) { + struct stat rstatbuf, + rlstatbuf; + + /* some further checks on the file */ + status = stat_filter(rsrc_path, &rstatbuf); + + lstatus = lstat_filter(rsrc_path, &rlstatbuf); + +/* if (!status && !lstatus && S_ISREG(rlstatbuf.st_mode)*/ +/* && rlstatbuf.st_size > (off_t)0) { */ + if (!status && !lstatus && S_ISREG(rstatbuf.st_mode) && + rstatbuf.st_size > (off_t)0) { + + /* + * have a resource file - insert it into the + * current directory but flag that we have a + * resource fork + */ + insert_file_entry(this_dir, rsrc_path, + short_name, htype); + } + } + } +#endif /* APPLE_HYB */ + + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + /* memset the whole struct, not just the isorec.extent part JCP */ + memset(s_entry, 0, sizeof (struct directory_entry)); + s_entry->next = this_dir->contents; +/* memset(s_entry->isorec.extent, 0, 8); */ + this_dir->contents = s_entry; + deep_flag = 0; + s_entry->table = NULL; + + s_entry->name = strdup(short_name); + s_entry->whole_name = strdup(whole_path); + + s_entry->de_flags = 0; + + /* + * If the current directory is hidden, then hide all it's members + * otherwise check if this entry needs to be hidden as well + */ + if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY) { + s_entry->de_flags |= INHIBIT_ISO9660_ENTRY; + } else if (strcmp(short_name, ".") != 0 && strcmp(short_name, "..") + != 0) { + if (i_matches(short_name) || i_matches(whole_path)) { + if (verbose > 1) { + fprintf(stderr, + "Hidden from ISO9660 tree: %s\n", + whole_path); + } + s_entry->de_flags |= INHIBIT_ISO9660_ENTRY; + } + if (h_matches(short_name) || h_matches(whole_path)) { + if (verbose > 1) { + fprintf(stderr, + "Hidden ISO9660 attribute: %s\n", + whole_path); + } + s_entry->de_flags |= HIDDEN_FILE; + } + } + if (this_dir != reloc_dir && + this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) { + s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; + } else if (strcmp(short_name, ".") != 0 && strcmp(short_name, "..") + != 0) { + if (j_matches(short_name) || j_matches(whole_path)) { + if (verbose > 1) { + fprintf(stderr, + "Hidden from Joliet tree: %s\n", + whole_path); + } + s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; + } + } + +#ifdef SORTING + /* inherit any sort weight from parent directory */ + s_entry->sort = this_dir->sort; + +#ifdef DVD_VIDEO + /* + * No use at all to do a sort if we don't make a dvd video/audio + */ + /* + * Assign special weights to VIDEO_TS and AUDIO_TS files. + * This can't be done with sort_matches for two reasons: + * first, we need to match against the destination (DVD) + * path rather than the source path, and second, there are + * about 2400 different file names to check, each needing + * a different priority, and adding that many patterns to + * sort_matches would slow things to a crawl. + */ + + if (dvd_video) { + s_entry->sort = assign_dvd_weights(s_entry->name, this_dir, s_entry->sort); + /* turn on sorting if necessary, regardless of cmd-line options */ + if ((s_entry->sort != this_dir->sort) && do_sort == 0) + do_sort++; + } +#endif + + /* see if this entry should have a new weighting */ + if (do_sort && strcmp(short_name, ".") != 0 && + strcmp(short_name, "..") != 0) { + s_entry->sort = sort_matches(whole_path, s_entry->sort); + } +#endif /* SORTING */ + + s_entry->filedir = this_dir; + s_entry->isorec.flags[0] = ISO_FILE; + if (s_entry->de_flags & HIDDEN_FILE) + s_entry->isorec.flags[0] |= ISO_EXISTENCE; + s_entry->isorec.ext_attr_length[0] = 0; + iso9660_date(s_entry->isorec.date, statbuf.st_mtime); + s_entry->isorec.file_unit_size[0] = 0; + s_entry->isorec.interleave[0] = 0; + +#ifdef APPLE_HYB + if (apple_both && !x_hfs) { + s_entry->hfs_ent = NULL; + s_entry->assoc = NULL; + s_entry->hfs_off = (off_t)0; + s_entry->hfs_type = htype; + if (have_rsrc) { + /* associated (rsrc) file */ + s_entry->isorec.flags[0] |= ISO_ASSOCIATED; + /* set the type of HFS file */ + s_entry->hfs_type = have_rsrc; + /* + * don't want the rsrc file to be included in any + * Joliet tree + */ + s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; + } else if (s_entry->next) { + /* + * if previous entry is an associated file, + * then "link" it to this file i.e. we have a + * data/resource pair + */ + if (s_entry->next->isorec.flags[0] & ISO_ASSOCIATED) { + s_entry->assoc = s_entry->next; + /* share the same HFS parameters */ + s_entry->hfs_ent = s_entry->next->hfs_ent; + s_entry->hfs_type = s_entry->next->hfs_type; + } + } + /* allocate HFS entry if required */ + if (apple_both && strcmp(short_name, ".") && + strcmp(short_name, "..")) { + if (!s_entry->hfs_ent) { + hfsdirent *hfs_ent; + + hfs_ent = + (hfsdirent *) e_malloc(sizeof (hfsdirent)); + + /* fill in the defaults */ + memset(hfs_ent, 0, sizeof (hfsdirent)); + + s_entry->hfs_ent = hfs_ent; + } + /* + * the resource fork is processed first, but the + * data fork's time info is used in preference + * i.e. time info is set from the resource fork + * initially, then it is set from the data fork + */ + if (have_rsrc) { + /* set rsrc size */ + s_entry->hfs_ent->u.file.rsize = lstatbuf.st_size; + /* + * this will be overwritten - but might as + * well set it here ... + */ + s_entry->hfs_ent->crdate = lstatbuf.st_ctime; + s_entry->hfs_ent->mddate = lstatbuf.st_mtime; + } else { + /* set data size */ + s_entry->hfs_ent->u.file.dsize = lstatbuf.st_size; + s_entry->hfs_ent->crdate = lstatbuf.st_ctime; + s_entry->hfs_ent->mddate = lstatbuf.st_mtime; + } + } + } +#endif /* APPLE_HYB */ + + if (strcmp(short_name, ".") == 0) { + this_dir->dir_flags |= DIR_HAS_DOT; + } + if (strcmp(short_name, "..") == 0) { + this_dir->dir_flags |= DIR_HAS_DOTDOT; + } + if (this_dir->parent && + this_dir->parent == reloc_dir && + strcmp(short_name, "..") == 0) { + s_entry->inode = UNCACHED_INODE; + s_entry->dev = (dev_t) UNCACHED_DEVICE; + deep_flag = NEED_PL; + } else +#ifdef APPLE_HYB + if (have_rsrc) { + /* don't want rsrc files to be cached */ + s_entry->inode = UNCACHED_INODE; + s_entry->dev = (dev_t) UNCACHED_DEVICE; + } else +#endif /* APPLE_HYB */ + { + s_entry->inode = STAT_INODE(statbuf); + s_entry->dev = statbuf.st_dev; + } + set_723(s_entry->isorec.volume_sequence_number, + volume_sequence_number); + iso9660_file_length(short_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)) { + 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 = (off_t)0; + statbuf.st_size = (off_t)0; + } else { + s_entry->size = statbuf.st_size; + } + + set_733((char *) s_entry->isorec.size, statbuf.st_size); + s_entry->realsize = statbuf.st_size; + } else { + s_entry->isorec.flags[0] |= ISO_DIRECTORY; + } +#ifdef APPLE_HYB + /* if the directory is HFS excluded, then we don't have an hfs_ent */ + if (apple_both && s_entry->hfs_ent && + (s_entry->isorec.flags[0] & ISO_DIRECTORY)) { + /* get the Mac directory name */ + get_hfs_dir(whole_path, short_name, s_entry); + + /* if required, set ISO directory name from HFS name */ + if (use_mac_name) + iso9660_file_length(s_entry->hfs_ent->name, s_entry, 1); + } +#endif /* APPLE_HYB */ + + if (strcmp(short_name, ".") != 0 && strcmp(short_name, "..") != 0 && + S_ISDIR(statbuf.st_mode) && + this_dir->depth > RR_relocation_depth) { + struct directory *child; + + if (!reloc_dir) + generate_reloc_directory(); + + /* + * Replicate the entry for this directory. The old one will + * stay where it is, and it will be neutered so that it no + * longer looks like a directory. The new one will look like + * a directory, and it will be put in the reloc_dir. + */ + s_entry1 = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry1, s_entry, sizeof (struct directory_entry)); + s_entry1->table = NULL; + s_entry1->name = strdup(this_dir->contents->name); + s_entry1->whole_name = strdup(this_dir->contents->whole_name); + s_entry1->next = reloc_dir->contents; + reloc_dir->contents = s_entry1; + s_entry1->priority = 32768; + s_entry1->parent_rec = this_dir->contents; + set_723(s_entry1->isorec.volume_sequence_number, + volume_sequence_number); + + deep_flag = NEED_RE; + + if (use_XA || use_RockRidge) { + generate_xa_rr_attributes(whole_path, + short_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; + child = find_or_create_directory(reloc_dir, whole_path, + s_entry1, 0, NULL); +/* if (!no_scandir)*/ + if (!0) + scan_directory_tree(child, whole_path, s_entry1); + s_entry1->filedir = this_dir; + + statbuf.st_size = (off_t)0; + statbuf.st_mode &= 0777; + set_733((char *) s_entry->isorec.size, 0); + s_entry->realsize=0; + s_entry->size = 0; + s_entry->isorec.flags[0] = ISO_FILE; + s_entry->inode = UNCACHED_INODE; + s_entry->de_flags |= RELOCATED_DIRECTORY; + deep_flag = NEED_CL; + } + if (generate_tables && + strcmp(s_entry->name, ".") != 0 && + strcmp(s_entry->name, "..") != 0) { + + char buffer[SECTOR_SIZE]; + int nchar; + + switch (lstatbuf.st_mode & S_IFMT) { + case S_IFDIR: + sprintf(buffer, "D\t%s\n", + s_entry->name); + break; + +/* + * extra for WIN32 - if it doesn't have the major/minor defined, then + * S_IFBLK and S_IFCHR type files are unlikely to exist anyway ... + * code similar to that in rock.c + */ +#if 0 +/* + * Use the device handling code from <device.h> + */ +#ifndef major +#define major(dev) (sizeof (dev_t) <= 2 ? ((dev) >> 8) : \ + (sizeof (dev_t) <= 4 ? (((dev) >> 8) >> 8) : \ + (((dev) >> 16) >> 16))) +#define minor(dev) (sizeof (dev_t) <= 2 ? (dev) & 0xff : \ + (sizeof (dev_t) <= 4 ? (dev) & 0xffff : \ + (dev) & 0xffffffff)) +#endif +#endif + +#ifdef S_IFBLK + case S_IFBLK: + sprintf(buffer, "B\t%s\t%lu %lu\n", + s_entry->name, + (unsigned long) major(statbuf.st_rdev), + (unsigned long) minor(statbuf.st_rdev)); + break; +#endif +#ifdef S_IFIFO + case S_IFIFO: + sprintf(buffer, "P\t%s\n", + s_entry->name); + break; +#endif +#ifdef S_IFCHR + case S_IFCHR: + sprintf(buffer, "C\t%s\t%lu %lu\n", + s_entry->name, + (unsigned long) major(statbuf.st_rdev), + (unsigned long) minor(statbuf.st_rdev)); + break; +#endif +#ifdef S_IFLNK + case S_IFLNK: +#ifdef HAVE_READLINK + nchar = readlink(whole_path, + (char *) symlink_buff, + sizeof (symlink_buff)-1); +#else + nchar = -1; +#endif + symlink_buff[nchar < 0 ? 0 : nchar] = 0; + sprintf(buffer, "L\t%s\t%s\n", + s_entry->name, symlink_buff); + break; +#endif +#ifdef S_IFSOCK + case S_IFSOCK: + sprintf(buffer, "S\t%s\n", + s_entry->name); + break; +#endif + 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(short_name, ".") != 0 && strcmp(short_name, "..") + != 0) { + struct directory *child; + + child = find_or_create_directory(this_dir, whole_path, + s_entry, 1, NULL); + if (no_scandir) + dflag = 1; + else + dflag = scan_directory_tree(child, whole_path, + s_entry); + + if (!dflag) { + lstatbuf.st_mode = + (lstatbuf.st_mode & ~S_IFMT) | S_IFREG; + if (child->contents == NULL) { + delete_directory(this_dir, child); + } + } + } + /* If unable to scan directory, mark this as a non-directory */ + } + 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 */ + +#ifdef APPLE_HYB + /* if the file is HFS excluded, then we don't have an hfs_ent */ + if (apple_both && !have_rsrc && s_entry->hfs_ent) { + if (S_ISREG(lstatbuf.st_mode)) { /* it's a regular file */ + + /* fill in the rest of the HFS entry */ + get_hfs_info(whole_path, short_name, s_entry); + + /* if required, set ISO directory name from HFS name */ + if (use_mac_name) + iso9660_file_length(s_entry->hfs_ent->name, + s_entry, 0); + + /* print details about the HFS file */ + if (verbose > 2) + print_hfs_info(s_entry); + + /* + * copy the new ISO9660 name to the rsrc fork + * - if it exists + */ + if (s_entry->assoc) + strcpy(s_entry->assoc->isorec.name, + s_entry->isorec.name); + + /* + * we can't handle hard links in the hybrid case, so we + * "uncache" the file. The downside to this is that + * hard linked files are added to the output image + * more than once (we've already done this for rsrc + * files) + */ + if (apple_hyb) { + s_entry->inode = UNCACHED_INODE; + s_entry->dev = (dev_t) UNCACHED_DEVICE; + } + } else if (!(s_entry->isorec.flags[0] & ISO_DIRECTORY)) { + /* not a directory .. */ + + /* + * no mac equivalent, so ignore - have to be careful + * here, the hfs_ent may be also be for a relocated + * directory + */ + if (s_entry->hfs_ent && + !(s_entry->de_flags & RELOCATED_DIRECTORY)) + free(s_entry->hfs_ent); + s_entry->hfs_ent = NULL; + } + /* + * if the rsrc size is zero, then we don't need the entry, so + * we might as well delete it - this will only happen if we + * didn't know the rsrc size from the rsrc file size + */ + if (s_entry->assoc && s_entry->assoc->size == 0) + delete_rsrc_ent(s_entry); + } + if (apple_ext && s_entry->assoc) { + /* need Apple extensions for the resource fork as well */ + generate_xa_rr_attributes(whole_path, + short_name, s_entry->assoc, + &statbuf, &lstatbuf, deep_flag); + } + /* leave out resource fork for the time being */ + /* + * XXX This is most likely wrong and should just be: + * XXX if (use_XA || use_RockRidge) { + */ +/* if ((use_XA || use_RockRidge) && !have_rsrc) {*/ + if (use_XA || use_RockRidge) { +#else + if (use_XA || use_RockRidge) { +#endif /* APPLE_HYB */ + generate_xa_rr_attributes(whole_path, + short_name, s_entry, + &statbuf, &lstatbuf, deep_flag); + + } + return (1); +} + + +void +generate_iso9660_directories(struct directory *node, FILE *outfile) +{ + struct directory *dpnt; + + dpnt = node; + + while (dpnt) { + if (dpnt->extent > session_start) { + generate_one_directory(dpnt, outfile); + } + if (dpnt->subdir) + generate_iso9660_directories(dpnt->subdir, outfile); + dpnt = dpnt->next; + } +} + +/* + * Function: find_or_create_directory + * + * Purpose: Locate a directory entry in the tree, create if needed. + * If a directory is created and stat_template is non-null, + * create the directory with ownership, permissions, etc., + * from stat_template, otherwise use fallback defaults. + * + * Arguments: parent & de are never NULL at the same time. + */ +struct directory * +find_or_create_directory(struct directory *parent, + const char *path, + struct directory_entry *de, + int flag, + struct stat *stat_template) +{ + struct directory *dpnt; + struct directory_entry *orig_de; + struct directory *next_brother; + const char *cpnt; + const char *pnt; + struct stat my_statbuf; + + orig_de = de; + + /* + * XXX It seems that the tree that has been read from the + * XXX previous session does not carry whole_name entries. + * XXX We provide a hack in multi.c:find_or_create_directory() + * XXX that should be removed when a reasonable method could + * XXX be found. + */ + if (path == NULL) { + fprintf(stderr, "Warning: missing whole name for: '%s'\n", de->name); + path = de->name; + } + pnt = strrchr(path, PATH_SEPARATOR); + if (pnt == NULL) { + pnt = path; + } else { + pnt++; + } + + if (parent != NULL) { + dpnt = parent->subdir; + + while (dpnt) { + /* + * Weird hack time - if there are two directories by + * the same name in the reloc_dir, they are not + * treated as the same thing unless the entire path + * matches completely. + */ + if (flag && strcmp(dpnt->de_name, pnt) == 0) { + return (dpnt); + } + dpnt = dpnt->next; + } + } + /* + * We don't know if we have a valid directory entry for this one yet. + * If not, we need to create one. + */ + if (de == NULL) { + de = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memset(de, 0, sizeof (struct directory_entry)); + de->next = parent->contents; + parent->contents = de; + de->name = strdup(pnt); + de->whole_name = strdup(path); + de->filedir = parent; + de->isorec.flags[0] = ISO_DIRECTORY; + de->priority = 32768; + de->inode = UNCACHED_INODE; + de->dev = (dev_t) UNCACHED_DEVICE; + set_723(de->isorec.volume_sequence_number, + volume_sequence_number); + iso9660_file_length(pnt, de, 1); + + /* + * If we were given a stat template, use it for + * ownership/permissions, otherwise use fallback defaults. + */ + init_fstatbuf(); + if (stat_template) { + my_statbuf = *stat_template; + } else { + my_statbuf = fstatbuf; /* defaults */ + my_statbuf.st_mode = new_dir_mode; + } + my_statbuf.st_mode &= ~S_IFMT; /* zero out file type */ + my_statbuf.st_mode |= S_IFDIR; /* force to be a directory */ + my_statbuf.st_nlink = 2; + + /* + * Apply attributes from my_statbuf to the new directory. + */ + if (use_XA || use_RockRidge) { + generate_xa_rr_attributes("", (char *) pnt, de, + &my_statbuf, &my_statbuf, 0); + } + iso9660_date(de->isorec.date, fstatbuf.st_mtime); +#ifdef APPLE_HYB + if (apple_both) { + /* give the directory an HFS entry */ + hfsdirent *hfs_ent; + + hfs_ent = (hfsdirent *) e_malloc(sizeof (hfsdirent)); + + /* fill in the defaults */ + memset(hfs_ent, 0, sizeof (hfsdirent)); + hfs_ent->crdate = my_statbuf.st_ctime; + hfs_ent->mddate = my_statbuf.st_mtime; + + de->hfs_ent = hfs_ent; + + /* get the Mac directory name */ + get_hfs_dir((char *) path, (char *) pnt, de); + } +#endif /* APPLE_HYB */ + } + /* + * If we don't have a directory for this one yet, then allocate it now, + * and patch it into the tree in the appropriate place. + */ + dpnt = (struct directory *) e_malloc(sizeof (struct directory)); + memset(dpnt, 0, sizeof (struct directory)); + dpnt->next = NULL; + dpnt->subdir = NULL; + dpnt->self = de; + dpnt->contents = NULL; + dpnt->whole_name = strdup(path); + cpnt = strrchr(path, PATH_SEPARATOR); + if (cpnt) + cpnt++; + else + cpnt = path; + dpnt->de_name = strdup(cpnt); + dpnt->size = 0; + dpnt->extent = 0; + dpnt->jextent = 0; + dpnt->jsize = 0; +#ifdef APPLE_HYB + dpnt->hfs_ent = de->hfs_ent; +#endif /* APPLE_HYB */ + + if (orig_de == NULL) { + struct stat xstatbuf; + struct stat parent_statbuf; + int sts; + + /* + * Now add a . and .. entry in the directory itself. This is a + * little tricky - if the real directory exists, we need to + * stat it first. Otherwise, we use the fictitious fstatbuf + * which points to the time at which genisoimage was started. + */ + if (parent == NULL || parent->whole_name[0] == '\0') + sts = -1; + else + sts = stat_filter(parent->whole_name, &parent_statbuf); + + if (sts != 0) { + parent_statbuf = fstatbuf; + parent_statbuf.st_mode = new_dir_mode | S_IFDIR; + parent_statbuf.st_nlink = 2; + } + + if (debug && parent) { + fprintf(stderr, "stat parent->whole_name: '%s' -> %d.\n", + parent->whole_name, sts); + } + attach_dot_entries(dpnt, &my_statbuf, &parent_statbuf); + } + if (!parent || parent == root) { + if (!root) { + root = dpnt; /* First time through for root */ + /* directory only */ + root->depth = 0; + root->parent = root; + } else { + dpnt->depth = 1; + if (!root->subdir) { + root->subdir = dpnt; + } else { + next_brother = root->subdir; + while (next_brother->next) + next_brother = next_brother->next; + next_brother->next = dpnt; + } + dpnt->parent = parent; + } + } else { + /* Come through here for normal traversal of tree */ +#ifdef DEBUG + fprintf(stderr, "%s(%d) ", path, dpnt->depth); +#endif + if (parent->depth > RR_relocation_depth) { + /* + * XXX to prevent this, we would need to add + * XXX support for RR directory relocation + * XXX to find_or_create_directory() + */ +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Directories too deep for '%s' (%d) max is %d.\n", + path, parent->depth, RR_relocation_depth); +#else + fprintf(stderr, + "Directories too deep for '%s' (%d) max is %d.\n", + path, parent->depth, RR_relocation_depth); + exit(1); +#endif + } + dpnt->parent = parent; + dpnt->depth = parent->depth + 1; + + if (!parent->subdir) { + parent->subdir = dpnt; + } else { + next_brother = parent->subdir; + while (next_brother->next) + next_brother = next_brother->next; + next_brother->next = dpnt; + } + } + + return (dpnt); +} + +/* + * Function: delete_directory + * + * Purpose: Locate a directory entry in the tree, create if needed. + * + * Arguments: + */ +static void +delete_directory(parent, child) + struct directory *parent; + struct directory *child; +{ + struct directory *tdir; + + if (child->contents != NULL) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Unable to delete non-empty directory\n"); +#else + fprintf(stderr, "Unable to delete non-empty directory\n"); + exit(1); +#endif + } + free(child->whole_name); + child->whole_name = NULL; + + free(child->de_name); + child->de_name = NULL; + +#ifdef APPLE_HYB + if (apple_both && child->hfs_ent) + free(child->hfs_ent); +#endif /* APPLE_HYB */ + + if (parent->subdir == child) { + parent->subdir = child->next; + } else { + for (tdir = parent->subdir; tdir->next != NULL; + tdir = tdir->next) { + if (tdir->next == child) { + tdir->next = child->next; + break; + } + } + if (tdir == NULL) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Unable to locate child directory in parent list\n"); +#else + fprintf(stderr, + "Unable to locate child directory in parent list\n"); + exit(1); +#endif + } + } + free(child); +} + +int +sort_tree(struct directory *node) +{ + struct directory *dpnt; + int ret = 0; + + dpnt = node; + + while (dpnt) { + ret = sort_n_finish(dpnt); + if (ret) { + break; + } + if (dpnt->subdir) + sort_tree(dpnt->subdir); + dpnt = dpnt->next; + } + return (ret); +} + +void +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; + } +} + +void +update_nlink_field(struct directory *node) +{ + struct directory *dpnt; + struct directory *xpnt; + struct directory_entry *s_entry; + int i; + + dpnt = node; + + while (dpnt) { + if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) { + dpnt = dpnt->next; + continue; + } + /* + * First, count up the number of subdirectories this guy has. + */ + for (i = 0, xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next) + if ((xpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0) + i++; + /* + * Next check to see if we have any relocated directories in + * this directory. The nlink field will include these as + * real directories when they are properly relocated. + * In the non-rockridge disk, the relocated entries appear as + * zero length files. + */ + for (s_entry = dpnt->contents; s_entry; + s_entry = s_entry->next) { + if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0 && + (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == + 0) { + i++; + } + } + /* Now update the field in the Rock Ridge entry. */ + update_nlink(dpnt->self, i + 2); + + /* Update the '.' entry for this directory. */ + update_nlink(dpnt->contents, i + 2); + + /* Update all of the '..' entries that point to this guy. */ + for (xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next) + update_nlink(xpnt->contents->next, i + 2); + + if (dpnt->subdir) + update_nlink_field(dpnt->subdir); + dpnt = dpnt->next; + } +} + +/* + * something quick and dirty to locate a file given a path + * recursively walks down path in filename until it finds the + * directory entry for the desired file + */ +struct directory_entry * +search_tree_file(struct directory *node, char *filename) +{ + struct directory_entry *depnt; + struct directory *dpnt; + char *p1; + char *rest; + char *subdir; + + /* strip off next directory name from filename */ + subdir = strdup(filename); + + if ((p1 = strchr(subdir, '/')) == subdir) { + fprintf(stderr, + "call to search_tree_file with an absolute path, stripping\n"); + fprintf(stderr, + "initial path separator. Hope this was intended...\n"); + memmove(subdir, subdir + 1, strlen(subdir) - 1); + p1 = strchr(subdir, '/'); + } + /* do we need to find a subdirectory */ + if (p1) { + *p1 = '\0'; + +#ifdef DEBUG_TORITO + fprintf(stderr, "Looking for subdir called %s\n", p1); +#endif + + rest = p1 + 1; + +#ifdef DEBUG_TORITO + fprintf(stderr, "Remainder of path name is now %s\n", rest); +#endif + + dpnt = node->subdir; + while (dpnt) { +#ifdef DEBUG_TORITO + fprintf(stderr, + "%4d %5d %s\n", dpnt->extent, dpnt->size, + dpnt->de_name); +#endif + if (strcmp(subdir, dpnt->de_name) == 0) { +#ifdef DEBUG_TORITO + fprintf(stderr, + "Calling next level with filename = %s", rest); +#endif + return (search_tree_file(dpnt, rest)); + } + dpnt = dpnt->next; + } + + /* if we got here means we couldnt find the subdir */ + return (NULL); + } else { + /* look for a normal file now */ + depnt = node->contents; + while (depnt) { +#ifdef DEBUG_TORITO + fprintf(stderr, "%4d %5d %s\n", depnt->isorec.extent, + depnt->size, depnt->name); +#endif + if (strcmp(filename, depnt->name) == 0) { +#ifdef DEBUG_TORITO + fprintf(stderr, "Found our file %s", filename); +#endif + return (depnt); + } + depnt = depnt->next; + } + /* if we got here means we couldnt find the subdir */ + return (NULL); + } +#ifdef ERIC_FUN + fprintf(stderr, "We cant get here in search_tree_file :-/ \n"); +#endif +} + +void +init_fstatbuf() +{ + time_t current_time; + + if (fstatbuf.st_ctime == 0) { + time(¤t_time); + if (rationalize_uid) + fstatbuf.st_uid = uid_to_use; + else + fstatbuf.st_uid = getuid(); + if (rationalize_gid) + fstatbuf.st_gid = gid_to_use; + else + fstatbuf.st_gid = getgid(); + fstatbuf.st_ctime = current_time; + fstatbuf.st_mtime = current_time; + fstatbuf.st_atime = current_time; + } +} diff --git a/genisoimage/udf.c b/genisoimage/udf.c new file mode 100644 index 0000000..c63d372 --- /dev/null +++ b/genisoimage/udf.c @@ -0,0 +1,1213 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)udf.c 1.14 04/04/15 Copyright 2001 J. Schilling */ +/* + * udf.c - UDF support for genisoimage + * + * Written by Ben Rudiak-Gould (2001). + * + * Copyright 2001 J. Schilling. + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Some remaining issues: + * + * - Do not forget to edit joliet.c and remove the VIDEO_TS lines after + * we did implement a decent own file name handling for UDF. + * + * - UDF supports UNIX-style file permissions and uid/gid, but currently + * this code just sets them to default values and ignores their Rock + * Ridge counterparts. This would be easy to fix. + * + * - There's no support for symlinks, Mac type/creator, or Mac resource + * forks. Hard links and followed symlinks may work, but if so, it's + * only by accident. + * + * - The file system mirrors the Joliet file system, so files excluded + * from Joliet will also be excluded from UDF, the -jcharset option + * also applies to UDF, file names too long for Joliet will also be + * truncated on UDF, and characters not allowed by Joliet will also + * be translated on UDF. (Fortunately, Joliet is pretty lenient.) + * + * - convert_to_unicode is always called with in_nls, not hfs_nls. This + * may lead to incorrect name conversion sometimes when using a Mac + * filesystem. See joliet.c for an example of what's supposed to be + * done. + * + * - DVD-Video discs are supposed to have Copyright Management Information + * in both the ISO and UDF filesystems. This is not implemented in ISO, + * and the code to do it in UDF is currently #ifdef'd out. I'm not sure + * whether discs without this information are actually DVD-Video + * compliant. The Copyright Management Information is described in ECMA + * Technical Report TR/71. + * + * - Most of the space before sector 256 on the disc (~480K) is wasted, + * because UDF Bridge requires a pointer block at sector 256. ISO 9660 + * structures could be moved below sector 256 if they're small enough, but + * this would be ugly to implement since it breaks the output_fragment + * abstraction. + * + * - Each file must have a File Entry, and each File Entry seems to + * require its own 2K sector. As a result, there is an overhead of more + * than 2K *per file* when using UDF. I couldn't see any way to avoid + * this. + * + * - Read performance would probably be improved by placing the File Entry + * for each file just before the file itself, instead of at the beginning + * of the disc. But this would not work for DVD-Video files, which have + * to be stored contiguously. So there would have to be an override + * mechanism to handle this case. I don't know if it's worth the trouble. + */ + +#ifdef UDF + +#include "config.h" +#include "genisoimage.h" +#include <timedefs.h> +#include <schily.h> + +#include "udf.h" +#include "udf_fs.h" + +extern int use_sparcboot; + +extern struct directory *root; +extern time_t begun; + +static unsigned lba_main_seq; +static unsigned lba_main_seq_copy; +static unsigned lba_integ_seq; +static unsigned lba_udf_partition_start; +static unsigned lba_last_file_entry; +static unsigned lba_end_anchor_vol_desc; + +static unsigned num_udf_files; +static unsigned num_udf_directories; + +static unsigned volume_set_id[2]; + +#define UDF_MAIN_SEQ_LENGTH (16) +#define UDF_INTEG_SEQ_LENGTH (2) + +/* only works for granularity a power of 2! */ +#define PAD(val, granularity) (((val)+(granularity)-1)&~((granularity)-1)) + +#define read_733(field) ((0[field]&255)+(1[field]&255)*256+(2[field]&255)*65536+(3[field]&255)*16777216) + + +/**************** SIZE ****************/ + +static int set_file_ident_desc(unsigned char *, unsigned, char *, int, + unsigned, unsigned); + +static unsigned +directory_size(struct directory *dpnt) +{ + unsigned size_in_bytes; + struct directory_entry *de; + Uchar dummy_buf[SECTOR_SIZE]; + + /* parent directory */ + size_in_bytes = set_file_ident_desc(dummy_buf, 0, 0, 0, 0, 0); + + /* directory contents */ + for (de = dpnt->jcontents; de; de = de->jnext) { + if (!(de->de_flags & INHIBIT_JOLIET_ENTRY)) { + char *name = USE_MAC_NAME(de) ? de->hfs_ent->name : de->name; + /* skip . and .. */ + if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + continue; + size_in_bytes += set_file_ident_desc(dummy_buf, 0, name, 0, 0, 0); + } + } + return (size_in_bytes); +} + +static void +assign_udf_directory_addresses(struct directory *dpnt) +{ + if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) { + dpnt->self->udf_file_entry_sector = last_extent; + last_extent += 1 + ISO_BLOCKS(directory_size(dpnt)); + ++num_udf_directories; + } + if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) { + for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) { + assign_udf_directory_addresses(dpnt); + } + } +} + +static void +assign_udf_file_entry_addresses(struct directory *dpnt) +{ + if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) { + struct directory_entry *de; + for (de = dpnt->jcontents; de; de = de->jnext) { + if (!(de->de_flags & RELOCATED_DIRECTORY) && + !(de->isorec.flags[0] & ISO_DIRECTORY)) { + de->udf_file_entry_sector = last_extent++; + ++num_udf_files; + } + } + } + if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) { + for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) { + assign_udf_file_entry_addresses(dpnt); + } + } +} + +/****************************/ + +static int +udf_vol_recognition_area_size(int starting_extent) +{ + last_extent = starting_extent+3; + return (0); +} + +static int +udf_main_seq_size(int starting_extent) +{ + lba_main_seq = starting_extent; + last_extent = starting_extent + UDF_MAIN_SEQ_LENGTH; + return (0); +} + +static int +udf_main_seq_copy_size(int starting_extent) +{ + lba_main_seq_copy = starting_extent; + last_extent = starting_extent + UDF_MAIN_SEQ_LENGTH; + return (0); +} + +static int +udf_integ_seq_size(int starting_extent) +{ + lba_integ_seq = starting_extent; + last_extent = starting_extent + UDF_INTEG_SEQ_LENGTH; + return (0); +} + +static int +udf_end_anchor_vol_desc_size(int starting_extent) +{ + lba_end_anchor_vol_desc = starting_extent; + last_extent = starting_extent+1; + return (0); +} + +static int +udf_file_set_desc_size(int starting_extent) +{ + lba_udf_partition_start = starting_extent; + last_extent = starting_extent+2; + return (0); +} + +static int +udf_dirtree_size(int starting_extent) +{ + num_udf_directories = 0; + assign_udf_directory_addresses(root); + return (0); +} + +static int +udf_file_entries_size(int starting_extent) +{ + num_udf_files = 0; + assign_udf_file_entry_addresses(root); + lba_last_file_entry = last_extent-1; + return (0); +} + +static int +udf_pad_to_sector_32_size(int starting_extent) +{ + if (last_extent < session_start+32) + last_extent = session_start+32; + return (0); +} + +static int +udf_pad_to_sector_256_size(int starting_extent) +{ + if (last_extent < session_start+256) + last_extent = session_start+256; + return (0); +} + +static int +udf_padend_avdp_size(int starting_extent) +{ + lba_end_anchor_vol_desc = starting_extent; + + /* add at least 16 and at most 31 sectors, ending at a mult. of 16 */ + last_extent = (starting_extent+31) & ~15; + if (!use_sparcboot) + last_extent = starting_extent + 150; + return (0); +} + +extern int oneblock_size(int); + +/**************** WRITE ****************/ + +static unsigned +crc_ccitt(unsigned char *buf, unsigned len) +{ + const unsigned poly = 0x11021; + static unsigned short lookup[256]; + unsigned int r; + unsigned int i; + + if (lookup[1] == 0) { + unsigned int j, k; + for (j = 0; j < 256; ++j) { + unsigned int temp = j << 8; + for (k = 0; k < 8; ++k) { + unsigned int hibit = temp & 32768; + temp <<= 1; + if (hibit) + temp ^= poly; + } + lookup[j] = temp; + } + } + + r = 0; + for (i = 0; i < len; ++i) { + r = (r << 8) ^ lookup[((r >> 8) ^ buf[i]) & 255]; + } + + return (r & 65535); +} + +#define set8(dst, src) do { *(dst) = (src); } while (0) + +static void +set16(udf_Uint16 *dst, unsigned int src) +{ + dst->l = (char)(src); + dst->h = (char)(src>>8); +} + +static void +set32(udf_Uint32 *dst, unsigned src) +{ + dst->l = (char)(src); + dst->ml = (char)(src>>8); + dst->mh = (char)(src>>16); + dst->h = (char)(src>>24); +} + +static void +set64(udf_Uint64 *dst, uint64_t src) +{ + set32(&dst->l, src); + set32(&dst->h, src>>32); +} + +static int +set_ostaunicode(unsigned char *dst, int dst_size, char *src) +{ + unsigned char buf[1024]; + int i; + int expanded_length; + + expanded_length = joliet_strlen(src, in_nls); + if (expanded_length > 1024) + expanded_length = 1024; + if (expanded_length > (dst_size-1)*2) + expanded_length = (dst_size-1)*2; + + convert_to_unicode(buf, expanded_length, src, in_nls); + dst[0] = 8; /* use 8-bit representation by default */ + for (i = 0; i < (expanded_length>>1); ++i) { + dst[i + 1] = buf[i*2+1]; + if (buf[i*2] != 0) { + /* + * There's a Unicode character with value >=256. + * Use 16-bit representation instead. + */ + int length_to_copy = (dst_size-1) & ~1; + if (length_to_copy > expanded_length) + length_to_copy = expanded_length; + dst[0] = 16; + memcpy(dst+1, buf, length_to_copy); + return (length_to_copy + 1); + } + } + return ((expanded_length>>1) + 1); +} + +static void +set_extent(udf_extent_ad *ext, unsigned lba, unsigned length_bytes) +{ + set32(&ext->extent_length, length_bytes); + set32(&ext->extent_location, lba); +} + +static void +set_dstring(udf_dstring *dst, char *src, int n) +{ + dst[n-1] = set_ostaunicode((Uchar *)dst, n-1, src); +} + +static void +set_charspec(udf_charspec *dst) +{ + /*set8(&dst->character_set_type, 0);*/ + memcpy(dst->character_set_info, "OSTA Compressed Unicode", 23); +} + +static void +set_impl_ident(udf_EntityID *ent) +{ + strcpy((char *)ent->ident, "*genisoimage"); +} + +static void +set_tag(udf_tag *t, unsigned tid, unsigned lba, int crc_length) +{ + unsigned char checksum; + int i; + + set16(&t->tag_ident, tid); + set16(&t->desc_version, 2); + set16(&t->desc_crc, crc_ccitt((unsigned char *)t+16, crc_length-16)); + set16(&t->desc_crc_length, crc_length-16); + set32(&t->tag_location, lba); + set8(&t->tag_checksum, 0); + checksum = 0; + for (i = 0; i < 16; ++i) + checksum += ((unsigned char *)t)[i]; + set8(&t->tag_checksum, checksum); +} + +static void +set_timestamp_from_iso_date(udf_timestamp *ts, const char *iso_date_raw) +{ + struct { + unsigned char years_since_1900; + unsigned char month, day; + unsigned char hour, minute, second; + signed char offset_from_gmt; + } *iso_date = (void *)iso_date_raw; + + set16(&ts->type_and_time_zone, + 4096 + ((iso_date->offset_from_gmt * 15) & 4095)); + set16(&ts->year, 1900 + iso_date->years_since_1900); + set8(&ts->month, iso_date->month); + set8(&ts->day, iso_date->day); + set8(&ts->hour, iso_date->hour); + set8(&ts->minute, iso_date->minute); + set8(&ts->second, iso_date->second); + /*set8(&ts->centiseconds, 0);*/ + /*set8(&ts->hundreds_of_microseconds, 0);*/ + /*set8(&ts->microseconds, 0);*/ +} + +static void +set_timestamp_from_time_t(udf_timestamp *ts, time_t t) +{ + char iso_date[7]; + iso9660_date(iso_date, t); + set_timestamp_from_iso_date(ts, iso_date); +} + + +static void +set_anchor_volume_desc_pointer(unsigned char *buf, unsigned lba) +{ + udf_anchor_volume_desc_ptr *avdp = (udf_anchor_volume_desc_ptr *)buf; + set_extent(&avdp->main_volume_desc_seq_extent, + lba_main_seq, SECTOR_SIZE*UDF_MAIN_SEQ_LENGTH); + set_extent(&avdp->reserve_volume_desc_seq_extent, + lba_main_seq_copy, SECTOR_SIZE*UDF_MAIN_SEQ_LENGTH); + set_tag(&avdp->desc_tag, UDF_TAGID_ANCHOR_VOLUME_DESC_PTR, lba, 512); +} + +static void +set_primary_vol_desc(unsigned char *buf, unsigned lba) +{ + char temp[17]; + + udf_primary_volume_desc *pvd = (udf_primary_volume_desc *)buf; + /*set32(&pvd->volume_desc_seq_number, 0);*/ + /*set32(&pvd->primary_volume_desc_number, 0);*/ + set_dstring(pvd->volume_ident, volume_id, sizeof (pvd->volume_ident)); + set16(&pvd->volume_seq_number, 1); + set16(&pvd->maximum_volume_seq_number, 1); + set16(&pvd->interchange_level, 2); + set16(&pvd->maximum_interchange_level, 2); + set32(&pvd->character_set_list, 1); + set32(&pvd->maximum_character_set_list, 1); + sprintf(temp, "%08X%08X", volume_set_id[0], volume_set_id[1]); + set_dstring(pvd->volume_set_ident, temp, + sizeof (pvd->volume_set_ident)); + set_charspec(&pvd->desc_character_set); + set_charspec(&pvd->explanatory_character_set); + /*pvd->volume_abstract;*/ + /*pvd->volume_copyright_notice;*/ + /*pvd->application_ident;*/ + set_timestamp_from_time_t(&pvd->recording_date_and_time, begun); + set_impl_ident(&pvd->impl_ident); + set_tag(&pvd->desc_tag, UDF_TAGID_PRIMARY_VOLUME_DESC, lba, 512); +} + +static void +set_impl_use_vol_desc(unsigned char *buf, unsigned lba) +{ + udf_impl_use_volume_desc *iuvd = (udf_impl_use_volume_desc *)buf; + set32(&iuvd->volume_desc_seq_number, 1); + strcpy((char *)iuvd->impl_ident.ident, "*UDF LV Info"); + iuvd->impl_ident.ident_suffix[0] = 2; + iuvd->impl_ident.ident_suffix[1] = 1; + set_charspec(&iuvd->impl_use.lvi_charset); + set_dstring(iuvd->impl_use.logical_volume_ident, volume_id, + sizeof (iuvd->impl_use.logical_volume_ident)); + /*set_dstring(iuvd->impl_use.lv_info1, "", sizeof (iuvd->impl_use.lv_info1));*/ + /*set_dstring(iuvd->impl_use.lv_info2, "", sizeof (iuvd->impl_use.lv_info2));*/ + /*set_dstring(iuvd->impl_use.lv_info3, "", sizeof (iuvd->impl_use.lv_info3));*/ + set_impl_ident(&iuvd->impl_use.impl_id); + set_tag(&iuvd->desc_tag, UDF_TAGID_IMPL_USE_VOLUME_DESC, lba, 512); +} + +static void +set_partition_desc(unsigned char *buf, unsigned lba) +{ + udf_partition_desc *pd = (udf_partition_desc *)buf; + set32(&pd->volume_desc_seq_number, 2); + set16(&pd->partition_flags, UDF_PARTITION_FLAG_ALLOCATED); + /*set16(&pd->partition_number, 0);*/ + set8(&pd->partition_contents.flags, UDF_ENTITYID_FLAG_PROTECTED); /*???*/ + strcpy((char *)pd->partition_contents.ident, "+NSR02"); + set32(&pd->access_type, UDF_ACCESSTYPE_READONLY); + set32(&pd->partition_starting_location, lba_udf_partition_start); + set32(&pd->partition_length, + lba_end_anchor_vol_desc - lba_udf_partition_start); + set_impl_ident(&pd->impl_ident); + set_tag(&pd->desc_tag, UDF_TAGID_PARTITION_DESC, lba, 512); +} + +static void +set_domain_ident(udf_EntityID *ent) +{ + strcpy((char *)ent->ident, "*OSTA UDF Compliant"); + memcpy(ent->ident_suffix, "\002\001\003", 3); +} + +static void +set_logical_vol_desc(unsigned char *buf, unsigned lba) +{ + udf_logical_volume_desc *lvd = (udf_logical_volume_desc *)buf; + set32(&lvd->volume_desc_seq_number, 3); + set_charspec(&lvd->desc_character_set); + set_dstring(lvd->logical_volume_ident, volume_id, + sizeof (lvd->logical_volume_ident)); + set32(&lvd->logical_block_size, SECTOR_SIZE); + set_domain_ident(&lvd->domain_ident); + set32(&lvd->logical_volume_contents_use.extent_length, 2*SECTOR_SIZE); + /*set32(&lvd->logical_volume_contents_use.extent_location.logical_block_number, 0);*/ + /*set16(&lvd->logical_volume_contents_use.extent_location.partition_reference_number, 0);*/ + set32(&lvd->map_table_length, 6); + set32(&lvd->number_of_partition_maps, 1); + set_impl_ident(&lvd->impl_ident); + set_extent(&lvd->integrity_seq_extent, lba_integ_seq, + SECTOR_SIZE*UDF_INTEG_SEQ_LENGTH); + set8(&lvd->partition_map[0].partition_map_type, + UDF_PARTITION_MAP_TYPE_1); + set8(&lvd->partition_map[0].partition_map_length, 6); + set16(&lvd->partition_map[0].volume_seq_number, 1); + /*set16(&lvd->partition_map[0].partition_number, 0);*/ + set_tag(&lvd->desc_tag, UDF_TAGID_LOGICAL_VOLUME_DESC, lba, 446); +} + +static void +set_unallocated_space_desc(unsigned char *buf, unsigned lba) +{ + udf_unallocated_space_desc *usd = (udf_unallocated_space_desc *)buf; + set32(&usd->volume_desc_seq_number, 4); + /*set32(&usd->number_of_allocation_descs, 0);*/ + set_tag(&usd->desc_tag, UDF_TAGID_UNALLOCATED_SPACE_DESC, lba, 24); +} + +static void +set_terminating_desc(unsigned char *buf, unsigned lba) +{ + udf_terminating_desc *td = (udf_terminating_desc *)buf; + set_tag(&td->desc_tag, UDF_TAGID_TERMINATING_DESC, lba, 512); +} + +static void +set_logical_vol_integrity_desc(unsigned char *buf, unsigned lba) +{ + udf_logical_volume_integrity_desc *lvid = + (udf_logical_volume_integrity_desc *)buf; + + set_timestamp_from_time_t(&lvid->recording_date, begun); + set32(&lvid->integrity_type, UDF_INTEGRITY_TYPE_CLOSE); + /*lvid->next_integrity_extent;*/ + set64(&lvid->logical_volume_contents_use.unique_id, + lba_last_file_entry+1); + set32(&lvid->number_of_partitions, 1); + set32(&lvid->length_of_impl_use, 46); + /*set32(&lvid->free_space_table, 0);*/ + set32(&lvid->size_table, + lba_end_anchor_vol_desc - lba_udf_partition_start); + set_impl_ident(&lvid->impl_use.impl_id); + set32(&lvid->impl_use.number_of_files, num_udf_files); + set32(&lvid->impl_use.number_of_directories, num_udf_directories); + set16(&lvid->impl_use.minimum_udf_read_revision, 0x102); + set16(&lvid->impl_use.minimum_udf_write_revision, 0x102); + set16(&lvid->impl_use.maximum_udf_write_revision, 0x102); + set_tag(&lvid->desc_tag, UDF_TAGID_LOGICAL_VOLUME_INTEGRITY_DESC, + lba, 88+46); +} + +static void +set_file_set_desc(unsigned char *buf, unsigned rba) +{ + udf_file_set_desc *fsd = (udf_file_set_desc *)buf; + + set_timestamp_from_time_t(&fsd->recording_date_and_time, begun); + set16(&fsd->interchange_level, 3); + set16(&fsd->maximum_interchange_level, 3); + set32(&fsd->character_set_list, 1); + set32(&fsd->maximum_character_set_list, 1); + /*set32(&fsd->file_set_number, 0);*/ + /*set32(&fsd->file_set_desc_number, 0);*/ + set_charspec(&fsd->logical_volume_ident_character_set); + set_dstring(fsd->logical_volume_ident, volume_id, + sizeof (fsd->logical_volume_ident)); + set_charspec(&fsd->file_set_character_set); + set_dstring(fsd->file_set_ident, volume_id, + sizeof (fsd->file_set_ident)); + /*fsd->copyright_file_ident;*/ + /*fsd->abstract_file_ident;*/ + set32(&fsd->root_directory_icb.extent_length, SECTOR_SIZE); + set32(&fsd->root_directory_icb.extent_location.logical_block_number, + root->self->udf_file_entry_sector - lba_udf_partition_start); + set_domain_ident(&fsd->domain_ident); + /*fsd->next_extent;*/ + set_tag(&fsd->desc_tag, UDF_TAGID_FILE_SET_DESC, rba, 512); +} + +static int +set_file_ident_desc(unsigned char *buf, unsigned rba, char *name, + int is_directory, unsigned file_entry_rba, + unsigned unique_id) +{ + udf_file_ident_desc *fid = (udf_file_ident_desc *)buf; + int length_of_file_ident, length, padded_length; + set16(&fid->file_version_number, 1); + set8(&fid->file_characteristics, + (is_directory ? UDF_FILE_CHARACTERISTIC_DIRECTORY : 0) + + (name == 0) * UDF_FILE_CHARACTERISTIC_PARENT); + set32(&fid->icb.extent_length, SECTOR_SIZE); + set32(&fid->icb.extent_location.logical_block_number, file_entry_rba); + set16(&fid->icb.extent_location.partition_reference_number, 0); + set32(&fid->icb.impl_use.unique_id, unique_id); + set16(&fid->length_of_impl_use, 0); + if (name) { + length_of_file_ident = + set_ostaunicode((Uchar *)fid->file_ident, 512, name); + } else { + length_of_file_ident = 0; + } + set8(&fid->length_of_file_ident, length_of_file_ident); + length = 38 + length_of_file_ident; + padded_length = PAD(length, 4); + while (length < padded_length) { + buf[length++] = 0; + } + set_tag(&fid->desc_tag, UDF_TAGID_FILE_IDENT_DESC, rba, length); + return (length); +} + +static void +set_file_entry(unsigned char *buf, unsigned rba, unsigned file_rba, + uint64_t length, const char *iso_date, int is_directory, + unsigned link_count, unsigned unique_id) +{ + udf_short_ad *allocation_desc; + unsigned chunk; + + udf_file_entry *fe = (udf_file_entry *)buf; + + /*set32(&fe->icb_tag.prior_recorded_number_of_direct_entries, 0);*/ + set16(&fe->icb_tag.strategy_type, 4); + /*set16(&fe->icb_tag.strategy_parameter, 0);*/ + set16(&fe->icb_tag.maximum_number_of_entries, 1); + set8(&fe->icb_tag.file_type, is_directory + ? UDF_ICBTAG_FILETYPE_DIRECTORY : UDF_ICBTAG_FILETYPE_BYTESEQ); + /*fe->icb_tag.parent_icb_location;*/ + set16(&fe->icb_tag.flags, UDF_ICBTAG_FLAG_NONRELOCATABLE + | UDF_ICBTAG_FLAG_ARCHIVE | UDF_ICBTAG_FLAG_CONTIGUOUS); + if (rationalize_uid) + set32(&fe->uid, uid_to_use); + else + set32(&fe->uid, -1); + if (rationalize_gid) + set32(&fe->gid, gid_to_use); + else + set32(&fe->gid, -1); + if (is_directory) { + set32(&fe->permissions, + UDF_FILEENTRY_PERMISSION_OR | UDF_FILEENTRY_PERMISSION_OX | + UDF_FILEENTRY_PERMISSION_GR | UDF_FILEENTRY_PERMISSION_GX | + UDF_FILEENTRY_PERMISSION_UR | UDF_FILEENTRY_PERMISSION_UX); + } else { + set32(&fe->permissions, UDF_FILEENTRY_PERMISSION_OR + | UDF_FILEENTRY_PERMISSION_GR | UDF_FILEENTRY_PERMISSION_UR); + } + set16(&fe->file_link_count, link_count); + /*fe->record_format;*/ + /*fe->record_display_attributes;*/ + /*fe->record_length;*/ + set64(&fe->info_length, length); + set64(&fe->logical_blocks_recorded, ISO_BLOCKS(length)); + if (iso_date) { + set_timestamp_from_iso_date(&fe->access_time, iso_date); + fe->modification_time = fe->access_time; + fe->attribute_time = fe->access_time; + } + set32(&fe->checkpoint, 1); + /*fe->ext_attribute_icb;*/ + set_impl_ident(&fe->impl_ident); + set64(&fe->unique_id, unique_id); + /* + * Extended attributes that may (?) be required for DVD-Video + * compliance + */ +#if 0 + set32(&fe->length_of_ext_attributes, 24+52+56); + set32(&fe->ext_attribute_header.impl_attributes_location, 24); + set32(&fe->ext_attribute_header.application_attributes_location, + 24+52+56); + set_tag(&fe->ext_attribute_header.desc_tag, + UDF_TAGID_EXT_ATTRIBUTE_HEADER_DESC, rba, 24 /*???*/); + set32(&fe->ext_attribute_free_ea_space.attribute_type, SECTOR_SIZE); + set8(&fe->ext_attribute_free_ea_space.attribute_subtype, 1); + set32(&fe->ext_attribute_free_ea_space.attribute_length, 52); + set32(&fe->ext_attribute_free_ea_space.impl_use_length, 4); + strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident, + "*UDF FreeAppEASpace"); + set32(&fe->ext_attribute_dvd_cgms_info.attribute_type, SECTOR_SIZE); + set8(&fe->ext_attribute_dvd_cgms_info.attribute_subtype, 1); + set32(&fe->ext_attribute_dvd_cgms_info.attribute_length, 56); + set32(&fe->ext_attribute_dvd_cgms_info.impl_use_length, 8); + strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident, + "*UDF DVD CGMS Info"); + fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[0] = 2; + fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[1] = 1; +#else + /*set32(&fe->length_of_ext_attributes, 0);*/ +#endif + + allocation_desc = &fe->allocation_desc; + /* + * Only a file size less than 1GB can be expressed by a single + * AllocationDescriptor. When the size of a file is larger than 1GB, + * 2 or more AllocationDescriptors should be used. We don't know + * whether a singl 8-byte AllocationDescriptor should be written or no + * one should be written if the size of a file is 0 byte. - FIXME. + * + * XXX We get called with buf[2048]. This allows a max. file size of + * XXX 234 GB. With more we would cause a buffer overflow. + * XXX We need to check whether UDF would allow files > 234 GB. + */ + for (; length > 0; length -= chunk) { + chunk = (length > 0x3ffff800) ? 0x3ffff800 : length; + set32(&allocation_desc->extent_length, chunk); + set32(&allocation_desc->extent_position, file_rba); + file_rba += chunk >> 11; + allocation_desc++; + } + set32(&fe->length_of_allocation_descs, + (unsigned char *) allocation_desc - + (unsigned char *) &fe->allocation_desc); + set_tag(&fe->desc_tag, UDF_TAGID_FILE_ENTRY, rba, + (unsigned char *) allocation_desc - buf); +} + +static unsigned +directory_link_count(struct directory *dpnt) +{ + /* + * The link count is equal to 1 (for the parent) plus the + * number of subdirectories. + */ + unsigned link_count = 1; + struct directory_entry *de; + + /* count relocated subdirectories */ + for (de = dpnt->jcontents; de; de = de->jnext) { + if ((de->de_flags & + (INHIBIT_JOLIET_ENTRY | RELOCATED_DIRECTORY)) == + RELOCATED_DIRECTORY) { + link_count++; + } + } + /* count ordinary subdirectories */ + for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) { + if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) { + link_count++; + } + } + return (link_count); +} + +static void +write_one_udf_directory(struct directory *dpnt, FILE *outfile) +{ + unsigned size_in_bytes, padded_size_in_bytes; + struct directory_entry *de; + unsigned ident_size; + unsigned base_sector; + struct directory *parent; + Uchar buf[SECTOR_SIZE]; + + memset(buf, 0, SECTOR_SIZE); + set_file_entry( + buf, + last_extent_written - lba_udf_partition_start, + last_extent_written+1 - lba_udf_partition_start, + directory_size(dpnt), + dpnt->self->isorec.date, + 1, /* is_directory */ + directory_link_count(dpnt), + (dpnt == root) ? 0 : dpnt->self->udf_file_entry_sector); + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + + base_sector = last_extent_written - lba_udf_partition_start; + + /* parent directory */ + parent = dpnt->parent; + if (parent == reloc_dir) { + parent = dpnt->self->parent_rec->filedir; + } + ident_size = set_file_ident_desc( + buf, + base_sector, + 0, + 1, + parent->self->udf_file_entry_sector - lba_udf_partition_start, + (parent == root) ? 0 : parent->self->udf_file_entry_sector); + jtwrite(buf, ident_size, 1, 0, FALSE); + xfwrite(buf, ident_size, 1, outfile, 0, FALSE); + size_in_bytes = ident_size; + + /* directory contents */ + for (de = dpnt->jcontents; de; de = de->jnext) { + char *name; + struct directory_entry *de1; + + if (de->de_flags & INHIBIT_JOLIET_ENTRY) + continue; + + name = USE_MAC_NAME(de) ? de->hfs_ent->name : de->name; + + /* skip . and .. */ + if (name[0] == '.' && (name[1] == 0 || + (name[1] == '.' && name[2] == 0))) + continue; + + /* look in RR_MOVED for relocated directories */ + de1 = de; + if (de->de_flags & RELOCATED_DIRECTORY) { + for (de1 = reloc_dir->contents; de1; de1 = de1->next) { + if (de1->parent_rec == de) { + break; + } + } + if (!de1) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Unable to locate relocated directory\n"); +#else + fprintf(stderr, + "Unable to locate relocated directory\n"); + exit(1); +#endif + } + } + + ident_size = set_file_ident_desc( + buf, + base_sector + (size_in_bytes / SECTOR_SIZE), + name, + !!(de1->isorec.flags[0] & ISO_DIRECTORY), + de1->udf_file_entry_sector - lba_udf_partition_start, + de1->udf_file_entry_sector); + jtwrite(buf, ident_size, 1, 0, FALSE); + xfwrite(buf, ident_size, 1, outfile, 0, FALSE); + size_in_bytes += ident_size; + } + + padded_size_in_bytes = PAD(size_in_bytes, SECTOR_SIZE); + if (size_in_bytes < padded_size_in_bytes) { + memset(buf, 0, padded_size_in_bytes - size_in_bytes); + jtwrite(buf, padded_size_in_bytes - size_in_bytes, 1, 0, FALSE); + xfwrite(buf, padded_size_in_bytes - size_in_bytes, 1, outfile, 0, FALSE); + } + + last_extent_written += padded_size_in_bytes / SECTOR_SIZE; +} + +static void +write_udf_directories(struct directory *dpnt, FILE *outfile) +{ + if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) { + write_one_udf_directory(dpnt, outfile); + } + if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) { + for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) { + write_udf_directories(dpnt, outfile); + } + } +} + +static void +write_udf_file_entries(struct directory *dpnt, FILE *outfile) +{ + Uchar buf[SECTOR_SIZE]; + + memset(buf, 0, SECTOR_SIZE); + + if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) { + struct directory_entry *de; + for (de = dpnt->jcontents; de; de = de->jnext) { + if (!(de->de_flags & RELOCATED_DIRECTORY) && + !(de->isorec.flags[0] & ISO_DIRECTORY)) { + + memset(buf, 0, 512); + set_file_entry( + buf, + (last_extent_written++) - lba_udf_partition_start, + read_733(de->isorec.extent) - lba_udf_partition_start, + de->realsize, + de->isorec.date, + 0, /* is_directory */ + 1, /* link_count */ + de->udf_file_entry_sector); + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE); + } + } + } + if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) { + for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) { + write_udf_file_entries(dpnt, outfile); + } + } +} + +/****************************/ + +static int +udf_vol_recognition_area_write(FILE *out) +{ + static const char *identifiers[3] = { "BEA01", "NSR02", "TEA01" }; + int i; + char buf[SECTOR_SIZE]; + udf_volume_recognition_desc *vsd = (udf_volume_recognition_desc *)buf; + + memset(buf, 0, sizeof (buf)); + /*set8(&vsd->structure_type, 0);*/ + set8(&vsd->structure_version, 1); + for (i = 0; i < 3; ++i) { + memcpy(vsd->standard_identifier, identifiers[i], 5); + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE); + } + last_extent_written += 3; + return (0); +} + +static int +udf_main_seq_write(FILE *out) +{ + Uchar buf[SECTOR_SIZE]; + int i; + + /* + * volume_set_id needs to be set to a (64-bit) "unique" number. + * This will have to do for now. + */ + volume_set_id[0] = begun; + volume_set_id[1] = (unsigned)clock(); /* XXX Maybe non-portable */ + + memset(buf, 0, sizeof (buf)); + set_primary_vol_desc(buf, last_extent_written++); + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE); + + memset(buf, 0, sizeof (buf)); + set_impl_use_vol_desc(buf, last_extent_written++); + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE); + + memset(buf, 0, sizeof (buf)); + set_partition_desc(buf, last_extent_written++); + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE); + + memset(buf, 0, sizeof (buf)); + set_logical_vol_desc(buf, last_extent_written++); + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE); + + memset(buf, 0, sizeof (buf)); + set_unallocated_space_desc(buf, last_extent_written++); + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE); + + memset(buf, 0, sizeof (buf)); + set_terminating_desc(buf, last_extent_written++); + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE); + + memset(buf, 0, sizeof (buf)); + for (i = 6; i < UDF_MAIN_SEQ_LENGTH; ++i) { + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE); + last_extent_written++; + } + + return (0); +} + +static int +udf_integ_seq_write(FILE *out) +{ + Uchar buf[SECTOR_SIZE*UDF_INTEG_SEQ_LENGTH]; + + memset(buf, 0, sizeof (buf)); + + set_logical_vol_integrity_desc(buf+0*SECTOR_SIZE, + last_extent_written++); + set_terminating_desc(buf+1*SECTOR_SIZE, last_extent_written++); + + jtwrite(buf, SECTOR_SIZE, UDF_INTEG_SEQ_LENGTH, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, UDF_INTEG_SEQ_LENGTH, out, 0, FALSE); + return (0); +} + +static int +udf_anchor_vol_desc_write(FILE *out) +{ + Uchar buf[SECTOR_SIZE]; + + memset(buf, 0, sizeof (buf)); + set_anchor_volume_desc_pointer(buf, last_extent_written++); + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE); + return (0); +} + +static int +udf_file_set_desc_write(FILE *out) +{ + Uchar buf[SECTOR_SIZE*2]; + + memset(buf, 0, sizeof (buf)); + + set_file_set_desc(buf+0*SECTOR_SIZE, + (last_extent_written++) - lba_udf_partition_start); + set_terminating_desc(buf+1*SECTOR_SIZE, + (last_extent_written++) - lba_udf_partition_start); + + jtwrite(buf, SECTOR_SIZE, 2, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 2, out, 0, FALSE); + + return (0); +} + +static int +udf_dirtree_write(FILE *out) +{ + write_udf_directories(root, out); + return (0); +} + +static int +udf_file_entries_write(FILE *out) +{ + write_udf_file_entries(root, out); + return (0); +} + +static int +pad_to(unsigned last_extent_to_write, FILE *out) +{ + char buf[SECTOR_SIZE]; + memset(buf, 0, sizeof (buf)); + while (last_extent_written < last_extent_to_write) { + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE); + ++last_extent_written; + } + return (0); +} + +static int +udf_pad_to_sector_32_write(FILE *out) +{ + return (pad_to(session_start+32, out)); +} + +static int +udf_pad_to_sector_256_write(FILE *out) +{ + return (pad_to(session_start+256, out)); +} + +static int +udf_padend_avdp_write(FILE *out) +{ + Uchar buf[SECTOR_SIZE]; + unsigned last_extent_to_write = (last_extent_written+31) & ~15; + + if (!use_sparcboot) + last_extent_to_write = last_extent_written + 150; + + memset(buf, 0, sizeof (buf)); + while (last_extent_written < last_extent_to_write) { + set_anchor_volume_desc_pointer(buf, last_extent_written++); + jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE); + } + return (0); +} + + +struct output_fragment udf_vol_recognition_area_frag = { NULL, udf_vol_recognition_area_size, NULL, udf_vol_recognition_area_write, "UDF volume recognition area" }; +struct output_fragment udf_main_seq_frag = { NULL, udf_main_seq_size, NULL, udf_main_seq_write, "UDF main seq" }; +struct output_fragment udf_main_seq_copy_frag = { NULL, udf_main_seq_copy_size, NULL, udf_main_seq_write, "UDF second seq" }; +struct output_fragment udf_integ_seq_frag = { NULL, udf_integ_seq_size, NULL, udf_integ_seq_write, "UDF integ seq" }; +struct output_fragment udf_anchor_vol_desc_frag = { NULL, oneblock_size, NULL, udf_anchor_vol_desc_write, "UDF Anchor volume" }; +struct output_fragment udf_file_set_desc_frag = { NULL, udf_file_set_desc_size, NULL, udf_file_set_desc_write, "UDF file set" }; +struct output_fragment udf_dirtree_frag = { NULL, udf_dirtree_size, NULL, udf_dirtree_write, "UDF directory tree" }; +struct output_fragment udf_file_entries_frag = { NULL, udf_file_entries_size, NULL, udf_file_entries_write, "UDF file entries" }; +struct output_fragment udf_end_anchor_vol_desc_frag = { NULL, udf_end_anchor_vol_desc_size, NULL, udf_anchor_vol_desc_write, "UDF Anchor end volume" }; + +struct output_fragment udf_pad_to_sector_32_frag = { NULL, udf_pad_to_sector_32_size, NULL, udf_pad_to_sector_32_write, "UDF pad to sector 32" }; +struct output_fragment udf_pad_to_sector_256_frag = { NULL, udf_pad_to_sector_256_size, NULL, udf_pad_to_sector_256_write, "UDF pad to sector 256" }; +struct output_fragment udf_padend_avdp_frag = { NULL, udf_padend_avdp_size, NULL, udf_padend_avdp_write, "UDF Pad end" }; + +/* + * This function assigns weights as follows: + * + * /VIDEO_TS/VIDEO_TS.IFO 11199 + * /VIDEO_TS/VIDEO_TS.VOB 11198 + * /VIDEO_TS/VIDEO_TS.BUP 11188 + * /VIDEO_TS/VTS_01_0.IFO 11187 + * /VIDEO_TS/VTS_01_0.VOB 11186 + * : : + * /VIDEO_TS/VTS_01_9.VOB 11177 + * /VIDEO_TS/VTS_01_0.BUP 11176 + * : : + * /VIDEO_TS/VTS_99_0.BUP 10000 + * + * This ensures that DVD-Video files are laid out properly on the disc. + * The same thing is done for AUDIO_TS files, except in the 20000 range + * instead of the 10000 range. + * + * Question: what about JACKET_P files? + * + * Answer: At least as far as I know :) + * JACKET_P files are still images (single frame mpeg video .i.e mp2 + * format). The DVD Jacket pictures will be displayed on the TV screen + * when the player is in a stop/resume mode. + * The location is not dependent on IFO information and the only must + * as far as I know is that they are in upper case (both dir and files). + * This sparce information makes me conclude that they don't need any + * weight. This obviously needs to be tested. + */ +int +assign_dvd_weights(char *name, struct directory *this_dir, int val) +{ + int ts_number; + int segment; + int audio; + + if (name[0] != 'A' && name[0] != 'V') + return (val); + + if (memcmp(name, "VIDEO_TS", 8) == 0) { + ts_number = 0; + audio = 0; + } else if (memcmp(name, "VTS_", 4) == 0) { + ts_number = 1; + audio = 0; + } else if (memcmp(name, "AUDIO_TS", 8) == 0) { + ts_number = 0; + audio = 1; + } else if (memcmp(name, "ATS_", 4) == 0) { + ts_number = 1; + audio = 1; + } else { + return (val); + } + + if (this_dir->parent != root || + strcmp(this_dir->de_name, "VIDEO_TS") != 0) + return (val); + + if (ts_number == 0) { + segment = 0; + } else { + if (name[4] >= '0' && name[4] <= '9' && + name[5] >= '0' && name[5] <= '9' && + name[6] == '_' && + name[7] >= '0' && name[7] <= '9') { + ts_number = name[4] * 10 + name[5] - ('0' * 11); + segment = name[7] - '0'; + } else { + return (val); + } + } + + if (strcmp(name+8, audio ? ".AOB" : ".VOB") == 0) { + return (audio * 10000 - ts_number * 12 - segment + 11198); + } else if (strcmp(name+8, ".IFO") == 0) { + return (audio * 10000 - ts_number * 12 + 11199); + } else if (strcmp(name+8, ".BUP") == 0) { + return (audio * 10000 - ts_number * 12 + 11188); + } else { + return (val); + } +} + +#endif /* UDF */ diff --git a/genisoimage/udf.h b/genisoimage/udf.h new file mode 100644 index 0000000..dc7bb94 --- /dev/null +++ b/genisoimage/udf.h @@ -0,0 +1,55 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)udf.h 1.2 04/03/01 Copyright 2001-2004 J. Schilling */ +/* + * UDF external definitions for genisoimage + * + * Copyright (c) 2001-2004 J. Schilling + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _UDF_H +#define _UDF_H + +extern struct output_fragment udf_vol_recognition_area_frag; +extern struct output_fragment udf_main_seq_frag; +extern struct output_fragment udf_main_seq_copy_frag; +extern struct output_fragment udf_integ_seq_frag; +extern struct output_fragment udf_anchor_vol_desc_frag; +extern struct output_fragment udf_file_set_desc_frag; +extern struct output_fragment udf_dirtree_frag; +extern struct output_fragment udf_file_entries_frag; +extern struct output_fragment udf_end_anchor_vol_desc_frag; + +extern struct output_fragment udf_pad_to_sector_32_frag; +extern struct output_fragment udf_pad_to_sector_256_frag; +extern struct output_fragment udf_padend_avdp_frag; + +int assign_dvd_weights(char *name, struct directory *this_dir, int val); + +extern int use_udf; + +#endif /* _UDF_H */ diff --git a/genisoimage/udf_fs.h b/genisoimage/udf_fs.h new file mode 100644 index 0000000..850a3cc --- /dev/null +++ b/genisoimage/udf_fs.h @@ -0,0 +1,462 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)udf_fs.h 1.2 04/03/01 Copyright 2001-2004 J. Schilling */ +/* + * udf_fs.h - UDF structure definitions for genisoimage + * + * Written by Ben Rudiak-Gould (2001). + * + * Copyright 2001-2004 J. Schilling. + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _UDF_FS_H +#define _UDF_FS_H + +/* + * Abbreviations: + * + * ad allocation descriptor + * desc descriptor + * ext extended + * ident identifier + * impl implementation + * info information + * ptr pointer + * seq sequence + */ + +typedef char udf_Uint8; +typedef char udf_dchar; +typedef char udf_dstring; +typedef char udf_byte; +typedef char udf_zerobyte; + +/* Is this safe? Are there compilers so perverse as to pad these structs? */ +typedef struct udf_Uint16_ { + char l; + char h; +} udf_Uint16; + +typedef struct udf_Uint32_ { + char l; + char ml; + char mh; + char h; +} udf_Uint32; +typedef struct udf_Uint64_ { + udf_Uint32 l; + udf_Uint32 h; +} udf_Uint64; + +typedef struct udf_tag_ { /* ECMA-167 3/7.2 */ +/* 0*/ udf_Uint16 tag_ident; +/* 2*/ udf_Uint16 desc_version; +/* 4*/ udf_Uint8 tag_checksum; +/* 5*/ udf_zerobyte reserved; +/* 6*/ udf_Uint16 tag_serial_number; +/* 8*/ udf_Uint16 desc_crc; +/*10*/ udf_Uint16 desc_crc_length; +/*12*/ udf_Uint32 tag_location; +/*16*/ +} udf_tag; + +#define UDF_TAGID_PRIMARY_VOLUME_DESC 1 +#define UDF_TAGID_ANCHOR_VOLUME_DESC_PTR 2 +#define UDF_TAGID_IMPL_USE_VOLUME_DESC 4 +#define UDF_TAGID_PARTITION_DESC 5 +#define UDF_TAGID_LOGICAL_VOLUME_DESC 6 +#define UDF_TAGID_UNALLOCATED_SPACE_DESC 7 +#define UDF_TAGID_TERMINATING_DESC 8 +#define UDF_TAGID_LOGICAL_VOLUME_INTEGRITY_DESC 9 +#define UDF_TAGID_FILE_SET_DESC 256 +#define UDF_TAGID_FILE_IDENT_DESC 257 +#define UDF_TAGID_FILE_ENTRY 261 +#define UDF_TAGID_EXT_ATTRIBUTE_HEADER_DESC 262 + +typedef struct udf_extent_ad_ { /* ECMA-167 3/7.1 */ +/*0*/ udf_Uint32 extent_length; +/*4*/ udf_Uint32 extent_location; +/*8*/ +} udf_extent_ad; + +typedef struct udf_charspec_ { /* ECMA-167 1/7.2.1 */ +/* 0*/ udf_Uint8 character_set_type; +/* 1*/ udf_byte character_set_info[63]; +/*64*/ +} udf_charspec; + +typedef struct udf_EntityID_ { /* ECMA-167 1/7.4 */ +/* 0*/ udf_Uint8 flags; +/* 1*/ udf_byte ident[23]; +/*24*/ udf_byte ident_suffix[8]; +/*32*/ +} udf_EntityID; + +#define UDF_ENTITYID_FLAG_PROTECTED 2 /* ECMA-167 1/7.4.1 */ + +typedef struct udf_lb_addr_ { /* ECMA-167 4/7.1 */ +/*0*/ udf_Uint32 logical_block_number; +/*4*/ udf_Uint16 partition_reference_number; +/*6*/ +} udf_lb_addr; + +typedef struct udf_short_ad_ { /* ECMA-167 4/14.14.1 */ +/*0*/ udf_Uint32 extent_length; +/*4*/ udf_Uint32 extent_position; +/*8*/ +} udf_short_ad; + +typedef struct udf_long_ad_impl_use_field_ { /* UDF 2.01 2.3.4.3 */ +/*0*/ udf_Uint16 flags; +/*2*/ udf_Uint32 unique_id; +/*6*/ +} udf_long_ad_impl_use_field; + +typedef struct udf_long_ad_ { /* ECMA-167 4/14.14.2 */ +/* 0*/ udf_Uint32 extent_length; +/* 4*/ udf_lb_addr extent_location; +/*10*/ udf_long_ad_impl_use_field impl_use; +/*16*/ +} udf_long_ad; + +typedef struct udf_timestamp_ { /* TR/71 1.5.4 */ +/* 0*/ udf_Uint16 type_and_time_zone; +/* 2*/ udf_Uint16 year; +/* 4*/ udf_Uint8 month; +/* 5*/ udf_Uint8 day; +/* 6*/ udf_Uint8 hour; +/* 7*/ udf_Uint8 minute; +/* 8*/ udf_Uint8 second; +/* 9*/ udf_Uint8 centiseconds; +/*10*/ udf_Uint8 hundreds_of_microseconds; +/*11*/ udf_Uint8 microseconds; +/*12*/ +} udf_timestamp; + +typedef struct udf_volume_recognition_desc_ { /* TR/71 2.4.{1,2,3} */ + udf_Uint8 structure_type; + udf_byte standard_identifier[5]; + udf_Uint8 structure_version; + udf_zerobyte structure_data[2041]; +} udf_volume_recognition_desc; + +typedef struct udf_anchor_volume_desc_ptr_ { /* TR/71 2.5.1 */ +/* 0*/ udf_tag desc_tag; +/* 16*/ udf_extent_ad main_volume_desc_seq_extent; +/* 24*/ udf_extent_ad reserve_volume_desc_seq_extent; +/* 32*/ udf_zerobyte reserved[480]; +/*512*/ +} udf_anchor_volume_desc_ptr; + +typedef struct udf_primary_volume_desc_ { /* TR/71 2.6.1 */ +/* 0*/ udf_tag desc_tag; +/* 16*/ udf_Uint32 volume_desc_seq_number; +/* 20*/ udf_Uint32 primary_volume_desc_number; +/* 24*/ udf_dstring volume_ident[32]; +/* 56*/ udf_Uint16 volume_seq_number; +/* 58*/ udf_Uint16 maximum_volume_seq_number; +/* 60*/ udf_Uint16 interchange_level; +/* 62*/ udf_Uint16 maximum_interchange_level; +/* 64*/ udf_Uint32 character_set_list; +/* 68*/ udf_Uint32 maximum_character_set_list; +/* 72*/ udf_dstring volume_set_ident[128]; +/*200*/ udf_charspec desc_character_set; +/*264*/ udf_charspec explanatory_character_set; +/*328*/ udf_extent_ad volume_abstract; +/*336*/ udf_extent_ad volume_copyright_notice; +/*344*/ udf_EntityID application_ident; +/*376*/ udf_timestamp recording_date_and_time; +/*388*/ udf_EntityID impl_ident; +/*420*/ udf_byte impl_use[64]; +/*484*/ udf_Uint32 predecessor_volume_desc_seq_location; +/*488*/ udf_Uint16 flags; +/*490*/ udf_zerobyte reserved[22]; +/*512*/ +} udf_primary_volume_desc; + +typedef struct udf_impl_use_volume_desc_impl_use_field_ { /* TR/71 2.6.3 */ +/* 0*/ udf_charspec lvi_charset; +/* 64*/ udf_dstring logical_volume_ident[128]; +/*192*/ udf_dstring lv_info1[36]; +/*228*/ udf_dstring lv_info2[36]; +/*264*/ udf_dstring lv_info3[36]; +/*300*/ udf_EntityID impl_id; +/*332*/ udf_byte impl_use[128]; +/*460*/ +} udf_impl_use_volume_desc_impl_use_field; + +typedef struct udf_impl_use_volume_desc_ { /* TR/71 2.6.2 */ +/* 0*/ udf_tag desc_tag; +/* 16*/ udf_Uint32 volume_desc_seq_number; +/* 20*/ udf_EntityID impl_ident; +/* 52*/ udf_impl_use_volume_desc_impl_use_field impl_use; +/*512*/ +} udf_impl_use_volume_desc; + +typedef struct udf_partition_desc_ { /* TR/71 2.6.4 */ +/* 0*/ udf_tag desc_tag; +/* 16*/ udf_Uint32 volume_desc_seq_number; +/* 20*/ udf_Uint16 partition_flags; +/* 22*/ udf_Uint16 partition_number; +/* 24*/ udf_EntityID partition_contents; +/* 56*/ udf_byte partition_contents_use[128]; +/*184*/ udf_Uint32 access_type; +/*188*/ udf_Uint32 partition_starting_location; +/*192*/ udf_Uint32 partition_length; +/*196*/ udf_EntityID impl_ident; +/*228*/ udf_byte impl_use[128]; +/*356*/ udf_zerobyte reserved[156]; +/*512*/ +} udf_partition_desc; + +#define UDF_PARTITION_FLAG_ALLOCATED 1 /* ECMA-167 3/10.5.3 */ +#define UDF_ACCESSTYPE_READONLY 1 /* ECMA-167 3/10.5.7 */ + +typedef struct udf_type_1_partition_map_ { /* TR/71 2.6.8 */ +/*0*/ udf_Uint8 partition_map_type; +/*1*/ udf_Uint8 partition_map_length; +/*2*/ udf_Uint16 volume_seq_number; +/*4*/ udf_Uint16 partition_number; +/*6*/ +} udf_type_1_partition_map; + +#define UDF_PARTITION_MAP_TYPE_1 1 + +typedef struct udf_logical_volume_desc_ { /* TR/71 2.6.7 */ +/* 0*/ udf_tag desc_tag; +/* 16*/ udf_Uint32 volume_desc_seq_number; +/* 20*/ udf_charspec desc_character_set; +/* 84*/ udf_dstring logical_volume_ident[128]; +/*212*/ udf_Uint32 logical_block_size; +/*216*/ udf_EntityID domain_ident; +/*248*/ udf_long_ad logical_volume_contents_use; +/*264*/ udf_Uint32 map_table_length; +/*268*/ udf_Uint32 number_of_partition_maps; +/*272*/ udf_EntityID impl_ident; +/*304*/ udf_byte impl_use[128]; +/*432*/ udf_extent_ad integrity_seq_extent; +/*440*/ udf_type_1_partition_map partition_map[1]; +/*446*/ +} udf_logical_volume_desc; + +typedef struct udf_unallocated_space_desc_ { /* TR/71 2.6.9 */ +/* 0*/ udf_tag desc_tag; +/*16*/ udf_Uint32 volume_desc_seq_number; +/*20*/ udf_Uint32 number_of_allocation_descs; +/*24*/ /*udf_extent_ad allocation_descs[0];*/ +} udf_unallocated_space_desc; + +typedef struct udf_terminating_desc_ { /* TR/71 2.6.10 */ +/* 0*/ udf_tag desc_tag; +/* 16*/ udf_zerobyte reserved[496]; +/*512*/ +} udf_terminating_desc; + +typedef struct udf_logical_volume_integrity_desc_impl_use_field_ { /* TR/71 2.7.3 */ +/* 0*/ udf_EntityID impl_id; +/*32*/ udf_Uint32 number_of_files; +/*36*/ udf_Uint32 number_of_directories; +/*40*/ udf_Uint16 minimum_udf_read_revision; +/*42*/ udf_Uint16 minimum_udf_write_revision; +/*44*/ udf_Uint16 maximum_udf_write_revision; +/*46*/ /*udf_byte impl_use[0];*/ +} udf_logical_volume_integrity_desc_impl_use_field; + +typedef struct udf_logical_volume_integrity_desc_contents_use_field_ { /* TR/71 2.7.2 */ + udf_Uint64 unique_id; + udf_zerobyte reserved[24]; +} udf_logical_volume_integrity_desc_contents_use_field; + +typedef struct udf_logical_volume_integrity_desc_ { /* TR/71 2.7.1 */ +/* 0*/ udf_tag desc_tag; +/*16*/ udf_timestamp recording_date; +/*28*/ udf_Uint32 integrity_type; +/*32*/ udf_extent_ad next_integrity_extent; +/*40*/ udf_logical_volume_integrity_desc_contents_use_field logical_volume_contents_use; +/*72*/ udf_Uint32 number_of_partitions; +/*76*/ udf_Uint32 length_of_impl_use; +/*80*/ udf_Uint32 free_space_table; +/*84*/ udf_Uint32 size_table; +/*88*/ udf_logical_volume_integrity_desc_impl_use_field impl_use; +} udf_logical_volume_integrity_desc; + +#define UDF_INTEGRITY_TYPE_CLOSE 1 /* ECMA-167 3/10.10.3 */ + +typedef struct udf_file_set_desc_ { /* TR/71 3.3.1 */ +/* 0*/ udf_tag desc_tag; +/*16*/ udf_timestamp recording_date_and_time; +/*28*/ udf_Uint16 interchange_level; +/*30*/ udf_Uint16 maximum_interchange_level; +/*32*/ udf_Uint32 character_set_list; +/*36*/ udf_Uint32 maximum_character_set_list; +/*40*/ udf_Uint32 file_set_number; +/*44*/ udf_Uint32 file_set_desc_number; +/*48*/ udf_charspec logical_volume_ident_character_set; +/*112*/ udf_dstring logical_volume_ident[128]; +/*240*/ udf_charspec file_set_character_set; +/*304*/ udf_dstring file_set_ident[32]; +/*336*/ udf_dstring copyright_file_ident[32]; +/*368*/ udf_dstring abstract_file_ident[32]; +/*400*/ udf_long_ad root_directory_icb; +/*416*/ udf_EntityID domain_ident; +/*448*/ udf_long_ad next_extent; +/*464*/ udf_zerobyte reserved[48]; +/*512*/ +} udf_file_set_desc; + +typedef struct udf_file_ident_desc_ { /* TR/71 3.4.1 */ +/* 0*/ udf_tag desc_tag; +/*16*/ udf_Uint16 file_version_number; +/*18*/ udf_Uint8 file_characteristics; +/*19*/ udf_Uint8 length_of_file_ident; +/*20*/ udf_long_ad icb; +/*36*/ udf_Uint16 length_of_impl_use; +/*38*/ /*udf_EntityID impl_use;*/ +/*38*/ udf_dchar file_ident[1]; + /*udf_zerobyte padding[0/1/2/3];*/ +} udf_file_ident_desc; + +#define UDF_FILE_CHARACTERISTIC_HIDDEN 1 /* ECMA-167 4/14.4.3 */ +#define UDF_FILE_CHARACTERISTIC_DIRECTORY 2 +#define UDF_FILE_CHARACTERISTIC_DELETED 4 +#define UDF_FILE_CHARACTERISTIC_PARENT 8 + +typedef struct udf_icbtag_ { /* TR/71 3.5.2 */ +/* 0*/ udf_Uint32 prior_recorded_number_of_direct_entries; +/* 4*/ udf_Uint16 strategy_type; +/* 6*/ udf_Uint16 strategy_parameter; +/* 8*/ udf_Uint16 maximum_number_of_entries; +/*10*/ udf_zerobyte reserved; +/*11*/ udf_Uint8 file_type; +/*12*/ udf_lb_addr parent_icb_location; +/*18*/ udf_Uint16 flags; +/*20*/ +} udf_icbtag; + +#define UDF_ICBTAG_FILETYPE_DIRECTORY 4 /* ECMA-167 4/14.6.6 */ +#define UDF_ICBTAG_FILETYPE_BYTESEQ 5 + +#define UDF_ICBTAG_FLAG_MASK_AD_TYPE 7 /* TR/71 3.5.3 */ +#define UDF_ICBTAG_FLAG_SHORT_AD 0 +#define UDF_ICBTAG_FLAG_DIRECTORY_SORT 8 +#define UDF_ICBTAG_FLAG_NONRELOCATABLE 16 +#define UDF_ICBTAG_FLAG_ARCHIVE 32 +#define UDF_ICBTAG_FLAG_SETUID 64 +#define UDF_ICBTAG_FLAG_SETGID 128 +#define UDF_ICBTAG_FLAG_STICKY 256 +#define UDF_ICBTAG_FLAG_CONTIGUOUS 512 +#define UDF_ICBTAG_FLAG_SYSTEM 1024 +#define UDF_ICBTAG_FLAG_TRANSFORMED 2048 +#define UDF_ICBTAG_FLAG_MULTI_VERSIONS 4096 + +typedef struct udf_ext_attribute_header_desc_ { /* TR/71 3.6.1 */ +/* 0*/ udf_tag desc_tag; +/*16*/ udf_Uint32 impl_attributes_location; +/*20*/ udf_Uint32 application_attributes_location; +/*24*/ +} udf_ext_attribute_header_desc; + +typedef struct udf_ext_attribute_free_ea_space_ { /* TR/71 3.6.{2,3} */ +/* 0*/ udf_Uint32 attribute_type; /* = 2048 */ +/* 4*/ udf_Uint8 attribute_subtype; /* = 1 */ +/* 5*/ udf_zerobyte reserved[3]; +/* 8*/ udf_Uint32 attribute_length; /* = 52 */ +/*12*/ udf_Uint32 impl_use_length; /* = 4 */ +/*16*/ udf_EntityID impl_ident; /* "*UDF FreeEASpace" */ +/*48*/ udf_Uint16 header_checksum; +/*50*/ udf_Uint16 free_ea_space; /* = 0 */ +/*52*/ +} udf_ext_attribute_free_ea_space; + +typedef struct udf_ext_attribute_dvd_cgms_info_ { /* TR/71 3.6.{2,4} */ +/* 0*/ udf_Uint32 attribute_type; /* = 2048 */ +/* 4*/ udf_Uint8 attribute_subtype; /* = 1 */ +/* 5*/ udf_zerobyte reserved[3]; +/* 8*/ udf_Uint32 attribute_length; /* = 56 */ +/*12*/ udf_Uint32 impl_use_length; /* = 8 */ +/*16*/ udf_EntityID impl_ident; /* "*UDF DVD CGMS Info" */ +/*48*/ udf_Uint16 header_checksum; +/*50*/ udf_byte cgms_info; +/*51*/ udf_Uint8 data_structure_type; +/*52*/ udf_byte protection_system_info[4]; +/*56*/ +} udf_ext_attribute_dvd_cgms_info; + +#define UDF_CGMSINFO_NO_COPIES 48 /* TR/71 3.6.4 */ +#define UDF_CGMSINFO_ONE_GENERATION 32 +#define UDF_CGMSINFO_UNLIMITED_COPIES 0 +#define UDF_CGMSINFO_FLAG_COPYRIGHTED_MATERIAL 128 + +typedef struct udf_file_entry_ { /* TR/71 3.5.1 */ +/* 0*/ udf_tag desc_tag; +/*16*/ udf_icbtag icb_tag; +/*36*/ udf_Uint32 uid; +/*40*/ udf_Uint32 gid; +/*44*/ udf_Uint32 permissions; +/*48*/ udf_Uint16 file_link_count; +/*50*/ udf_Uint8 record_format; +/*51*/ udf_Uint8 record_display_attributes; +/*52*/ udf_Uint32 record_length; +/*56*/ udf_Uint64 info_length; +/*64*/ udf_Uint64 logical_blocks_recorded; +/*72*/ udf_timestamp access_time; +/*84*/ udf_timestamp modification_time; +/*96*/ udf_timestamp attribute_time; +/*108*/ udf_Uint32 checkpoint; +/*112*/ udf_long_ad ext_attribute_icb; +/*128*/ udf_EntityID impl_ident; +/*160*/ udf_Uint64 unique_id; +/*168*/ udf_Uint32 length_of_ext_attributes; +/*172*/ udf_Uint32 length_of_allocation_descs; +#if 0 +/*176*/ udf_ext_attribute_header_desc ext_attribute_header; +/*200*/ udf_ext_attribute_free_ea_space ext_attribute_free_ea_space; +/*252*/ udf_ext_attribute_dvd_cgms_info ext_attribute_dvd_cgms_info; +/*308*/ udf_short_ad allocation_desc; +/*316*/ +#else +/*176*/ udf_short_ad allocation_desc; +/*184*/ +#endif +} udf_file_entry; + +/* + * (U,G,O) = (owner, group, other) + * (X,R) = (execute, read) + * + * There are Write, Change Attribute and Delete permissions also, + * but it is not permitted to set them on DVD Read-Only media. + */ +#define UDF_FILEENTRY_PERMISSION_OX 1 /* TR/71 3.5.4 */ +#define UDF_FILEENTRY_PERMISSION_OR 4 +#define UDF_FILEENTRY_PERMISSION_GX 32 +#define UDF_FILEENTRY_PERMISSION_GR 128 +#define UDF_FILEENTRY_PERMISSION_UX 1024 +#define UDF_FILEENTRY_PERMISSION_UR 4096 + + +#endif /* _UDF_FS_H */ diff --git a/genisoimage/vms.c b/genisoimage/vms.c new file mode 100644 index 0000000..9f1c885 --- /dev/null +++ b/genisoimage/vms.c @@ -0,0 +1,320 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)vms.c 1.9 04/03/04 joerg */ +/* + * File vms.c - assorted bletcherous hacks for VMS. + * + * Written by Eric Youngdale (1993). + * + */ + +#include <mconfig.h> +#ifdef VMS +#define opendir fake_opendir +#include "genisoimage.h" +#undef opendir +#include <rms.h> +#include <descrip.h> +#include <ssdef.h> + +static struct RAB *rab; /* used for external mailfiles */ +static int rms_status; + +static +error_exit(char *text) +{ + fprintf(stderr, "%s\n", text); + exit(33); +} + + +char *strrchr(const char *, char); + +int +VMS_stat(char *path, struct stat * spnt) +{ + char *spath; + char sbuffer[255]; + char *pnt, + *ppnt; + char *pnt1; + + ppnt = strrchr(path, ']'); + if (ppnt) + ppnt++; + else + ppnt = path; + + spath = path; + + if (strcmp(ppnt, ".") == 0 || strcmp(ppnt, "..") == 0) { + strcpy(sbuffer, path); + + /* Find end of actual name */ + pnt = strrchr(sbuffer, ']'); + if (!pnt) + return (0); + + pnt1 = pnt; + while (*pnt1 != '[' && *pnt1 != '.') + pnt1--; + + if (*pnt1 != '[' && strcmp(ppnt, "..") == 0) { + pnt1--; + while (*pnt1 != '[' && *pnt1 != '.') + pnt1--; + }; + + if (*pnt1 == '.') { + *pnt1 = ']'; + pnt = pnt1; + while (*pnt != '.' && *pnt != ']') + pnt++; + *pnt++ = ']'; + while (*pnt != '.' && *pnt != ']') + pnt++; + *pnt = 0; + strcat(sbuffer, ".DIR;1"); + }; + + if (*pnt1 == '[') { + pnt1++; + *pnt1 = 0; + strcat(pnt1, "000000]"); + pnt1 = strrchr(path, '[') + 1; + pnt = sbuffer + strlen(sbuffer); + while (*pnt1 && *pnt1 != '.' && *pnt1 != ']') + *pnt++ = *pnt1++; + *pnt = 0; + strcat(sbuffer, ".DIR;1"); + }; + + spath = sbuffer; + }; + return (stat_filter(spath, spnt)); +} + +static int dircontext[32] = {0, }; +static char *searchpath[32]; +static struct direct d_entry[32]; + +int optind = 0; +char *optarg; + +int +getopt(int argc, char *argv[], char *flags) +{ + char *pnt; + char c; + + optind++; + if (*argv[optind] != '-') + return (EOF); + optarg = 0; + + c = *(argv[optind] + 1); + pnt = (char *) strchr(flags, c); + if (!pnt) + return (c); /* Not found */ + if (pnt[1] == ':') { + optind++; + optarg = argv[optind]; + }; + return (c); +} + +void +vms_path_fixup(char *name) +{ + char *pnt1; + + pnt1 = name + strlen(name) - 6; + + /* First strip the .DIR;1 */ + if (strcmp(pnt1, ".DIR;1") == 0) + *pnt1 = 0; + + pnt1 = (char *) strrchr(name, ']'); + if (pnt1) { + if (pnt1[1] == 0) + return; + *pnt1 = '.'; + strcat(name, "]"); + return; + }; + pnt1 = (char *) strrchr(name, '>'); + if (pnt1) { + if (pnt1[1] == 0) + return; + *pnt1 = '.'; + strcat(name, ">"); + return; + }; +} + +int +opendir(char *path) +{ + int i; + + for (i = 1; i < 32; i++) { + if (dircontext[i] == 0) { + dircontext[i] = -1; + searchpath[i] = (char *) e_malloc(strlen(path) + 6); + strcpy(searchpath[i], path); + vms_path_fixup(searchpath[i]); + strcat(searchpath[i], "*.*.*"); + return (i); + }; + }; + exit(0); +} + +struct direct * +readdir(int context) +{ + int i; + char cresult[100]; + char *pnt; + int status; + + $DESCRIPTOR(dpath, searchpath[context]); + $DESCRIPTOR(result, cresult); + + if (dircontext[context] == -1) { + dircontext[context] = -2; + strcpy(d_entry[context].d_name, "."); + return (&d_entry[context]); + }; + + if (dircontext[context] == -2) { + dircontext[context] = -3; + strcpy(d_entry[context].d_name, ".."); + return (&d_entry[context]); + }; + + if (dircontext[context] == -3) + dircontext[context] = 0; + + dpath.dsc$w_length = strlen(searchpath[context]); + lib$find_file(&dpath, &result, &dircontext[context], + 0, 0, &status, 0); + + if (status == SS$_NOMOREFILES) + return (0); + + /* Now trim trailing spaces from the name */ + i = result.dsc$w_length - 1; + while (i && cresult[i] == ' ') + i--; + cresult[i + 1] = 0; + + /* Now locate the actual portion of the file we want */ + + pnt = (char *) strrchr(cresult, ']'); + if (pnt) + pnt++; + else + pnt = cresult; + + strcpy(d_entry[context].d_name, pnt); + return (&d_entry[context]); +} + +void +closedir(int context) +{ + lib$find_file_end(&dircontext[context]); + free(searchpath[context]); + searchpath[context] = (char *) 0; + dircontext[context] = 0; +} + +static +open_file(char *fn) +{ + /* + * this routine initializes a rab and fab required to get the + * correct definition of the external data file used by mail + */ + struct FAB *fab; + + rab = (struct RAB *) e_malloc(sizeof (struct RAB)); + fab = (struct FAB *) e_malloc(sizeof (struct FAB)); + + *rab = cc$rms_rab; /* initialize RAB */ + rab->rab$l_fab = fab; + + *fab = cc$rms_fab; /* initialize FAB */ + fab->fab$l_fna = fn; + fab->fab$b_fns = strlen(fn); + fab->fab$w_mrs = 512; + fab->fab$b_fac = FAB$M_BIO | FAB$M_GET; + fab->fab$b_org = FAB$C_SEQ; + fab->fab$b_rfm = FAB$C_FIX; + fab->fab$l_xab = (char *) 0; + + rms_status = sys$open(rab->rab$l_fab); + if (rms_status != RMS$_NORMAL && rms_status != RMS$_CREATED) + error_exit("$OPEN"); + rms_status = sys$connect(rab); + if (rms_status != RMS$_NORMAL) + error_exit("$CONNECT"); + return (1); +} + +static +close_file(struct RAB * prab) +{ + rms_status = sys$close(prab->rab$l_fab); + free(prab->rab$l_fab); + free(prab); + if (rms_status != RMS$_NORMAL) + error_exit("$CLOSE"); +} + +#define NSECT 16 +extern unsigned int last_extent_written; + +int +vms_write_one_file(char *filename, off_t size, FILE * outfile) +{ + int status, + i; + char buffer[SECTOR_SIZE * NSECT]; + int count; + int use; + off_t 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/genisoimage/vms.h b/genisoimage/vms.h new file mode 100644 index 0000000..722fb82 --- /dev/null +++ b/genisoimage/vms.h @@ -0,0 +1,29 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)vms.h 1.3 04/03/01 eric */ +/* + * Header file genisoimage.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 + +extern int vms_write_one_file(char *filename, off_t size, FILE * outfile); + +#endif diff --git a/genisoimage/volume.c b/genisoimage/volume.c new file mode 100644 index 0000000..dd45336 --- /dev/null +++ b/genisoimage/volume.c @@ -0,0 +1,728 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)volume.c 1.14 04/07/09 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */ +/* + * Copyright (c) 1997, 1998, 1999, 2000 James Pearson + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * volume.c: prepare HFS volume for mkhybrid + * + * James Pearson 17/7/97 + * modified JCP 29/7/97 to improve allocation sizes to cut + * down on wasted space. Now uses the HFS "allocation" size rounded + * up to the nearest 2048 bytes. Savings can be significant with + * a large volume containing lots of smallish files. + * + * Updated for v1.12 - now uses the built in RELOCATED_DIRECTORY + * flag for finding the real directory location JCP 8/1/97 + */ + +#ifdef APPLE_HYB + +#include <mconfig.h> +#include "genisoimage.h" +#include <errno.h> + +#define HFS_MIN_SIZE 1600 /* 800k == 1600 HFS blocks */ + +static hfsvol *vol_save = 0; /* used to "destroy" an HFS volume */ + +static int AlcSiz(Ulong); +static int XClpSiz(Ulong); +static int get_vol_size(int); +int write_fork(hfsfile * hfp, long tot); +int make_mac_volume(struct directory *, int); +static int copy_to_mac_vol(hfsvol *, struct directory *); +static void set_dir_info(hfsvol *, struct directory *); + +/* + * AlcSiz: find allocation size for given volume size + */ +static int +AlcSiz(Ulong vlen) +{ + int lpa, + drAlBlkSiz; + + /* code extracted from hfs_format() */ + lpa = 1 + vlen / 65536; + drAlBlkSiz = lpa * HFS_BLOCKSZ; + + /* + * now set our "allocation size" to the allocation block rounded up to + * the nearest SECTOR_SIZE (2048 bytes) + */ + drAlBlkSiz = ROUND_UP(drAlBlkSiz, SECTOR_SIZE); + + return (drAlBlkSiz); +} + +/* + * XClpSiz: find the default size of the catalog/extent file + */ +static int +XClpSiz(Ulong vlen) +{ + int olpa, + lpa, + drNmAlBlks, + drAlBlkSiz; + int vbmsz, + drXTClpSiz; + + /* code extracted from hfs_format() */ + + /* get the lpa from our calculated allocation block size */ + drAlBlkSiz = AlcSiz(vlen); + lpa = drAlBlkSiz / HFS_BLOCKSZ; + + vbmsz = (vlen / lpa + 4095) / 4096; + drNmAlBlks = (vlen - 5 - vbmsz) / lpa; + drXTClpSiz = drNmAlBlks / 128 * drAlBlkSiz; + + /* override the drXTClpSiz size for large volumes */ + if (drXTClpSiz > hce->max_XTCsize) { + drXTClpSiz = hce->max_XTCsize; + } else { + /* + * make allowances because we have possibly rounded up the + * allocation size get the "original" lpa " + */ + olpa = 1 + vlen / 65536; + + /* adjust size upwards */ + drXTClpSiz = ((Ullong)drXTClpSiz * lpa) / olpa; + } + + /* round up to the nearest allocation size */ + drXTClpSiz = ROUND_UP(drXTClpSiz, drAlBlkSiz); + + return (drXTClpSiz); +} + +/* + * get_vol_size: get the size of the volume including the extent/catalog + */ +static int +get_vol_size(int vblen) +{ + int drXTClpSiz; + int drAlBlkSiz; + int new_vblen; + + /* + * try to estimate a "volume size" based on the code in hfs_format + * - we need the size of the catalog/extents and Desktop files included + * in the volume, as we add this to the end of the ISO volume + */ + drXTClpSiz = XClpSiz(vblen); + drAlBlkSiz = AlcSiz(vblen); + + /* + * catalog file is set at CTC times (default twice) the extents + * file size - hence the (ctc_size + 1) below. The Desktop starts of + * the same size as the "clump size" == 4 x drAlBlkSiz, + * plus a spare drAlBlkSiz for the alternative MDB + */ + new_vblen = vblen + + ((hce->ctc_size + 1) * drXTClpSiz + 5 * drAlBlkSiz) / HFS_BLOCKSZ; + + return (new_vblen); +} + +/* + * write_fork: "write" file data to the volume + * + * This is used to update the HFS file internal structures + * but no data is actually written (it's trapped deep down in + * libhfs). + */ +int +write_fork(hfsfile *hfp, long tot) +{ + char blk[HFS_BLOCKSZ]; + unsigned short start; + long len; + + len = tot; + /* we need to know where this fork starts */ + start = hfs_get_drAllocPtr(hfp); + + /* loop through the data a block at a time */ + while (len >= HFS_BLOCKSZ) { + if (hfs_write(hfp, blk, HFS_BLOCKSZ) < 0) + return (-1); + len -= HFS_BLOCKSZ; + } + /* write out anything left */ + if (len) + if (hfs_write(hfp, blk, len) < 0) + return (-1); + + /* + * set the start of the allocation search to be immediately after + * this fork + */ + hfs_set_drAllocPtr(hfp, start, tot); + + return (0); +} + +/* + * make_mac_volume: "create" an HFS volume using the ISO data + * + * The HFS volume structures are set up (but no data is written yet). + * + * ISO volumes have a allocation size of 2048 bytes - regardless + * of the size of the volume. HFS allocation size is depends on volume + * size, so we may have to update the ISO structures to add in any + * padding. + */ +int +make_mac_volume(struct directory *dpnt, int start_extent) +{ + char vol_name[HFS_MAX_VLEN + 1]; /* Mac volume name */ + hfsvol *vol; /* Mac volume */ + int vblen; /* vol length (HFS blocks) */ + int Csize, + lastCsize; /* allocation sizes */ + int ret = 0; /* return value */ + int loop = 1; + + /* umount volume if we have had a previous attempt */ + if (vol_save) + if (hfs_umount(vol_save, 0, hfs_lock) < 0) + return (-1); + + /* set the default clump size to the ISO block size */ + Csize = lastCsize = SECTOR_SIZE; + + if (verbose > 1) + fprintf(stderr, "Creating HFS Volume info\n"); + + /* name or copy ISO volume name to Mac Volume name */ + strncpy(vol_name, hfs_volume_id ? hfs_volume_id : volume_id, + HFS_MAX_VLEN); + vol_name[HFS_MAX_VLEN] = '\0'; + + /* get initial size of HFS volume (size of current ISO volume) */ + vblen = (last_extent - session_start) * HFS_BLK_CONV; + + /* make sure volume is at least 800k */ + if (vblen < HFS_MIN_SIZE) + vblen += insert_padding_file(HFS_MIN_SIZE - vblen); + + /* + * add on size of extents/catalog file, but this may mean the + * allocation size will change, so loop round until the + * allocation size doesn't change + */ + while (loop) { + hce->XTCsize = XClpSiz(vblen); + vblen = get_vol_size(vblen); + Csize = AlcSiz(vblen); + + if (Csize == lastCsize) { + /* allocation size hasn't changed, so carry on */ + loop = 0; + } else { + /* + * allocation size has changed, so update + * ISO volume size + */ + if ((vblen = get_adj_size(Csize)) < 0) { + sprintf(hce->error, + "too many files for HFS volume"); + return (-1); + } + vblen += + ROUND_UP((start_extent - session_start) * + HFS_BLK_CONV, Csize); + lastCsize = Csize; + } + } + + /* take off the label/map size */ + vblen -= hce->hfs_map_size; + + hce->hfs_vol_size = vblen; + + /* set the default allocation size for libhfs */ + hce->Csize = Csize; + + /* format and mount the "volume" */ + if (hfs_format(hce, 0, vol_name) < 0) { + sprintf(hce->error, "can't HFS format %s", vol_name); + return (-1); + } + /* + * update the ISO structures with new start extents and any + * padding required + */ + if (Csize != SECTOR_SIZE) { + last_extent = adj_size(Csize, start_extent, + hce->hfs_hdr_size + hce->hfs_map_size); + adj_size_other(dpnt); + } + if ((vol = hfs_mount(hce, 0, 0)) == 0) { + sprintf(hce->error, "can't HFS mount %s", vol_name); + return (-1); + } + /* save the volume for possible later use */ + vol_save = vol; + + /* + * Recursively "copy" the files to the volume + * - we need to know the first allocation block in the volume as + * starting blocks of files are relative to this. + */ + ret = copy_to_mac_vol(vol, dpnt); + if (ret < 0) + return (ret); + + /* + * make the Desktop files - I *think* this stops the Mac rebuilding the + * desktop when the CD is mounted on a Mac These will be ignored if they + * already exist + */ + if (create_dt) + ret = make_desktop(vol, + (last_extent - session_start) * HFS_BLK_CONV); + if (ret < 0) + return (ret); + + /* close the volume */ + if (hfs_flush(vol) < 0) + return (-1); + + /* unmount and set the start blocks for the catalog/extents files */ + if (hfs_umount(vol, (last_extent - session_start) * HFS_BLK_CONV, hfs_lock) < 0) + return (-1); + + return (Csize); +} + +#define TEN 10 /* well, it is! */ +#define LCHAR "_" + +/* + * copy_to_mac_vol: copy all files in a directory to corresponding + * Mac folder. + * + * Files are copied recursively to corresponding folders on the Mac + * volume. The caller routine needs to do a hfs_chdir before calling this + * routine. + */ +static int +copy_to_mac_vol(hfsvol *vol, struct directory *node) +{ + struct directory_entry *s_entry; /* ISO directory entry */ + struct directory_entry *s_entry1; /* tmp ISO directory entry */ + struct directory *dpnt; /* ISO directory */ + + hfsfile *hfp; /* HFS file */ + hfsdirent *ent; /* HFS file entities */ + long id; /* current HFS folder */ + long dext, + rext; /* real data/rsrc start blk */ + int ret; /* result code */ + int new_name; /* HFS file has modified name */ + + int tens; + int digits; + int i; + + /* store the current HFS directory ID */ + if ((id = hfs_getcwd(vol)) == 0) + return (-1); + + if (verbose > 1) + fprintf(stderr, "HFS scanning %s\n", node->whole_name); + + /* loop through the ISO directory entries and process files */ + for (s_entry = node->contents; s_entry; s_entry = s_entry->next) { + /* ignore directory and associated (rsrc) files */ + if (s_entry->isorec.flags[0] & (ISO_DIRECTORY|ISO_ASSOCIATED)) + continue; + + /* ignore any non-Mac type file */ + if (!s_entry->hfs_ent) + continue; + + /* + * ignore if from a previous session + * - should be trapped above + */ + if (s_entry->starting_block < session_start) + continue; + +#ifdef DEBUG + fprintf(stderr, " Name = %s", s_entry->whole_name); + fprintf(stderr, " Startb = %d\n", s_entry->starting_block); +#endif /* DEBUG */ + + ent = s_entry->hfs_ent; + + /* create file */ + i = HFS_MAX_FLEN - strlen(ent->name); + new_name = 0; + tens = TEN; + digits = 1; + + while (1) { + /* + * try to open file - if it exists, + * then append '_' to the name and try again + */ + errno = 0; + if ((hfs_create(vol, ent->name, ent->u.file.type, + ent->u.file.creator)) < 0) { + if (errno != EEXIST) { + /* + * not an "exist" error, or we can't + * append as the filename is already + * HFS_MAX_FLEN chars + */ + sprintf(hce->error, + "can't HFS create file %s", + s_entry->whole_name); + return (-1); + } else if (i == 0) { + /* + * File name at max HFS length + * - make unique name + */ + if (!new_name) + new_name++; + + sprintf(ent->name + + HFS_MAX_FLEN - digits - 1, + "%s%d", LCHAR, new_name); + new_name++; + if (new_name == tens) { + tens *= TEN; + digits++; + } + } else { + /* append '_' to get new name */ + strcat(ent->name, LCHAR); + i--; + new_name = 1; + } + } else + break; + } + + /* warn that we have a new name */ + if (new_name && verbose > 0) { + fprintf(stderr, "Using HFS name: %s for %s\n", + ent->name, + s_entry->whole_name); + } + /* open file */ + if ((hfp = hfs_open(vol, ent->name)) == 0) { + sprintf(hce->error, "can't HFS open %s", + s_entry->whole_name); + return (-1); + } + /* if it has a data fork, then "write" it out */ + if (ent->u.file.dsize) + write_fork(hfp, ent->u.file.dsize); + + /* if it has a resource fork, set the fork and "write" it out */ + if (ent->u.file.rsize) { + if ((hfs_setfork(hfp, 1)) < 0) + return (-1); + write_fork(hfp, ent->u.file.rsize); + } + + /* make file invisible if ISO9660 hidden */ + if (s_entry->de_flags & HIDDEN_FILE) + ent->fdflags |= HFS_FNDR_ISINVISIBLE; + + /* update any HFS file attributes */ + if ((hfs_fsetattr(hfp, ent)) < 0) { + sprintf(hce->error, "can't HFS set attributes %s", + s_entry->whole_name); + return (-1); + } + /* + * get the ISO starting block of data fork (may be zero) + * and convert to the equivalent HFS block + */ + if (ent->u.file.dsize) { + dext = (s_entry->starting_block - session_start) * + HFS_BLK_CONV; + } else { + dext = 0; + } + + /* + * if the file has a resource fork (associated file), + * get it's ISO starting block and convert as above + */ + if (s_entry->assoc && ent->u.file.rsize) { + rext = + (s_entry->assoc->starting_block - session_start) * + HFS_BLK_CONV; + } else { + rext = 0; + } + + /* close the file and update the starting blocks */ + if (hfs_close(hfp, dext, rext) < 0) { + sprintf(hce->error, "can't HFS close file %s", + s_entry->whole_name); + return (-1); + } + } + + /* set folder info and custom icon (if it exists) */ + set_dir_info(vol, node); + + /* + * process sub-directories - have a slight problem here, + * if the directory had been relocated, then we need to find the + * real directory - we do this by first finding the + * real directory_entry, and then finding it's directory info + */ + + /* following code taken from joliet.c */ + for (s_entry = node->contents; s_entry; s_entry = s_entry->next) { + if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) { + /* + * if the directory has been reloacted, then search the + * relocated directory for the real entry + */ + for (s_entry1 = reloc_dir->contents; s_entry1; + s_entry1 = s_entry1->next) { + if (s_entry1->parent_rec == s_entry) + break; + } + + /* have a problem - can't find the real directory */ + if (s_entry1 == NULL) { + sprintf(hce->error, + "can't locate relocated directory %s", + s_entry->whole_name); + return (-1); + } + } else + s_entry1 = s_entry; + + /* now have the correct entry - now find the actual directory */ + if ((s_entry1->isorec.flags[0] & ISO_DIRECTORY) && + strcmp(s_entry1->name, ".") && + strcmp(s_entry1->name, "..")) { + if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) + dpnt = reloc_dir->subdir; + else + dpnt = node->subdir; + + while (1) { + if (dpnt->self == s_entry1) + break; + dpnt = dpnt->next; + if (!dpnt) { + sprintf(hce->error, + "can't find directory location %s", + s_entry1->whole_name); + return (-1); + } + } + /* + * now have the correct directory + * - so do the HFS stuff + */ + ent = dpnt->hfs_ent; + + /* + * if we don't have hfs entries, then this is a "deep" + * directory - this will be processed later + */ + if (!ent) + continue; + + /* make sub-folder */ + i = HFS_MAX_FLEN - strlen(ent->name); + new_name = 0; + tens = TEN; + digits = 1; + + while (1) { + /* + * try to create new directory + * - if it exists, then append '_' to the name + * and try again + */ + errno = 0; + if (hfs_mkdir(vol, ent->name) < 0) { + if (errno != EEXIST) { + /* + * not an "exist" error, + * or we can't append as the + * filename is already + * HFS_MAX_FLEN chars + */ + sprintf(hce->error, + "can't HFS create folder %s", + s_entry->whole_name); + return (-1); + } else if (i == 0) { + /* + * File name at max HFS length + * - make unique name + */ + if (!new_name) + new_name++; + + sprintf(ent->name + + HFS_MAX_FLEN - digits - 1, + "%s%d", LCHAR, new_name); + new_name++; + if (new_name == tens) { + tens *= TEN; + digits++; + } + } else { + /* append '_' to get new name */ + strcat(ent->name, LCHAR); + i--; + new_name = 1; + } + } else + break; + } + + /* warn that we have a new name */ + if (new_name && verbose > 0) { + fprintf(stderr, "Using HFS name: %s for %s\n", + ent->name, + s_entry->whole_name); + } + /* see if we need to "bless" this folder */ + if (hfs_bless && strcmp(s_entry->whole_name, hfs_bless) + == 0) { + hfs_stat(vol, ent->name, ent); + hfs_vsetbless(vol, ent->cnid); + if (verbose > 0) { + fprintf(stderr, "Blessing %s (%s)\n", + ent->name, + s_entry->whole_name); + } + /* stop any further checks */ + hfs_bless = NULL; + } + /* change to sub-folder */ + if (hfs_chdir(vol, ent->name) < 0) + return (-1); + + /* recursively copy files ... */ + ret = copy_to_mac_vol(vol, dpnt); + if (ret < 0) + return (ret); + + /* change back to this folder */ + if (hfs_setcwd(vol, id) < 0) + return (-1); + } + } + + return (0); +} + +/* + * set_dir_info: Set directory info for a file - also use a custom + * Icon - if it exists. + * + * Sets folder' layout (window layout, view, scroll bars etc) + * + * Set the 'HFS_FNDR_HASCUSTOMICON' bit of the folder flags + * if a file called 'Icon\r' exists in the folder + * + * Also makes sure the Icon file is invisible + * Don't worry if any of this fails ... + * + * Thanks to Rob Leslie <rob@mars.org> for how to do this. + */ + +#define ICON "Icon" + +static void +set_dir_info(hfsvol *vol, struct directory *de) +{ + hfsdirent *ent = de->hfs_ent; + hfsdirent ent1; + char name[HFS_MAX_FLEN + 1]; + unsigned short flags = 0; + + memset(&ent1, 0, sizeof (hfsdirent)); + + sprintf(name, "%s\r", ICON); + + /* get the attributes for the Icon file */ + if (hfs_stat(vol, name, &ent1) == 0) { + + /* make sure it is invisible */ + ent1.fdflags |= HFS_FNDR_ISINVISIBLE; + + /* set the new attributes for the Icon file */ + hfs_setattr(vol, name, &ent1); + + /* flag the folder as having a custom icon */ + flags |= HFS_FNDR_HASCUSTOMICON; + } + + /* make the current folder invisible if ISO9660 hidden */ + if (de->self->de_flags & HIDDEN_FILE) { + flags |= HFS_FNDR_ISINVISIBLE; + } + + /* may not have an hfs_ent for this directory */ + if (ent == NULL) { + ent = &ent1; + memset(ent, 0, sizeof (hfsdirent)); + + /* get the attributes for the folder */ + if (hfs_stat(vol, ":", ent) < 0) + return; + } + + /* set HFS_FNDR_HASCUSTOMICON/HFS_FNDR_ISINVISIBLE if needed */ + ent->fdflags |= flags; + + /* set the new attributes for the folder */ + if (hfs_setattr(vol, ":", ent) < 0) { + /* + * Only needed if we add things after this if statement. + */ +/* return;*/ + } +} + +#endif /* APPLE_HYB */ diff --git a/genisoimage/write.c b/genisoimage/write.c new file mode 100644 index 0000000..a423ab1 --- /dev/null +++ b/genisoimage/write.c @@ -0,0 +1,2840 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)write.c 1.88 06/02/01 joerg */ +/* Parts from @(#)write.c 1.106 07/02/17 joerg */ +/* + * Program write.c - dump memory structures to file for iso9660 filesystem. + * + * Written by Eric Youngdale (1993). + * + * Copyright 1993 Yggdrasil Computing, Incorporated + * Copyright (c) 1999-2003 J. Schilling + * + * 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. + */ + +/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */ + +#include <mconfig.h> +#include "genisoimage.h" +#include <timedefs.h> +#include <fctldefs.h> +#ifdef SORTING +#include "match.h" +#endif /* SORTING */ +#include <errno.h> +#include <schily.h> +#ifdef DVD_VIDEO +#include "dvd_reader.h" +#include "dvd_file.h" +#include "ifo_read.h" +#endif +#ifdef APPLE_HYB +#include <ctype.h> +#endif + +#ifdef VMS +#include "vms.h" +#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 int next_path_index = 1; +static int sort_goof; + +static int is_rr_dir = 0; + +struct output_fragment *out_tail; +struct output_fragment *out_list; + +struct iso_primary_descriptor vol_desc; + +void set_721(char *pnt, unsigned int i); +void set_722(char *pnt, unsigned int i); +void set_723(char *pnt, unsigned int i); +void set_731(char *pnt, unsigned int i); +void set_732(char *pnt, unsigned int i); +void set_733(char *pnt, unsigned int i); +int get_731(char *p); +int get_732(char *p); +int get_733(char *p); +static int xawrite(void *buffer, int size, int count, FILE *file, + int submode, BOOL islast); +void xfwrite(void *buffer, int size, int count, FILE *file, int submode, + BOOL islast); +static int assign_directory_addresses(struct directory *node); +#ifdef APPLE_HYB +static void write_one_file(char *filename, off_t size, FILE *outfile, + off_t off); +#else +static void write_one_file(char *filename, off_t size, FILE *outfile); +#endif +static void write_files(FILE *outfile); +#if 0 +static void dump_filelist __PR((void)); +#endif +static int compare_dirs(const void *rr, const void *ll); +int sort_directory(struct directory_entry **sort_dir, int rr); +static int root_gen(void); +static BOOL assign_file_addresses(struct directory *dpnt, BOOL isnest); +static void free_one_directory(struct directory *dpnt); +static void free_directories(struct directory *dpnt); +void generate_one_directory(struct directory *dpnt, FILE *outfile); +static void build_pathlist(struct directory *node); +static int compare_paths(void const *r, void const *l); +static int generate_path_tables(void); +void memcpy_max(char *to, char *from, int max); +void outputlist_insert(struct output_fragment *frag); +static int file_write(FILE *outfile); +static int pvd_write(FILE *outfile); +static int xpvd_write(FILE *outfile); +static int evd_write(FILE *outfile); +static int vers_write(FILE *outfile); +static int graftcp(char *to, char *from, char *ep); +static int pathcp(char *to, char *from, char *ep); +static int pathtab_write(FILE *outfile); +static int exten_write(FILE *outfile); +int oneblock_size(int starting_extent); +static int pathtab_size(int starting_extent); +static int startpad_size(int starting_extent); +static int interpad_size(int starting_extent); +static int endpad_size(int starting_extent); +static int file_gen(void); +static int dirtree_dump(void); +static int dirtree_fixup(int starting_extent); +static int dirtree_size(int starting_extent); +static int ext_size(int starting_extent); +static int dirtree_write(FILE *outfile); +static int dirtree_cleanup(FILE *outfile); +static int startpad_write(FILE *outfile); +static int interpad_write(FILE *outfile); +static int endpad_write(FILE *outfile); +#ifdef APPLE_HYB +static int hfs_pad; +static int hfs_get_parms(char *key); +static void hfs_file_gen(int start_extent); +static void gen_prepboot(void); +Ulong get_adj_size(int Csize); +int adj_size(int Csize, int start_extent, int extra); +void adj_size_other(struct directory *dpnt); +static int hfs_hce_write(FILE * outfile); +int insert_padding_file(int size); +#endif /* APPLE_HYB */ + +#ifdef SORTING +static int compare_sort(const void * rr, const void * ll); +static void reassign_link_addresses(struct directory * dpnt); +static int sort_file_addresses(void); +#endif /* SORTING */ + +/* + * 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 +set_721(char *pnt, unsigned int i) +{ + pnt[0] = i & 0xff; + pnt[1] = (i >> 8) & 0xff; +} + +void +set_722(char *pnt, unsigned int i) +{ + pnt[0] = (i >> 8) & 0xff; + pnt[1] = i & 0xff; +} + +void +set_723(char *pnt, unsigned int i) +{ + pnt[3] = pnt[0] = i & 0xff; + pnt[2] = pnt[1] = (i >> 8) & 0xff; +} + +void +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 +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; +} + +void +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; +} + +int +get_731(char *p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +int +get_732(char *p) +{ + return ((p[3] & 0xff) + | ((p[2] & 0xff) << 8) + | ((p[1] & 0xff) << 16) + | ((p[0] & 0xff) << 24)); +} + +int +get_733(char *p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +void +xfwrite(void *buffer, int size, int count, FILE *file, int submode, BOOL islast) +{ + /* + * This is a hack that could be made better. + * XXXIs this the only place? + * It is definitely needed on Operating Systems that do not allow to + * write files that are > 2GB. If the system is fast enough to be able + * to feed 1400 KB/s writing speed of a DVD-R drive, use stdout. + * If the system cannot do this reliable, you need to use this hacky + * option. + */ + static int idx = 0; + +#ifdef XFWRITE_DEBUG + if (count != 1 || (size % 2048) != 0) + fprintf(stderr, "Count: %d, size: %d\n", count, size); +#endif + + if (split_output != 0 && + (idx == 0 || ftell(file) >= ((off_t)1024 * 1024 * 1024))) { + char nbuf[512]; + extern char *outfile; + + if (idx == 0) + unlink(outfile); + sprintf(nbuf, "%s_%02d", outfile, idx++); + file = freopen(nbuf, "wb", file); + if (file == NULL) { +#ifdef USE_LIBSCHILY + comerr("Cannot open '%s'.\n", nbuf); +#else + fprintf(stderr, "Cannot open '%s'.\n", nbuf); + exit(1); +#endif + } + } + while (count) { + int got; + + seterrno(0); + if (osecsize != 0) + got = xawrite(buffer, size, count, file, submode, islast); + else + got = fwrite(buffer, size, count, file); + + if (got <= 0) { +#ifdef USE_LIBSCHILY + comerr("cannot fwrite %d*%d\n", size, count); +#else + fprintf(stderr, "cannot fwrite %d*%d\n", size, count); + exit(1); +#endif + } + /* + * This comment is in hope to prevent silly people from + * e.g. SuSE (who did not yet learn C but believe that + * they need to patch other peoples code) from changing the + * next cast into an illegal lhs cast expression. + * The cast below is the correct way to handle the problem. + * The (void *) cast is to avoid a GCC warning like: + * "warning: dereferencing type-punned pointer will break \ + * strict-aliasing rules" + * which is wrong this code. (void *) introduces a compatible + * intermediate type in the cast list. + */ + count -= got; + buffer = (void *)(((char *)buffer) + size * got); + } +} + +static int +xawrite(void *buffer, int size, int count, FILE *file, int submode, BOOL islast) +{ + register char *p = buffer; + register int amt = size * count; + register int n; + struct xa_subhdr subhdr[2]; + + if (osecsize == 2048) + return (fwrite(buffer, size, count, file)); + + if (amt % 2048) + comerrno(EX_BAD, + "Trying to write %d bytes (not a multiple of 2048).\n", + amt); + + subhdr[0].file_number = subhdr[1].file_number = 0; + subhdr[0].channel_number = subhdr[1].channel_number = 0; + subhdr[0].coding = subhdr[1].coding = 0; + + while (amt > 0) { +#ifdef LATER + if (submode < 0) + subhdr[0].sub_mode = subhdr[1].sub_mode = XA_SUBH_DATA; + else + subhdr[0].sub_mode = subhdr[1].sub_mode = submode; +#else + subhdr[0].sub_mode = subhdr[1].sub_mode = XA_SUBH_DATA; +#endif + + if ((amt <= 2048) && islast) { + subhdr[0].sub_mode = subhdr[1].sub_mode + |= (XA_SUBH_EOR|XA_SUBH_EOF); + } + n = fwrite(&subhdr, sizeof (subhdr), 1, file); + if (n <= 0) + return (n); + + n = fwrite(p, 2048, 1, file); + if (n <= 0) + return (n); + + p += 2048; + amt -= 2048; + } + return (1); +} + +#ifdef APPLE_HYB +/* + * use the deferred_write struct to store info about the hfs_boot_file + */ +static struct deferred_write mac_boot; + +#endif /* APPLE_HYB */ +static struct deferred_write *dw_head = NULL, + *dw_tail = NULL; + +unsigned int last_extent_written = 0; +static Uint path_table_index; +time_t begun; + +/* + * We recursively walk through all of the directories and assign extent + * numbers to them. We have already assigned extent numbers to everything that + * goes in front of them + */ +static int +assign_directory_addresses(struct directory *node) +{ + int dir_size; + struct directory *dpnt; + + dpnt = node; + + while (dpnt) { + /* skip if it's hidden */ + if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) { + dpnt = dpnt->next; + continue; + } + /* + * If we already have an extent for this (i.e. it came from a + * multisession disc), then don't reassign a new extent. + */ + dpnt->path_index = next_path_index++; + if (dpnt->extent == 0) { + dpnt->extent = last_extent; + dir_size = ISO_BLOCKS(dpnt->size); + + 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 += ISO_BLOCKS(dpnt->ce_bytes); + } + } + if (dpnt->subdir) { + assign_directory_addresses(dpnt->subdir); + } + dpnt = dpnt->next; + } + return (0); +} + +#ifdef APPLE_HYB +static void +write_one_file(char *filename, off_t size, FILE *outfile, off_t off) +#else +static void +write_one_file(char *filename, off_t size, FILE *outfile) +#endif /* APPLE_HYB */ +{ + /* + * It seems that there are still stone age C-compilers + * around. + * The Metrowerks C found on BeOS/PPC does not allow + * more than 32kB of local vars. + * As we do not need to call write_one_file() recursively + * we make buffer static. + */ +static char buffer[SECTOR_SIZE * NSECT]; + FILE *infile; + off_t remain; + int use; + + char *mirror_name; + unsigned char md5[16]; + int include_in_jigdo = list_file_in_jigdo(filename, size, &mirror_name, md5); + + if ((infile = fopen(filename, "rb")) == NULL) { +#ifdef USE_LIBSCHILY + comerr("cannot open '%s'\n", filename); +#else +#ifndef HAVE_STRERROR + fprintf(stderr, "cannot open '%s': (%d)\n", + filename, errno); +#else + fprintf(stderr, "cannot open '%s': %s\n", + filename, strerror(errno)); +#endif + exit(1); +#endif + } +#ifdef APPLE_HYB + fseek(infile, off, SEEK_SET); +#endif /* APPLE_HYB */ + remain = size; + + if (include_in_jigdo) + write_jt_match_record(filename, mirror_name, SECTOR_SIZE, size, md5); + + while (remain > 0) { + int amt; + + use = (remain > SECTOR_SIZE * NSECT - 1 ? + NSECT * SECTOR_SIZE : remain); + use = ISO_ROUND_UP(use); /* Round up to nearest sector */ + /* boundary */ + memset(buffer, 0, use); + seterrno(0); + amt = fread(buffer, 1, use, infile); + if (amt < use && amt < remain) { + /* + * Note that genisoimage is not star and no 100% archiver. + * We only detect file growth if the new size does not + * match 'use' at the last read. + */ + if (geterrno() == 0) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "File '%s' did shrink.\n" + "Files must not be changed while genisoimage runs!\n", + filename); +#else + fprintf(stderr, + "File '%s' did shrink.\n" + "Files must not be changed while genisoimage runs!\n", + filename); + exit(EX_BAD); +#endif + } +#ifdef USE_LIBSCHILY + comerr("Cannot read from '%s'\n", filename); +#else + fprintf(stderr, "Cannot read from '%s'\n", filename); + exit(1); +#endif + } + if (!include_in_jigdo) + jtwrite(buffer, use, 1, + XA_SUBH_DATA, remain <= (SECTOR_SIZE * NSECT)); + xfwrite(buffer, use, 1, outfile, + XA_SUBH_DATA, remain <= (SECTOR_SIZE * NSECT)); + last_extent_written += use / SECTOR_SIZE; +#if 0 + if ((last_extent_written % 1000) < use / SECTOR_SIZE) { + fprintf(stderr, "%d..", last_extent_written); + } +#else + if (verbose > 0 && + (int)(last_extent_written % (gui ? 500 : 5000)) < + use / SECTOR_SIZE) { + time_t now; + time_t the_end; + double frac; + + time(&now); + frac = last_extent_written / (1.0 * last_extent); + the_end = begun + (now - begun) / frac; +#ifndef NO_FLOATINGPOINT + fprintf(stderr, "%6.2f%% done, estimate finish %s", + frac * 100., ctime(&the_end)); +#else + fprintf(stderr, "%3d.%-02d%% done, estimate finish %s", + (int)(frac * 100.), + (int)((frac+.00005) * 10000.)%100, + ctime(&the_end)); +#endif + fflush(stderr); + } +#endif + remain -= use; + } + fclose(infile); +}/* write_one_file(... */ + +static void +write_files(FILE *outfile) +{ + struct deferred_write *dwpnt, + *dwnext; + + dwpnt = dw_head; + while (dwpnt) { +/*#define DEBUG*/ +#ifdef DEBUG + fprintf(stderr, + "The file name is %s and pad is %d, size is %lld and extent is %d\n", + dwpnt->name, dwpnt->pad, + (Llong)dwpnt->size, dwpnt->extent); +#endif + if (dwpnt->table) { + jtwrite(dwpnt->table, ISO_ROUND_UP(dwpnt->size), 1, XA_SUBH_DATA, TRUE); + xfwrite(dwpnt->table, ISO_ROUND_UP(dwpnt->size), 1, + outfile, + XA_SUBH_DATA, TRUE); + last_extent_written += ISO_BLOCKS(dwpnt->size); + table_size += dwpnt->size; +/* fprintf(stderr, "Size %lld ", (Llong)dwpnt->size); */ + free(dwpnt->table); + dwpnt->table = NULL; + } else { + +#ifdef VMS + vms_write_one_file(dwpnt->name, dwpnt->size, outfile); +#else +#ifdef APPLE_HYB + write_one_file(dwpnt->name, dwpnt->size, outfile, + dwpnt->off); +#else + write_one_file(dwpnt->name, dwpnt->size, outfile); +#endif /* APPLE_HYB */ +#endif + free(dwpnt->name); + dwpnt->name = NULL; + } + + +#ifndef DVD_VIDEO +#define dvd_video 0 +#endif + +#ifndef APPLE_HYB +#define apple_hyb 0 +#endif + +#if defined(APPLE_HYB) || defined(DVD_VIDEO) + + if (apple_hyb || dvd_video) { + /* + * we may have to pad out ISO files to work with HFS + * clump sizes + */ + char blk[SECTOR_SIZE]; + Uint i; + + for (i = 0; i < dwpnt->pad; i++) { + jtwrite(blk, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(blk, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + } + } +#endif /* APPLE_HYB || DVD_VIDEO */ + + + dwnext = dwpnt; + dwpnt = dwpnt->next; + free(dwnext); + dwnext = NULL; + } +}/* write_files(... */ + +#if 0 +static void +dump_filelist() +{ + struct deferred_write *dwpnt; + + dwpnt = dw_head; + while (dwpnt) { + fprintf(stderr, "File %s\n", dwpnt->name); + dwpnt = dwpnt->next; + } + fprintf(stderr, "\n"); +} + +#endif + +static int +compare_dirs(const void *rr, const void *ll) +{ + char *rpnt, + *lpnt; + struct directory_entry **r, + **l; + + r = (struct directory_entry **) rr; + l = (struct directory_entry **) ll; + rpnt = (*r)->isorec.name; + lpnt = (*l)->isorec.name; + +#ifdef APPLE_HYB + /* + * resource fork MUST (not sure if this is true for HFS volumes) be + * before the data fork - so force it here + */ + if ((*r)->assoc && (*r)->assoc == (*l)) + return (1); + if ((*l)->assoc && (*l)->assoc == (*r)) + return (-1); +#endif /* APPLE_HYB */ + + /* If the entries are the same, this is an error. */ + if (strcmp(rpnt, lpnt) == 0) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Error: '%s' and '%s' have the same ISO9660 name '%s'.\n", + (*r)->whole_name, (*l)->whole_name, + rpnt); +#else + fprintf(stderr, + "Error: '%s' and '%s' have the same ISO9660 name '%s'.\n", + (*r)->whole_name, (*l)->whole_name, + rpnt); +#endif + sort_goof++; + } + /* Check we don't have the same RR name */ + if (use_RockRidge && !is_rr_dir) { + /* + * entries *can* have the same RR name in the "rr_moved" + * directory so skip checks if we're in reloc_dir + */ + if (!(strcmp((*r)->name, (*l)->name))) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Error: '%s' and '%s' have the same Rock Ridge name '%s'.\n", + (*r)->whole_name, (*l)->whole_name, + (*r)->name); +#else + fprintf(stderr, + "Error: '%s' and '%s' have the same Rock Ridge name '%s'.\n", + (*r)->whole_name, (*l)->whole_name, + (*r)->name); +#endif + sort_goof++; + } + } + /* + * Put the '.' and '..' entries on the head of the sorted list. For + * normal ASCII, this always happens to be the case, but out of band + * characters cause this not to be the case sometimes. + * FIXME(eric) - these tests seem redundant, in that the name is never + * assigned these values. It will instead be \000 or \001, and thus + * should always be sorted correctly. I need to figure out why I + * thought I needed this in the first place. + */ +#if 0 + if (strcmp(rpnt, ".") == 0) + return (-1); + if (strcmp(lpnt, ".") == 0) + return (1); + + if (strcmp(rpnt, "..") == 0) + return (-1); + if (strcmp(lpnt, "..") == 0) + return (1); +#else + /* + * The code above is wrong (as explained in Eric's comment), leading to + * incorrect sort order iff the -L option ("allow leading dots") is in + * effect and a directory contains entries that start with a dot. + * (TF, Tue Dec 29 13:49:24 CET 1998) + */ + if ((*r)->isorec.name_len[0] == 1 && *rpnt == 0) + return (-1); /* '.' */ + if ((*l)->isorec.name_len[0] == 1 && *lpnt == 0) + return (1); + + if ((*r)->isorec.name_len[0] == 1 && *rpnt == 1) + return (-1); /* '..' */ + if ((*l)->isorec.name_len[0] == 1 && *lpnt == 1) + return (1); +#endif + + while (*rpnt && *lpnt) { + if (*rpnt == ';' && *lpnt != ';') + return (-1); + if (*rpnt != ';' && *lpnt == ';') + return (1); + + if (*rpnt == ';' && *lpnt == ';') + return (0); + + if (*rpnt == '.' && *lpnt != '.') + return (-1); + if (*rpnt != '.' && *lpnt == '.') + return (1); + + if ((unsigned char) *rpnt < (unsigned char) *lpnt) + return (-1); + if ((unsigned char) *rpnt > (unsigned char) *lpnt) + return (1); + rpnt++; + lpnt++; + } + if (*rpnt) + return (1); + if (*lpnt) + return (-1); + return (0); +} + +/* + * Function: sort_directory + * + * Purpose: Sort the directory in the appropriate ISO9660 + * order. + * + * Notes: Returns 0 if OK, returns > 0 if an error occurred. + */ +int +sort_directory(struct directory_entry **sort_dir, int rr) +{ + int dcount = 0; + int xcount = 0; + int j; + int i, + len; + struct directory_entry *s_entry; + struct directory_entry **sortlist; + + /* need to keep a count of how many entries are hidden */ + s_entry = *sort_dir; + while (s_entry) { + if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) + xcount++; + dcount++; + s_entry = s_entry->next; + } + + if (dcount == 0) { + return (0); + } + /* OK, now we know how many there are. Build a vector for sorting. */ + sortlist = (struct directory_entry **) + e_malloc(sizeof (struct directory_entry *) * dcount); + + j = dcount - 1; + dcount = 0; + s_entry = *sort_dir; + while (s_entry) { + if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { + /* put any hidden entries at the end of the vector */ + sortlist[j--] = s_entry; + } else { + sortlist[dcount] = s_entry; + dcount++; + } + len = s_entry->isorec.name_len[0]; + s_entry->isorec.name[len] = 0; + s_entry = s_entry->next; + } + + /* Each directory is required to contain at least . and .. */ + if (dcount < 2) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Directory size too small (. or .. missing ??%s)\n", + "?"); /* Try to avoid a GCC trigraph warning */ +#else + fprintf(stderr, + "Directory size too small (. or .. missing ??%s)\n", + "?"); /* Try to avoid a GCC trigraph warning */ +#endif + sort_goof = 1; + + } else { + /* only sort the non-hidden entries */ + sort_goof = 0; + is_rr_dir = rr; +#ifdef PROTOTYPES + qsort(sortlist, dcount, sizeof (struct directory_entry *), + (int (*) (const void *, const void *)) compare_dirs); +#else + qsort(sortlist, dcount, sizeof (struct directory_entry *), + compare_dirs); +#endif + + /* + * Now reassemble the linked list in the proper sorted order + * We still need the hidden entries, as they may be used in + * the Joliet tree. + */ + for (i = 0; i < dcount + xcount - 1; i++) { + sortlist[i]->next = sortlist[i + 1]; + } + + sortlist[dcount + xcount - 1]->next = NULL; + *sort_dir = sortlist[0]; + } + + free(sortlist); + sortlist = NULL; + return (sort_goof); +} + +static int +root_gen() +{ + init_fstatbuf(); + + root_record.length[0] = 1 + + offsetof(struct iso_directory_record, name[0]); + root_record.ext_attr_length[0] = 0; + set_733((char *) root_record.extent, root->extent); + set_733((char *) root_record.size, ISO_ROUND_UP(root->size)); + iso9660_date(root_record.date, root_statbuf.st_mtime); + root_record.flags[0] = ISO_DIRECTORY; + root_record.file_unit_size[0] = 0; + root_record.interleave[0] = 0; + set_723(root_record.volume_sequence_number, volume_sequence_number); + root_record.name_len[0] = 1; + return (0); +} + +#ifdef SORTING +/* + * sorts deferred_write entries based on the sort weight + */ +static int +compare_sort(const void *rr, const void *ll) +{ + struct deferred_write **r; + struct deferred_write **l; + int r_sort; + int l_sort; + + r = (struct deferred_write **) rr; + l = (struct deferred_write **) ll; + r_sort = (*r)->s_entry->sort; + l_sort = (*l)->s_entry->sort; + + if (r_sort != l_sort) + return (r_sort < l_sort ? 1 : -1); + else + return ((*r)->extent - (*l)->extent); +} + +/* + * reassign start extents to files that are "hard links" to + * files that may have been sorted + */ +static void +reassign_link_addresses(struct directory *dpnt) +{ + struct directory_entry *s_entry; + struct file_hash *s_hash; + + while (dpnt) { + s_entry = dpnt->contents; + for (s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) { + /* link files have already been given the weight NOT_SORTED */ + if (s_entry->sort == NOT_SORTED) + { + /* update the start extent */ + s_hash = find_hash(s_entry->dev, s_entry->inode); + if (s_hash) { + set_733((char *) s_entry->isorec.extent, + s_hash->starting_block); + s_entry->starting_block = s_hash->starting_block; + } + } + + if (verbose > 2 && s_entry->size != 0) { + fprintf(stderr, "%8u %8u ", + s_entry->starting_block, + (unsigned int)(s_entry->starting_block + ISO_BLOCKS(s_entry->size) - 1)); + + if (s_entry->inode != TABLE_INODE) { + fprintf(stderr, "%s\n", s_entry->whole_name); + } else { + fprintf(stderr, "%s%s%s\n", + s_entry->filedir->whole_name, + SPATH_SEPARATOR, trans_tbl); + } + } + } + if (dpnt->subdir) { + reassign_link_addresses(dpnt->subdir); + } + + dpnt = dpnt->next; + } +} + +/* + * sort files in order of the given sort weight + */ +static int +sort_file_addresses() +{ + struct deferred_write *dwpnt; + struct deferred_write **sortlist; + struct directory_entry *s_entry; + int start_extent; + int num = 0; + int i; + + /* need to store start extents for linked files */ + flush_hash(); + + /* find out how many files we have */ + dwpnt = dw_head; + while (dwpnt) { + num++; + dwpnt = dwpnt->next; + } + + /* return if we have none */ + if (num == 0) { + return (1); + } + + /* save the start extent of the first file */ + start_extent = dw_head->extent; + + /* set up vector to store entries */ + sortlist = (struct deferred_write **) + e_malloc(sizeof (struct deferred_write *) * num); + + for (i = 0, dwpnt = dw_head; i < num; i++, dwpnt = dwpnt->next) + sortlist[i] = dwpnt; + + /* sort the list */ +#ifdef PROTOTYPES + qsort(sortlist, num, sizeof (struct deferred_write *), + (int (*)(const void *, const void *))compare_sort); +#else + qsort(sortlist, num, sizeof (struct deferred_write *), compare_sort); +#endif + + /* reconstruct the linked list */ + for (i = 0; i < num-1; i++) { + sortlist[i]->next = sortlist[i+1]; + } + + sortlist[num-1]->next = NULL; + dw_head = sortlist[0]; + + free(sortlist); + + /* set the new start extents for the sorted list */ + for (i = 0, dwpnt = dw_head; i < num; i++, dwpnt = dwpnt->next) { + s_entry = dwpnt->s_entry; + dwpnt->extent = s_entry->starting_block = start_extent; + set_733((char *) s_entry->isorec.extent, start_extent); + + start_extent += ISO_BLOCKS(s_entry->size); +#ifdef DVD_VIDEO + /* + * Shouldn't this be done for every type of sort? Otherwise + * we will loose every pad info we add if we sort the files + */ + if (dvd_video) { + start_extent += dwpnt->pad; + } +#endif /* DVD_VIDEO */ + + /* cache start extents for any linked files */ + add_hash(s_entry); + } + + return (0); +} +#endif /* SORTING */ + + + +static BOOL +assign_file_addresses(struct directory *dpnt, BOOL isnest) +{ + struct directory *finddir; + struct directory_entry *s_entry; + struct file_hash *s_hash; + struct deferred_write *dwpnt; + char whole_path[PATH_MAX]; +#ifdef DVD_VIDEO + char dvd_path[PATH_MAX]; + title_set_info_t * title_set_info = NULL; + char *p; +#endif + BOOL ret = FALSE; + + while (dpnt) { +#ifdef DVD_VIDEO + if (dvd_video && root == dpnt->parent && + ((p = strstr(dpnt->whole_name, "VIDEO_TS")) != 0)&& + strcmp(p, "VIDEO_TS") == 0) { + + int maxlen = strlen(dpnt->whole_name)-8; + if (maxlen > (sizeof (dvd_path)-1)) + maxlen = sizeof (dvd_path)-1; + strncpy(dvd_path, dpnt->whole_name, maxlen); + dvd_path[maxlen] = '\0'; + +#ifdef DEBUG + fprintf(stderr, "Found 'VIDEO_TS', the path is %s \n", dvd_path); +#endif + title_set_info = DVDGetFileSet(dvd_path); + if (title_set_info == 0) { + /* + * Do not switch off -dvd-video but let is fail later. + */ +/* dvd_video = 0;*/ + errmsgno(EX_BAD, "Unable to parse DVD-Video structures.\n"); + } else { + ret = TRUE; + } + } +#endif /* DVD_VIDEO */ + + s_entry = dpnt->contents; + for (s_entry = dpnt->contents; s_entry; + s_entry = s_entry->next) { + /* + * If we already have an extent for this entry, then + * don't assign a new one. It must have come from a + * previous session on the disc. Note that we don't + * end up scheduling the thing for writing either. + */ + if (get_733(s_entry->isorec.extent) != 0) { + continue; + } + /* + * This saves some space if there are symlinks present + */ + s_hash = find_hash(s_entry->dev, s_entry->inode); + if (s_hash) { + if (verbose > 2) { + fprintf(stderr, "Cache hit for '%s%s%s'\n", s_entry->filedir->de_name, + SPATH_SEPARATOR, + s_entry->name); + } + set_733((char *) s_entry->isorec.extent, + s_hash->starting_block); + set_733((char *) s_entry->isorec.size, + s_hash->size); +#ifdef SORTING + /* check for non-directory files */ + if (do_sort && ((s_entry->isorec.flags[0] & ISO_DIRECTORY) == 0)) { + /* make sure the real file has the highest weighting */ + s_hash->de->sort = MAX(s_entry->sort, s_hash->de->sort); + /* flag this as a potential non-sorted file */ + s_entry->sort = NOT_SORTED; + } +#endif /* SORTING */ + continue; + } + /* + * If this is for a directory that is not a . or + * a .. entry, then look up the information for the + * entry. We have already assigned extents for + * directories, so we just need to fill in the blanks + * here. + */ + if (strcmp(s_entry->name, ".") != 0 && + strcmp(s_entry->name, "..") != 0 && + s_entry->isorec.flags[0] & ISO_DIRECTORY) { + finddir = dpnt->subdir; + while (1 == 1) { + if (finddir->self == s_entry) + break; + finddir = finddir->next; + if (!finddir) { +#ifdef DVD_VIDEO + if (title_set_info != 0) { + DVDFreeFileSet(title_set_info); + } +#endif + comerrno(EX_BAD, + "Fatal goof - could not find dir entry for '%s'\n", + s_entry->name); + } + } + set_733((char *) s_entry->isorec.extent, + finddir->extent); + s_entry->starting_block = finddir->extent; + s_entry->size = ISO_ROUND_UP(finddir->size); + total_dir_size += s_entry->size; + add_hash(s_entry); + set_733((char *) s_entry->isorec.size, + ISO_ROUND_UP(finddir->size)); + continue; + } + /* + * If this is . or .., then look up the relevant info + * from the tables. + */ + if (strcmp(s_entry->name, ".") == 0) { + set_733((char *) s_entry->isorec.extent, + dpnt->extent); + + /* + * Set these so that the hash table has the + * correct information + */ + s_entry->starting_block = dpnt->extent; + s_entry->size = ISO_ROUND_UP(dpnt->size); + + add_hash(s_entry); + s_entry->starting_block = dpnt->extent; + set_733((char *) s_entry->isorec.size, + ISO_ROUND_UP(dpnt->size)); + continue; + } + if (strcmp(s_entry->name, "..") == 0) { + if (dpnt == root) { + total_dir_size += root->size; + } + set_733((char *) s_entry->isorec.extent, + dpnt->parent->extent); + + /* + * Set these so that the hash table has the + * correct information + */ + s_entry->starting_block = dpnt->parent->extent; + s_entry->size = + ISO_ROUND_UP(dpnt->parent->size); + + add_hash(s_entry); + s_entry->starting_block = dpnt->parent->extent; + set_733((char *) s_entry->isorec.size, + ISO_ROUND_UP(dpnt->parent->size)); + continue; + } + /* + * Some ordinary non-directory file. Just schedule + * the file to be written. This is all quite + * straightforward, just make a list and assign + * extents as we go. Once we get through writing all + * of the directories, we should be ready write out + * these files + */ + if (s_entry->size) { + dwpnt = (struct deferred_write *) + e_malloc(sizeof (struct deferred_write)); + /* save this directory entry for later use */ + dwpnt->s_entry = s_entry; + /* set the initial padding to zero */ + dwpnt->pad = 0; +#ifdef DVD_VIDEO + if (dvd_video && (title_set_info != 0)) { + int pad; + + pad = DVDGetFilePad(title_set_info, s_entry->name); + if (pad < 0) { + errmsgno(EX_BAD, + "Implementation botch. Video pad for file %s is %d\n", + s_entry->name, pad), + comerrno(EX_BAD, + "Either the *.IFO file is bad or you found a genisoimage bug.\n"); + } + dwpnt->pad = pad; + if (verbose > 0 && pad != 0) { + fprintf(stderr, + "The pad was %d for file %s\n", dwpnt->pad, s_entry->name); + } + } +#endif /* DVD_VIDEO */ +#ifdef APPLE_HYB + /* + * maybe an offset to start of the real + * file/fork + */ + dwpnt->off = s_entry->hfs_off; +#else + dwpnt->off = (off_t)0; +#endif /* APPLE_HYB */ + if (dw_tail) { + dw_tail->next = dwpnt; + dw_tail = dwpnt; + } else { + dw_head = dwpnt; + dw_tail = dwpnt; + } + if (s_entry->inode == TABLE_INODE) { + dwpnt->table = s_entry->table; + dwpnt->name = NULL; + sprintf(whole_path, "%s%s%s", + s_entry->filedir->whole_name, + SPATH_SEPARATOR, trans_tbl); + } else { + dwpnt->table = NULL; + strcpy(whole_path, s_entry->whole_name); + dwpnt->name = strdup(whole_path); + } + dwpnt->next = NULL; + dwpnt->size = s_entry->size; + dwpnt->extent = last_extent; + set_733((char *) s_entry->isorec.extent, + last_extent); + s_entry->starting_block = last_extent; + add_hash(s_entry); + last_extent += ISO_BLOCKS(s_entry->size); +#ifdef DVD_VIDEO + /* Shouldn't we always add the pad info? */ + if (dvd_video) { + last_extent += dwpnt->pad; + } +#endif /* DVD_VIDEO */ + if (verbose > 2 && !do_sort) { + fprintf(stderr, "%8d %8u %s\n", + s_entry->starting_block, + last_extent - 1, whole_path); + } +#ifdef DBG_ISO + if (ISO_BLOCKS(s_entry->size) > 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 %lld\n", + (Llong)s_entry->size); + + } +#endif +#ifdef NOT_NEEDED /* Never use this code if you like to create a DVD */ + + if (last_extent > (800000000 >> 11)) { + /* More than 800Mb? Punt */ + fprintf(stderr, + "Extent overflow processing file '%s'\n", + whole_path); + fprintf(stderr, + "Starting block is %d\n", + s_entry->starting_block); + fprintf(stderr, + "Reported file size is %lld\n", + (Llong)s_entry->size); + exit(1); + } +#endif + continue; + } + /* + * This is for zero-length files. If we leave the + * extent 0, then we get screwed, because many readers + * simply drop files that have an extent of zero. + * Thus we leave the size 0, and just assign the + * extent number. + */ + set_733((char *) s_entry->isorec.extent, last_extent); + } + if (dpnt->subdir) { + if (assign_file_addresses(dpnt->subdir, TRUE)) + ret = TRUE; + } + dpnt = dpnt->next; + } +#ifdef DVD_VIDEO + if (title_set_info != NULL) { + DVDFreeFileSet(title_set_info); + } + if (dvd_video && !ret && !isnest) { + errmsgno(EX_BAD, + "Could not find correct 'VIDEO_TS' directory.\n"); + } +#endif /* DVD_VIDEO */ + return (ret); +} /* assign_file_addresses(... */ + +static void +free_one_directory(struct directory *dpnt) +{ + struct directory_entry *s_entry; + struct directory_entry *s_entry_d; + + s_entry = dpnt->contents; + while (s_entry) { + s_entry_d = s_entry; + s_entry = s_entry->next; + + if (s_entry_d->rr_attributes) { + free(s_entry_d->rr_attributes); + s_entry_d->rr_attributes = NULL; + } + if (s_entry_d->name != NULL) { + free(s_entry_d->name); + s_entry_d->name = NULL; + } + if (s_entry_d->whole_name != NULL) { + free(s_entry_d->whole_name); + s_entry_d->whole_name = NULL; + } +#ifdef APPLE_HYB + if (apple_both && s_entry_d->hfs_ent && !s_entry_d->assoc) + free(s_entry_d->hfs_ent); +#endif /* APPLE_HYB */ + + free(s_entry_d); + s_entry_d = NULL; + } + dpnt->contents = NULL; +}/* free_one_directory(... */ + +static void +free_directories(struct directory *dpnt) +{ + while (dpnt) { + free_one_directory(dpnt); + if (dpnt->subdir) + free_directories(dpnt->subdir); + dpnt = dpnt->next; + } +} + +void +generate_one_directory(struct directory *dpnt, FILE *outfile) +{ + unsigned int ce_address = 0; + char *ce_buffer; + unsigned int ce_index = 0; + unsigned int ce_size; + unsigned int dir_index; + char *directory_buffer; + int new_reclen; + struct directory_entry *s_entry; + struct directory_entry *s_entry_d; + unsigned int total_size; + + total_size = ISO_ROUND_UP(dpnt->size); + directory_buffer = (char *) e_malloc(total_size); + memset(directory_buffer, 0, total_size); + dir_index = 0; + + ce_size = ISO_ROUND_UP(dpnt->ce_bytes); + ce_buffer = NULL; + + if (ce_size > 0) { + 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) { + /* skip if it's hidden */ + if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { + s_entry = s_entry->next; + continue; + } + /* + * 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 = ISO_ROUND_UP(dir_index); + } + memcpy(directory_buffer + dir_index, &s_entry->isorec, + offsetof(struct iso_directory_record, name[0]) + + s_entry->isorec.name_len[0]); + dir_index += offsetof(struct iso_directory_record, name[0]) + + 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) { + struct iso_xa_dir_record *xadp; + unsigned char *pnt; + int len, + nbytes; + + /* + * Go through the entire record, first skip + * the XA record and then 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; + + if (len >= 14) { + xadp = (struct iso_xa_dir_record *)pnt; + + if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' && + xadp->reserved[0] == '\0') { + len -= 14; + pnt += 14; + } + } + + while (len > 3) { +#ifdef DEBUG + if (ce_size <= 0) { + fprintf(stderr, + "Warning: ce_index(%d) && ce_address(%d) not initialized\n", + ce_index, ce_address); + } +#endif + + if (pnt[0] == 'C' && pnt[1] == 'E') { + nbytes = get_733((char *) pnt + 20); + + if ((ce_index & (SECTOR_SIZE - 1)) + nbytes >= + SECTOR_SIZE) { + ce_index = ISO_ROUND_UP(ce_index); + } + set_733((char *) pnt + 4, + (ce_address + ce_index) >> 11); + set_733((char *) pnt + 12, + (ce_address + ce_index) & (SECTOR_SIZE - 1)); + + + /* + * Now store the block in the + * ce buffer + */ + memcpy(ce_buffer + ce_index, + pnt + pnt[2], nbytes); + ce_index += nbytes; + if (ce_index & 1) { + ce_index++; + } + } + len -= pnt[2]; + pnt += pnt[2]; + } + + } + rockridge_size += s_entry->total_rr_attr_size; + memcpy(directory_buffer + dir_index, + s_entry->rr_attributes, + s_entry->rr_attr_size); + dir_index += s_entry->rr_attr_size; + } + if (dir_index & 1) { + directory_buffer[dir_index++] = 0; + } + s_entry_d = s_entry; + s_entry = s_entry->next; + + /* + * Joliet doesn't use the Rock Ridge attributes, so we free + * it here. + */ + if (s_entry_d->rr_attributes) { + free(s_entry_d->rr_attributes); + s_entry_d->rr_attributes = NULL; + } + } + + if (dpnt->size != dir_index) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Unexpected directory length %lld expected: %d '%s'\n", + (Llong)dpnt->size, + dir_index, dpnt->de_name); +#else + fprintf(stderr, + "Unexpected directory length %lld expected: %d '%s'\n", + (Llong)dpnt->size, + dir_index, dpnt->de_name); +#endif + } + jtwrite(directory_buffer, total_size, 1, 0, FALSE); + xfwrite(directory_buffer, total_size, 1, outfile, 0, FALSE); + last_extent_written += total_size >> 11; + free(directory_buffer); + directory_buffer = NULL; + + if (ce_size > 0) { + if (ce_index != dpnt->ce_bytes) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Continuation entry record length mismatch %d expected: %d.\n", + ce_index, dpnt->ce_bytes); +#else + fprintf(stderr, + "Continuation entry record length mismatch %d expected: %d.\n", + ce_index, dpnt->ce_bytes); +#endif + } + jtwrite(ce_buffer, ce_size, 1, 0, FALSE); + xfwrite(ce_buffer, ce_size, 1, outfile, 0, FALSE); + last_extent_written += ce_size >> 11; + free(ce_buffer); + ce_buffer = NULL; + } +}/* generate_one_directory(... */ + +static void +build_pathlist(struct directory *node) +{ + struct directory *dpnt; + + dpnt = node; + + while (dpnt) { + /* skip if it's hidden */ + if ((dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0) + pathlist[dpnt->path_index] = dpnt; + + if (dpnt->subdir) + build_pathlist(dpnt->subdir); + dpnt = dpnt->next; + } +}/* build_pathlist(... */ + +static int +compare_paths(void const *r, void const *l) +{ + struct directory const *ll = *(struct directory * const *) l; + struct directory const *rr = *(struct directory * const *) r; + + if (rr->parent->path_index < ll->parent->path_index) { + return (-1); + } + if (rr->parent->path_index > ll->parent->path_index) { + return (1); + } + return (strcmp(rr->self->isorec.name, ll->self->isorec.name)); + +}/* compare_paths(... */ + +static int +generate_path_tables() +{ + struct directory_entry *de = NULL; + struct directory *dpnt; + int fix; + int i; + int j; + int namelen; + char *npnt; + char *npnt1; + int tablesize; + + /* First allocate memory for the tables and initialize the memory */ + tablesize = path_blocks << 11; + path_table_m = (char *) e_malloc(tablesize); + path_table_l = (char *) e_malloc(tablesize); + memset(path_table_l, 0, tablesize); + memset(path_table_m, 0, tablesize); + + /* + * Now start filling in the path tables. Start with root directory + */ + + path_table_index = 0; + pathlist = (struct directory **) e_malloc(sizeof (struct directory *) + * next_path_index); + memset(pathlist, 0, sizeof (struct directory *) * next_path_index); + build_pathlist(root); + + do { + fix = 0; +#ifdef PROTOTYPES + qsort(&pathlist[1], next_path_index - 1, + sizeof (struct directory *), + (int (*) (const void *, const void *)) compare_paths); +#else + qsort(&pathlist[1], next_path_index - 1, + sizeof (struct directory *), + compare_paths); +#endif + + for (j = 1; j < next_path_index; j++) { + if (pathlist[j]->path_index != j) { + pathlist[j]->path_index = j; + fix++; + } + } + } while (fix); + + for (j = 1; j < next_path_index; j++) { + dpnt = pathlist[j]; + if (!dpnt) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, "Entry %d not in path tables\n", j); +#else + fprintf(stderr, "Entry %d not in path tables\n", j); + exit(1); +#endif + } + npnt = dpnt->de_name; + + /* So the root comes out OK */ + if ((*npnt == 0) || (dpnt == root)) { + npnt = "."; + } + npnt1 = strrchr(npnt, PATH_SEPARATOR); + if (npnt1) { + npnt = npnt1 + 1; + } + de = dpnt->self; + if (!de) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Fatal ISO9660 goof - directory has amnesia\n"); +#else + fprintf(stderr, + "Fatal ISO9660 goof - directory has amnesia\n"); + exit(1); +#endif + } + 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; + + if (dpnt->parent->path_index > 0xffff) { +#ifdef USE_LIBSCHILY + comerrno(EX_BAD, + "Unable to generate sane path tables - too many directories (%d)\n", + dpnt->parent->path_index); +#else + fprintf(stderr, + "Unable to generate sane path tables - too many directories (%d)\n", + dpnt->parent->path_index); + exit(1); +#endif + } + + set_721(path_table_l + path_table_index, + dpnt->parent->path_index); + set_722(path_table_m + path_table_index, + dpnt->parent->path_index); + path_table_index += 2; + + for (i = 0; i < namelen; i++) { + path_table_l[path_table_index] = de->isorec.name[i]; + path_table_m[path_table_index] = de->isorec.name[i]; + path_table_index++; + } + if (path_table_index & 1) { + path_table_index++; /* For odd lengths we pad */ + } + } + + free(pathlist); + pathlist = NULL; + if (path_table_index != path_table_size) { +#ifdef USE_LIBSCHILY + errmsgno(EX_BAD, + "Path table lengths do not match %d expected: %d\n", + path_table_index, + path_table_size); +#else + fprintf(stderr, + "Path table lengths do not match %d expected: %d\n", + path_table_index, + path_table_size); +#endif + } + return (0); +}/* generate_path_tables(... */ + +void +memcpy_max(char *to, char *from, int max) +{ + int n = strlen(from); + + if (n > max) { + n = max; + } + memcpy(to, from, n); + +}/* memcpy_max(... */ + +void +outputlist_insert(struct output_fragment *frag) +{ + struct output_fragment *nfrag; + + nfrag = e_malloc(sizeof (*frag)); + movebytes(frag, nfrag, sizeof (*frag)); + nfrag->of_start_extent = 0; + + if (out_tail == NULL) { + out_list = out_tail = nfrag; + } else { + out_tail->of_next = nfrag; + out_tail = nfrag; + } +} + +static int +file_write(FILE *outfile) +{ + Uint should_write; + +#ifdef APPLE_HYB + char buffer[SECTOR_SIZE]; + + memset(buffer, 0, sizeof (buffer)); + + if (apple_hyb) { + + int i; + + /* + * write out padding to round up to HFS allocation block + */ + for (i = 0; i < hfs_pad; i++) { + jtwrite(buffer, sizeof (buffer), 1, 0, FALSE); + xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE); + last_extent_written++; + } + } +#endif /* APPLE_HYB */ + + /* + * 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. + */ + should_write = last_extent - session_start; + + if (verbose > 2) { +#ifdef DBG_ISO + fprintf(stderr, + "Total directory extents being written = %d\n", + last_extent); +#endif + +#ifdef APPLE_HYB + if (apple_hyb) + fprintf(stderr, + "Total extents scheduled to be written (inc HFS) = %d\n", + last_extent - session_start); + else +#endif /* APPLE_HYB */ + + fprintf(stderr, + "Total extents scheduled to be written = %u\n", + last_extent - session_start); + } + /* Now write all of the files that we need. */ + write_files(outfile); + +#ifdef APPLE_HYB + /* write out extents/catalog/dt file */ + if (apple_hyb) { + + jtwrite(hce->hfs_ce, HFS_BLOCKSZ, hce->hfs_tot_size, 0, FALSE); + xfwrite(hce->hfs_ce, HFS_BLOCKSZ, hce->hfs_tot_size, outfile, 0, FALSE); + + /* round up to a whole CD block */ + if (HFS_ROUND_UP(hce->hfs_tot_size) - + hce->hfs_tot_size * HFS_BLOCKSZ) { + jtwrite(buffer, + HFS_ROUND_UP(hce->hfs_tot_size) - + hce->hfs_tot_size * HFS_BLOCKSZ, 1, 0, FALSE); + xfwrite(buffer, + HFS_ROUND_UP(hce->hfs_tot_size) - + hce->hfs_tot_size * HFS_BLOCKSZ, 1, outfile, 0, FALSE); + } + last_extent_written += ISO_ROUND_UP(hce->hfs_tot_size * + HFS_BLOCKSZ) / SECTOR_SIZE; + + /* write out HFS boot block */ + if (mac_boot.name) + write_one_file(mac_boot.name, mac_boot.size, outfile, + mac_boot.off); + } +#endif /* APPLE_HYB */ + + /* The rest is just fluff. */ + if (verbose == 0) { + return (0); + } +#ifdef APPLE_HYB + if (apple_hyb) { + fprintf(stderr, + "Total extents actually written (inc HFS) = %d\n", + last_extent_written - session_start); + fprintf(stderr, "(Size of ISO volume = %d, HFS extra = %d)\n", + last_extent_written - session_start - hfs_extra, + hfs_extra); + } else +#else + fprintf(stderr, "Total extents actually written = %d\n", + last_extent_written - session_start); +#endif /* APPLE_HYB */ + + /* Hard links throw us off here */ + if (should_write != (last_extent - session_start)) { + fprintf(stderr, + "Number of extents written not what was predicted. Please fix.\n"); + fprintf(stderr, "Predicted = %d, written = %d\n", + should_write, last_extent); + } + fprintf(stderr, "Total translation table size: %d\n", table_size); + fprintf(stderr, "Total rockridge attributes bytes: %d\n", + rockridge_size); + fprintf(stderr, "Total directory bytes: %d\n", total_dir_size); + fprintf(stderr, "Path table size(bytes): %d\n", path_table_size); + +#ifdef DEBUG + fprintf(stderr, + "next extent, last_extent, last_extent_written %d %d %d\n", + next_extent, last_extent, last_extent_written); +#endif + + return (0); + +}/* iso_write(... */ + +/* + * Function to write the PVD for the disc. + */ +static int +pvd_write(FILE *outfile) +{ + char iso_time[17]; + int should_write; + struct tm local; + struct tm gmt; + + + time(&begun); + + local = *localtime(&begun); + gmt = *gmtime(&begun); + + /* + * There was a comment here about breaking in the year 2000. + * That's not true, in 2000 tm_year == 100, so 1900+tm_year == 2000. + */ + sprintf(iso_time, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00", + 1900 + local.tm_year, + local.tm_mon + 1, local.tm_mday, + local.tm_hour, local.tm_min, local.tm_sec); + + local.tm_min -= gmt.tm_min; + local.tm_hour -= gmt.tm_hour; + local.tm_yday -= gmt.tm_yday; + if (local.tm_yday < -2) /* Hit new-year limit */ + local.tm_yday = 1; /* Local is GMT + 1 day */ + iso_time[16] = (local.tm_min + 60 * + (local.tm_hour + 24 * local.tm_yday)) / 15; + + /* Next we write out the primary descriptor for the disc */ + memset(&vol_desc, 0, sizeof (vol_desc)); + vol_desc.type[0] = ISO_VD_PRIMARY; + memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof (ISO_STANDARD_ID)); + vol_desc.version[0] = 1; + + memset(vol_desc.system_id, ' ', sizeof (vol_desc.system_id)); + memcpy_max(vol_desc.system_id, system_id, strlen(system_id)); + + memset(vol_desc.volume_id, ' ', sizeof (vol_desc.volume_id)); + memcpy_max(vol_desc.volume_id, volume_id, strlen(volume_id)); + + should_write = last_extent - session_start; + set_733((char *) vol_desc.volume_space_size, should_write); + set_723(vol_desc.volume_set_size, volume_set_size); + set_723(vol_desc.volume_sequence_number, volume_sequence_number); + set_723(vol_desc.logical_block_size, SECTOR_SIZE); + + /* + * The path tables are used by DOS based machines to cache directory + * locations + */ + set_733((char *) vol_desc.path_table_size, path_table_size); + set_731(vol_desc.type_l_path_table, path_table[0]); + set_731(vol_desc.opt_type_l_path_table, path_table[1]); + set_732(vol_desc.type_m_path_table, path_table[2]); + set_732(vol_desc.opt_type_m_path_table, path_table[3]); + + /* Now we copy the actual root directory record */ + memcpy(vol_desc.root_directory_record, &root_record, + offsetof(struct iso_directory_record, name[0]) + 1); + + /* + * The rest is just fluff. It looks nice to fill in many of these + * fields, though. + */ + FILL_SPACE(volume_set_id); + if (volset_id) + memcpy_max(vol_desc.volume_set_id, volset_id, strlen(volset_id)); + + FILL_SPACE(publisher_id); + if (publisher) + memcpy_max(vol_desc.publisher_id, publisher, strlen(publisher)); + + FILL_SPACE(preparer_id); + if (preparer) + memcpy_max(vol_desc.preparer_id, preparer, strlen(preparer)); + + FILL_SPACE(application_id); + if (appid) + memcpy_max(vol_desc.application_id, appid, strlen(appid)); + + FILL_SPACE(copyright_file_id); + if (copyright) + memcpy_max(vol_desc.copyright_file_id, copyright, + strlen(copyright)); + + FILL_SPACE(abstract_file_id); + if (abstract) + memcpy_max(vol_desc.abstract_file_id, abstract, + strlen(abstract)); + + FILL_SPACE(bibliographic_file_id); + if (biblio) + memcpy_max(vol_desc.bibliographic_file_id, biblio, + strlen(biblio)); + + FILL_SPACE(creation_date); + FILL_SPACE(modification_date); + FILL_SPACE(expiration_date); + FILL_SPACE(effective_date); + vol_desc.file_structure_version[0] = 1; + FILL_SPACE(application_data); + + memcpy(vol_desc.creation_date, iso_time, 17); + memcpy(vol_desc.modification_date, iso_time, 17); + memcpy(vol_desc.expiration_date, "0000000000000000", 17); + memcpy(vol_desc.effective_date, iso_time, 17); + + if (use_XA) { + char *xap = &((char *)&vol_desc)[1024]; + + memcpy(&xap[0], "CD-XA001", 8); /* XA Sign. */ + memcpy(&xap[8], "\0\0", 2); /* XA flags */ + memcpy(&xap[10], "\0\0\0\0\0\0\0\0", 8); /* Start dir */ + memcpy(&xap[18], "\0\0\0\0\0\0\0\0", 8); /* Reserved */ + } + + /* if not a bootable cd do it the old way */ + jtwrite(&vol_desc, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(&vol_desc, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + return (0); +} + +/* + * Function to write the Extended PVD for the disc. + */ +static int +xpvd_write(FILE *outfile) +{ + vol_desc.type[0] = ISO_VD_SUPPLEMENTARY; + vol_desc.version[0] = 2; + vol_desc.file_structure_version[0] = 2; + + /* if not a bootable cd do it the old way */ + jtwrite(&vol_desc, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(&vol_desc, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + return (0); +} + +/* + * Function to write the EVD for the disc. + */ +static int +evd_write(FILE *outfile) +{ + struct iso_primary_descriptor evol_desc; + + /* + * Now write the end volume descriptor. Much simpler than the other + * one + */ + memset(&evol_desc, 0, sizeof (evol_desc)); + evol_desc.type[0] = (unsigned char) ISO_VD_END; + memcpy(evol_desc.id, ISO_STANDARD_ID, sizeof (ISO_STANDARD_ID)); + evol_desc.version[0] = 1; + jtwrite(&evol_desc, SECTOR_SIZE, 1, 0, TRUE); + xfwrite(&evol_desc, SECTOR_SIZE, 1, outfile, 0, TRUE); + last_extent_written += 1; + return (0); +} + +/* + * Function to write the version information for the disc. + */ +static int +vers_write(FILE *outfile) +{ + char vers[SECTOR_SIZE+1]; + int X_ac; + char **X_av; + char *cp; + int i; + int idx = 4; + int len; + extern char version_string[]; + extern int path_ind; + + /* Now write the version descriptor. */ + memset(vers, 0, sizeof (vers)); + strcpy(vers, "MKI "); + + cp = vers; + X_ac = saved_ac(); + X_av = saved_av(); + strcpy(&cp[idx], ctime(&begun)); + idx += 25; + strcpy(&cp[idx], version_string); + idx += strlen(version_string); + for (i = 1; i < X_ac; i++) { + len = strlen(X_av[i]); + if ((idx + len + 2) >= SECTOR_SIZE) + break; + cp[idx++] = ' '; + /* + * Do not give away secret information when not in debug mode. + */ + if (debug) + strcpy(&cp[idx], X_av[i]); + else if (i >= path_ind) + len = graftcp(&cp[idx], X_av[i], &vers[SECTOR_SIZE-1]); + else if (X_av[i][0] == '/') + len = pathcp(&cp[idx], X_av[i], &vers[SECTOR_SIZE-1]); + else + strcpy(&cp[idx], X_av[i]); + idx += len; + } + + cp[SECTOR_SIZE - 1] = '\0'; + /* Per default: keep privacy. Blackout the version and arguments. */ + if(getenv("ISODEBUG")) { + jtwrite(vers, SECTOR_SIZE, 1, 0, TRUE); + xfwrite(vers, SECTOR_SIZE, 1, outfile, 0, TRUE); + } else { + jtwrite(calloc(SECTOR_SIZE, 1), SECTOR_SIZE, 1, 0, TRUE); + xfwrite(calloc(SECTOR_SIZE, 1), SECTOR_SIZE, 1, outfile, 0, TRUE); + } + last_extent_written += 1; + return (0); +} + +/* + * Avoid to write unwanted information into the version info string. + */ +static int +graftcp(char *to, char *from, char *ep) +{ + int len = strlen(from); + char *node = NULL; + + if (use_graft_ptrs) + node = findgequal(from); + + if (node == NULL) { + len = 0; + node = from; + } else { + len = node - from; + *node = '\0'; + strncpy(to, from, ep - to); + *node++ = '='; + to += len++; + *to++ = '='; + } + return (len + pathcp(to, node, ep)); +} + +static int +pathcp(char *to, char *from, char *ep) +{ + int len = strlen(from); + char *p; + + p = strrchr(from, '/'); + if (p == NULL) { + strncpy(to, from, ep - to); + } else { + if (p[1] == '\0') { + --p; + while (p > from && *p != '/') + --p; + } + len = 0; + if (*p == '/') { + strncpy(to, "...", ep - to); + to += 3; + len = 3; + } + if (to < ep) { + strncpy(to, p, ep - to); + len += strlen(to); + } + } + return (len); +} + + +/* + * Function to write the path table for the disc. + */ +static int +pathtab_write(FILE *outfile) +{ + /* Next we write the path tables */ + jtwrite(path_table_l, path_blocks << 11, 1, 0, FALSE); + xfwrite(path_table_l, path_blocks << 11, 1, outfile, 0, FALSE); + last_extent_written += path_blocks; + jtwrite(path_table_m, path_blocks << 11, 1, 0, FALSE); + xfwrite(path_table_m, path_blocks << 11, 1, outfile, 0, FALSE); + last_extent_written += path_blocks; + free(path_table_l); + free(path_table_m); + path_table_l = NULL; + path_table_m = NULL; + return (0); +} + +static int +exten_write(FILE *outfile) +{ + jtwrite(extension_record, SECTOR_SIZE, 1, 0, FALSE); + xfwrite(extension_record, SECTOR_SIZE, 1, outfile, 0, FALSE); + last_extent_written++; + return (0); +} + +/* + * Functions to describe padding block at the start of the disc. + */ +int +oneblock_size(int starting_extent) +{ + last_extent++; + return (0); +} + +/* + * Functions to describe path table size. + */ +static int +pathtab_size(int starting_extent) +{ + path_table[0] = starting_extent; + + path_table[1] = 0; + path_table[2] = path_table[0] + path_blocks; + path_table[3] = 0; + last_extent += 2 * path_blocks; + return (0); +} + +/* + * Functions to describe padding blocks before PVD. + */ +static int +startpad_size(int starting_extent) +{ + last_extent = session_start + 16; + return (0); +} + +/* + * Functions to describe padding blocks between sections. + */ +static int +interpad_size(int starting_extent) +{ + int emod = 0; + +#ifdef needed + starting_extent += 16; /* First add 16 pad blocks */ +#endif + if ((emod = starting_extent % 16) != 0) { + starting_extent += 16 - emod; /* Now pad to mod 16 # */ + } + last_extent = starting_extent; + return (0); +} + +/* + * Functions to describe padding blocks at end of disk. + */ +static int +endpad_size(int starting_extent) +{ + starting_extent += 150; /* 150 pad blocks (post gap) */ + last_extent = starting_extent; + return (0); +} + +static int +file_gen() +{ +#ifdef APPLE_HYB + int start_extent = last_extent; /* orig ISO files start */ + +#endif /* APPLE_HYB */ + + if (!assign_file_addresses(root, FALSE)) { +#ifdef DVD_VIDEO + if (dvd_video) { + comerrno(EX_BAD, "Unable to make a DVD-Video image.\n" + "Possible reasons:\n" + " - VIDEO_TS subdirectory was not found on specified location\n" + " - VIDEO_TS has invalid contents\n" + ); + } +#else + ; /* EMPTY */ +#endif + } + + +#ifdef SORTING + if (do_sort) { + if (sort_file_addresses() == 0) + reassign_link_addresses(root); + } +#endif /* SORTING */ + +#ifdef APPLE_HYB + /* + * put this here for the time being - may when I've worked out how to + * use Eric's new system for creating/writing parts of the image it + * may move to it's own routine + */ + if (apple_hyb) + hfs_file_gen(start_extent); +#ifdef PREP_BOOT + else if (use_prep_boot || use_chrp_boot) + gen_prepboot(); +#endif /* PREP_BOOT */ +#endif /* APPLE_HYB */ + + return (0); +} + +static int +dirtree_dump() +{ + if (verbose > 2) { + dump_tree(root); + } + return (0); +} + +static int +dirtree_fixup(int starting_extent) +{ + if (use_RockRidge && reloc_dir) + finish_cl_pl_entries(); + + if (use_RockRidge) + update_nlink_field(root); + return (0); +} + +static int +dirtree_size(int starting_extent) +{ + assign_directory_addresses(root); + return (0); +} + +static int +ext_size(int starting_extent) +{ + extern int extension_record_size; + struct directory_entry *s_entry; + + extension_record_extent = starting_extent; + s_entry = root->contents; + set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 24, + extension_record_extent); + set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 8, + extension_record_size); + last_extent++; + return (0); +} + +static int +dirtree_write(FILE *outfile) +{ + generate_iso9660_directories(root, outfile); + return (0); +} + +static int +dirtree_cleanup(FILE *outfile) +{ + free_directories(root); + return (0); +} + +static int +startpad_write(FILE *outfile) +{ + char buffer[SECTOR_SIZE]; + int i; + int npad; + + memset(buffer, 0, sizeof (buffer)); + + npad = session_start + 16 - last_extent_written; + + for (i = 0; i < npad; i++) { + jtwrite(buffer, sizeof (buffer), 1, 0, FALSE); + xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE); + last_extent_written++; + } + + return (0); +} + +static int +interpad_write(FILE *outfile) +{ + char buffer[SECTOR_SIZE]; + int i; + int npad = 0; + + memset(buffer, 0, sizeof (buffer)); + +#ifdef needed + npad = 16; +#endif + if ((i = last_extent_written % 16) != 0) + npad += 16 - i; + + for (i = 0; i < npad; i++) { + jtwrite(buffer, sizeof (buffer), 1, 0, FALSE); + xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE); + last_extent_written++; + } + + return (0); +} + +static int +endpad_write(FILE *outfile) +{ + char buffer[SECTOR_SIZE]; + int i; + + memset(buffer, 0, sizeof (buffer)); + + for (i = 0; i < 150; i++) { + jtwrite(buffer, sizeof (buffer), 1, 0, FALSE); + xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE); + last_extent_written++; + } + + return (0); +} + +#ifdef APPLE_HYB + +/* + * hfs_get_parms: get HFS parameters from the command line + */ + +static int +hfs_get_parms(char *key) +{ + int ret = 0; + char *p; + + if (hfs_parms == NULL) + return (ret); + + if ((p = strstr(hfs_parms, key)) != NULL) { + p += strlen(key) + 1; + sscanf(p, "%d", &ret); + } + + return (ret); +} + +/* + * hfs_file_gen: set up "fake" HFS volume using the ISO9660 tree + */ +static void +hfs_file_gen(int start_extent) +{ + int Csize; /* clump size for HFS vol */ + int loop; + int last_extent_save = last_extent; + char *p; + + /* allocate memory for the libhfs/genisoimage extra info */ + hce = (hce_mem *) e_malloc(sizeof (hce_mem)); + + hce->error = (char *) e_malloc(1024); + + /* mark as unallocated for use later */ + hce->hfs_ce = hce->hfs_hdr = hce->hfs_map = 0; + + /* reserve space for the label partition - if it is needed */ +#ifdef PREP_BOOT + /* a PReP bootable partition needs the map.. */ + if (gen_pt || use_prep_boot || use_chrp_boot) +#else + if (gen_pt) +#endif /* PREP_BOOT */ + hce->hfs_map_size = HFS_MAP_SIZE; + else + hce->hfs_map_size = 0; + + /* set the HFS parameter string to upper case */ + if (hfs_parms) { + for (p = hfs_parms; *p; p++) + *p = toupper(*p); + } + + /* set the initial factor to increase Catalog file size */ + if ((hce->ctc_size = hfs_get_parms("CTC")) == 0) + hce->ctc_size = CTC; + + /* set the max size of the Catalog file */ + if ((hce->max_XTCsize = hfs_get_parms("MAX_XTCSIZE")) == 0) + hce->max_XTCsize = MAX_XTCSIZE; + + /* set the number of time to try to make an HFS volume */ + if ((loop = hfs_get_parms("CTC_LOOP")) == 0) + loop = CTC_LOOP; + + /* + * "create" the HFS volume (just the header, catalog/extents files) if + * there's a problem with the Catalog file being too small, we keep on + * increasing the size (up to CTC_LOOP) times and try again. + * Unfortunately I don't know enough about the inner workings of HFS, + * so I can't workout the size of the Catalog file in advance (and I + * don't want to "grow" as is is normally allowed to), therefore, this + * approach is a bit over the top as it involves throwing away the + * "volume" we have created and trying again ... + */ + do { + hce->error[0] = '\0'; + + /* attempt to create the Mac volume */ + Csize = make_mac_volume(root, start_extent); + + /* if we have a problem ... */ + if (Csize < 0) { + /* + * we've made too many attempts, or got some other + * error + */ + if (loop == 0 || errno != HCE_ERROR) { + /* HCE_ERROR is not a valid errno value */ + if (errno == HCE_ERROR) + errno = 0; + + /* exit with the error */ + if (*hce->error) + fprintf(stderr, "%s\n", hce->error); + perr(hfs_error); + } else { + /* increase Catalog file size factor */ + hce->ctc_size *= CTC; + + /* + * reset the initial "last_extent" and try + * again + */ + last_extent = last_extent_save; + } + } else { + /* everything OK - just carry on ... */ + loop = 0; + } + } + while (loop--); + + hfs_extra = HFS_ROUND_UP(hce->hfs_tot_size) / SECTOR_SIZE; + + last_extent += hfs_extra; + + /* generate the Mac label and HFS partition maps */ + mac_boot.name = hfs_boot_file; + + /* + * only generate the partition tables etc. if we are making a bootable + * CD - or if the -part option is given + */ + if (gen_pt) { + if (gen_mac_label(&mac_boot)) { + if (*hce->error) + fprintf(stderr, "%s\n", hce->error); + perr(hfs_error); + } + } + /* set Autostart filename if required */ + if (autoname) { + if (autostart()) + perr("Autostart filename must less than 12 characters"); + } + /* finished with any HFS type errors */ + free(hce->error); + hce->error = 0; + + /* + * the ISO files need to start on a multiple of the HFS allocation + * blocks, so find out how much padding we need + */ + + /* + * take in accout alignment of files wrt HFS volume start - remove any + * previous session as well + */ + start_extent -= session_start; + hfs_pad = ROUND_UP(start_extent*SECTOR_SIZE + + (hce->hfs_hdr_size + hce->hfs_map_size) * HFS_BLOCKSZ, + Csize) / SECTOR_SIZE; + + hfs_pad -= (start_extent + (hce->hfs_hdr_size + hce->hfs_map_size) / + HFS_BLK_CONV); + +#ifdef PREP_BOOT + gen_prepboot_label(hce->hfs_map); +#endif /* PREP_BOOT */ + +} + +#ifdef PREP_BOOT +static void +gen_prepboot() +{ + /* + * we need to allocate the hce struct since hce->hfs_map is used to + * generate the fdisk partition map required for PReP booting + */ + hce = (hce_mem *) e_malloc(sizeof (hce_mem)); + + /* mark as unallocated for use later */ + hce->hfs_ce = hce->hfs_hdr = hce->hfs_map = 0; + + /* reserve space for the label partition - if it is needed */ + hce->hfs_map_size = HFS_MAP_SIZE; + + hce->hfs_map = (unsigned char *) e_malloc(hce->hfs_map_size * HFS_BLOCKSZ); + gen_prepboot_label(hce->hfs_map); +} + +#endif /* PREP_BOOT */ + +/* + * get_adj_size: get the ajusted size of the volume with the HFS + * allocation block size for each file + */ +Ulong +get_adj_size(int Csize) +{ + struct deferred_write *dw; + Ulong size = 0; + int count = 0; + + /* loop through all the files finding the new total size */ + for (dw = dw_head; dw; dw = dw->next) { + size += (ROUND_UP(dw->size, Csize)/HFS_BLOCKSZ); + count++; + } + + /* + * crude attempt to prevent overflows - HFS can only cope with a + * maximum of about 65536 forks (actually less) - this will trap cases + * when we have far too many files + */ + + if (count >= 65536) + return (-1); + else + return (size); +} + +/* + * adj_size: adjust the ISO record entries for all files + * based on the HFS allocation block size + */ +int +adj_size(int Csize, int start_extent, int extra) +{ + struct deferred_write *dw; + struct directory_entry *s_entry; + int size; + + /* get the adjusted start_extent (with padding) */ + /* take in accout alignment of files wrt HFS volume start */ + + start_extent -= session_start; + + start_extent = ROUND_UP(start_extent*SECTOR_SIZE + extra*HFS_BLOCKSZ, + Csize) / SECTOR_SIZE; + + start_extent -= (extra / HFS_BLK_CONV); + + start_extent += session_start; + + /* initialise file hash */ + flush_hash(); + + /* + * loop through all files changing their starting blocks and finding + * any padding needed to written out latter + */ + for (dw = dw_head; dw; dw = dw->next) { + s_entry = dw->s_entry; + s_entry->starting_block = dw->extent = start_extent; + set_733((char *) s_entry->isorec.extent, start_extent); + size = ROUND_UP(dw->size, Csize) / SECTOR_SIZE; + dw->pad = size - ISO_ROUND_UP(dw->size) / SECTOR_SIZE; + + /* + * cache non-HFS files - as there may be multiple links to + * these files (HFS files can't have multiple links). We will + * need to change the starting extent of the other links later + */ + if (!s_entry->hfs_ent) + add_hash(s_entry); + + start_extent += size; + } + + return (start_extent); +} + +/* + * adj_size_other: adjust any non-HFS files that may be linked + * to an existing file (i.e. not have a deferred_write + * entry of it's own + */ +void +adj_size_other(struct directory *dpnt) +{ + struct directory_entry *s_entry; + struct file_hash *s_hash; + + while (dpnt) { + s_entry = dpnt->contents; + for (s_entry = dpnt->contents; s_entry; + s_entry = s_entry->next) { + /* + * if it's an HFS file or a directory - then ignore + * (we're after non-HFS files) + */ + if (s_entry->hfs_ent || + (s_entry->isorec.flags[0] & ISO_DIRECTORY)) + continue; + + /* + * find any cached entry and assign new starting + * extent + */ + s_hash = find_hash(s_entry->dev, s_entry->inode); + if (s_hash) { + set_733((char *) s_entry->isorec.extent, + s_hash->starting_block); + /* not vital - but tidy */ + s_entry->starting_block = + s_hash->starting_block; + } + } + if (dpnt->subdir) { + adj_size_other(dpnt->subdir); + } + dpnt = dpnt->next; + } + + /* clear file hash */ + flush_hash(); +} + +/* + * hfs_hce_write: write out the HFS header stuff + */ +static int +hfs_hce_write(FILE *outfile) +{ + char buffer[SECTOR_SIZE]; + int n = 0; + int r; /* HFS hdr output */ + int tot_size = hce->hfs_map_size + hce->hfs_hdr_size; + + memset(buffer, 0, sizeof (buffer)); + + /* + * hack time ... if the tot_size is greater than 32Kb then + * it won't fit in the first 16 blank SECTORS (64 512 byte + * blocks, as most of this is padding, we just truncate this + * data to 64x4xHFS_BLOCKSZ ... hope this is OK ... + */ + + if (tot_size > 64) tot_size = 64; + + /* get size in CD blocks == 4xHFS_BLOCKSZ == 2048 */ + n = tot_size / HFS_BLK_CONV; + r = tot_size % HFS_BLK_CONV; + + /* write out HFS volume header info */ + jtwrite(hce->hfs_map, HFS_BLOCKSZ, tot_size, 0, FALSE); + xfwrite(hce->hfs_map, HFS_BLOCKSZ, tot_size, outfile, 0, FALSE); + + /* fill up to a complete CD block */ + if (r) { + jtwrite(buffer, HFS_BLOCKSZ, HFS_BLK_CONV - r, 0, FALSE); + xfwrite(buffer, HFS_BLOCKSZ, HFS_BLK_CONV - r, outfile, 0, FALSE); + n++; + } + last_extent_written += n; + return (0); +} + +/* + * insert_padding_file : insert a dumy file to make volume at least + * 800k + * + * XXX If we ever need to write more then 2 GB, make size off_t + */ +int +insert_padding_file(int size) +{ + struct deferred_write *dwpnt; + + /* get the size in bytes */ + size *= HFS_BLOCKSZ; + + dwpnt = (struct deferred_write *) + e_malloc(sizeof (struct deferred_write)); + dwpnt->s_entry = 0; + /* set the padding to zero */ + dwpnt->pad = 0; + /* set offset to zero */ + dwpnt->off = (off_t)0; + + /* + * don't need to wory about the s_entry stuff as it won't be touched# + * at this point onwards + */ + + /* insert the entry in the list */ + if (dw_tail) { + dw_tail->next = dwpnt; + dw_tail = dwpnt; + } else { + dw_head = dwpnt; + dw_tail = dwpnt; + } + + /* aloocate memory as a "Table" file */ + dwpnt->table = e_malloc(size); + dwpnt->name = NULL; + + dwpnt->next = NULL; + dwpnt->size = size; + dwpnt->extent = last_extent; + last_extent += ISO_BLOCKS(size); + + /* retune the size in HFS blocks */ + return (ISO_ROUND_UP(size) / HFS_BLOCKSZ); +} + +struct output_fragment hfs_desc = {NULL, NULL, NULL, hfs_hce_write, "HFS volume header"}; + +#endif /* APPLE_HYB */ + +struct output_fragment startpad_desc = {NULL, startpad_size, NULL, startpad_write, "Initial Padblock"}; +struct output_fragment voldesc_desc = {NULL, oneblock_size, root_gen, pvd_write, "Primary Volume Descriptor"}; +struct output_fragment xvoldesc_desc = {NULL, oneblock_size, NULL, xpvd_write, "Enhanced Volume Descriptor"}; +struct output_fragment end_vol = {NULL, oneblock_size, NULL, evd_write, "End Volume Descriptor" }; +struct output_fragment version_desc = {NULL, oneblock_size, NULL, vers_write, "Version block" }; +struct output_fragment pathtable_desc = {NULL, pathtab_size, generate_path_tables, pathtab_write, "Path table"}; +struct output_fragment dirtree_desc = {NULL, dirtree_size, NULL, dirtree_write, "Directory tree" }; +struct output_fragment dirtree_clean = {NULL, dirtree_fixup, dirtree_dump, dirtree_cleanup, "Directory tree cleanup" }; +struct output_fragment extension_desc = {NULL, ext_size, NULL, exten_write, "Extension record" }; +struct output_fragment files_desc = {NULL, NULL, file_gen, file_write, "The File(s)"}; +struct output_fragment interpad_desc = {NULL, interpad_size, NULL, interpad_write, "Intermediate Padblock"}; +struct output_fragment endpad_desc = {NULL, endpad_size, NULL, endpad_write, "Ending Padblock"}; |