~ MKISOFS.BCKY MKISOFS.BCKABACKUP/LOG DEV01:[MKISOFS...]*.*;* DEV01:[000000]MKISOFS.BCK/SAVE WATSON IPV7.1 _IDIA02:: _$2$DKB500: V6.2 ~ y*[MKISOFS]COPYING.;1+,,.$/ 4$$ - 0123KPWO%56-)70 89*̞OGHJH The GPL below is copyrighted by the Free Software Foundation, but the instance of code that it refers to (the mkisofs utility is copyrighted by Yggdrasil Computing, Incorporated). ---------------------------------------- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. *[MKISOFS]MAKE.COM;2+,E. / 4O - 0123KPWO 56d) 7:+ 89*̞OGHJ$! Set the def dir to proper place for use in batch. Works for interactive too. $flnm = f$enviroment("PROCEDURE") ! get current procedure name $set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")' $goto START $! $COMPILE:subroutine $write SYS$OUTPUT "Compiling ''p1'..." $cc/prefix=all [.SRC]'p1 $library 'build_lib 'p1 $delete 'p1.OBJ;0 $exit $endsubroutine $! $START: $build_lib = "MKISOFS.OLB_" + f$getsyi("ARCH_NAME") $if f$search(build_lib).eqs."" then library/create/object 'build_lib $if p1.eqs."LINK" then goto link $call compile mkisofs $call compile write $call compile tree $call compile hash $call compile rock $call compile vms $call compile exclude $LINK: $link/exe=MKISOFS.EXE_'f$getsyi("ARCH_NAME") 'build_lib/library/include=mkisofs $exit *[MKISOFS]MKISOFS.8;1+,3./ 4- 0123KPWO567$ 89*̞OGHJ,.\" -*- nroff -*- .TH MKISOFS 8 "January 1995" "Version 1.05" .SH NAME mkisofs \- create a iso9660 filesystem with optional Rock Ridge attributes. .SH SYNOPSIS .B mkisofs [ .B \-R ] [ .B \-r ] [ .B \-T ] [ .B \-v ] [ .B \-z ] [ .B \-a ] [ .B \-f ] [ .B \-d ] [ .B \-D ] [ .B \-l ] [ .B \-L ] [ .B \-L ] [ .B \-V ] [ .B \-V .I volid ] [ .B \-i .I include-list ] [ .B \-p .I preparer ] [ .B \-P .I publisher ] [ .B \-A .I application_id ] [ .B \-x .I path ] .B \-o .I filename .I path .SH DESCRIPTION .B mkisofs is effectively a pre-mastering program to generate the iso9660 filesystem - it takes a snapshot of a given directory tree, and generates a binary image which will correspond to an iso9660 filesystem when written to a block device. .PP .B mkisofs is also capable of generating the System Use Sharing Protocol records specified by the Rock Ridge Interchange Protocol. This is used to further describe the files in the iso9660 filesystem to a unix host, and provides information such as longer filenames, uid/gid, posix permissions, and block and character devices. .PP Each file written to the iso9660 filesystem must have a filename in the 8.3 format (8 characters, period, 3 characters, all upper case), even if Rock Ridge is in use. This filename is used on systems that are not able to make use of the Rock Ridge extensions (such as MS-DOS), and each filename in each directory must be different from the other filenames in the same directory. .B mkisofs generally tries to form correct names by forcing the unix filename to upper case and truncating as required, but often times this yields unsatisfactory results when there are cases where the truncated names are not all unique. .B mkisofs assigns weightings to each filename, and if two names that are otherwise the same are found the name with the lower priority is renamed to have a 3 digit number as an extension (where the number is guaranteed to be unique). An example of this would be the files foo.bar and foo.bar.~1~ - the file foo.bar.~1~ would be written as FOO.000;1 and the file foo.bar would be written as FOO.BAR;1 .PP Note that .B mkisofs is not designed to communicate with the writer directly. Most writers have proprietary command sets which vary from one manufacturer to another, and you need a specialized tool to actually burn the disk. The .B cdwrite utility that comes with .B mkisofs is capable of communicating with Phillips drives (newer versions of cdwrite should be available from Yggdrasil). Most writers come with some version of DOS software that allows a direct image copy of an iso9660 image to the writer. The current version of .B cdwrite is available from ftp.storm.net: /pub/cdwrite-2.0beta1.tar.gz .PP Also you should know that most cd writers are very particular about timing. Once you start to burn a disc, you cannot let their buffer empty before you are done, or you will end up with a corrupt disc. Thus it is critical that you be able to maintain an uninterrupted data stream to the writer for the entire time that the disc is being written. .PP .br .B path is the path of the directory tree to be copied into the iso9660 filesystem. .SH OPTIONS .TP .I \-a Include all files on the iso9660 filesystem. Normally files that contain the characters '~' or '#' will not be included (these are typically backup files for editors under unix). .TP .I \-A application_id Specifies a text string that will be written into the volume header. This should describe the application that will be on the disc. There is space on the disc for 128 characters of information. This parameter can also be set in the file .I \&.mkisofsrc with APPI=id. If specified in both places, the command line version is used. .TP .I \-d Omit trailing period from files that do not have a period. This violates the ISO9660 standard, but it happens to work on many systems. Use with caution. .TP .I \-D Do not use deep directory relocation, and instead just pack them in the way we see them. This violates the ISO9660 standard, but it works on many systems. Use with caution. .TP .I \-f Follow symbolic links when generating the filesystem. When this option is not in use, symbolic links will be entered using Rock Ridge if enabled, otherwise the file will be ignored. .TP .I \-i include-list Use the specified file as a list of files to add to the directory tree. This is useful for quickly repacking a CD while adding files to it. The format of this file is path1/file=path2 where path1 is the directory in the ISO9660 file system where file should appear and path2 is the where to find the file. .TP .I \-l Allow full 32 character filenames. Normally the ISO9660 filename will be in an 8.3 format which is compatible with MS-DOS, even though the ISO9660 standard allows filenames of up to 32 characters. If you use this option, the disc may be difficult to use on a MS-DOS system, but this comes in handy on some other systems (such as the Amiga). Use with caution. .TP .I \-L Allow filenames to begin with a period. Usually, a leading dot is replaced with an underscore in order to maintain MS-DOS compatibility. .TP .I \-N Omit version numbers from ISO9660 file names. This may violate the ISO9660 standard, but no one really uses the version numbers anyway. Use with caution. .TP .I \-o filename is the name of the file to which the iso9660 filesystem image should be written. This can be a disk file, a tape drive, or it can correspond directly to the device name of the optical disc writer. If not specified, stdout is used. Note that the output can also be a block special device for a regular disk drive, in which case the disk partition can be mounted and examined to ensure that the premastering was done correctly. .TP .I \-P publisher_id Specifies a text string that will be written into the volume header. This should describe the publisher of the CDROM, usually with a mailing address and phone number. There is space on the disc for 128 characters of information. This parameter can also be set in the file .I \&.mkisofsrc with PUBL=. If specified in both places, the command line version is used. .TP .I \-p preparer_id Specifies a text string that will be written into the volume header. This should describe the preparer of the CDROM, usually with a mailing address and phone number. There is space on the disc for 128 characters of information. This parameter can also be set in the file .I \&.mkisofsrc with PREP=. If specified in both places, the command line version is used. .TP .I \-R Generate SUSP and RR records using the Rock Ridge protocol to further describe the files on the iso9660 filesystem. .TP .I \-r This is like the \-R option, but file ownership and modes are set to more useful values. The uid and gid are set to zero, because they are usually only useful on the author's system, and not useful to the client. All the file read bits are set true, so that files and directories are globally readable on the client. If any execute bit is set for a file, set all of the execute bits, so that executables are globally executable on the client. If any search bit is set for a directory, set all of the search bits, so that directories are globally searchable on the client. All write bits are cleared, because the CD-Rom will be mounted read-only in any case. If any of the special mode bits are set, clear them, because file locks are not useful on a read-only file system, and set-id bits are not desirable for uid 0 or gid 0. .TP .I \-T Generate a file TRANS.TBL in each directory on the CDROM, which can be used on non-Rock Ridge capable systems to help establish the correct file names. There is also information present in the file that indicates the major and minor numbers for block and character devices, and each symlink has the name of the link file given. .TP .I \-V volid Specifies the volume ID to be written into the master block. This parameter can also be set in the file .I \&.mkisofsrc with VOLI=id. If specified in both places, the command line version is used. .TP .I \-v Verbose execution. .TP .I \-x path Exclude .I path from being written to CDROM. .I path must be the complete pathname that results from concatenating the pathname given as command line argument and the path relative to this directory. Multiple paths may be excluded (up to 1000). Example: mkisofs \-o cd \-x /local/dir1 \-x /local/dir2 /local .TP .I \-z Generate special SUSP records for transparently compressed files. This is only of use and interest for hosts that support transparent decompression. This is an experimental feature, and no hosts yet support this, but there are ALPHA patches for Linux that can make use of this feature. .SH CONFIGURATION .B mkisofs looks for the .IR \&.mkisofsrc file, first in the current working directory, then in the user's home directory, and then in the directory in which the .B mkisofs binary is stored. This file is assumed to contain a series of lines of the form "TAG=value", and in this way you can specify certain options. The case of the tag is not significant. Some fields in the volume header are not settable on the command line, but can be altered through this facility. Comments may be placed in this file, using lines which start with a hash (#) character. .TP APPI The application identifier should describe the application that will be on the disc. There is space on the disc for 128 characters of information. May be overridden using the \-A command line option. .TP COPY The copyright information, often the name of a file on the disc containing the copyright notice. There is space in the disc for 37 characters of information. .TP ABST The abstract information, often the name of a file on the disc containing an abstract. There is space in the disc for 37 characters of information. .TP BIBL The bibliographic information, often the name of a file on the disc containing a bibliography. There is space in the disc for 37 characters of information. .TP PREP This should describe the preparer of the CDROM, usually with a mailing address and phone number. There is space on the disc for 128 characters of information. May be overridden using the \-p command line option. .TP PUBL This should describe the publisher of the CDROM, usually with a mailing address and phone number. There is space on the disc for 128 characters of information. May be overridden using the \-P command line option. .TP SYSI The System Identifier. There is space on the disc for 32 characters of information. .TP VOLI The Volume Identifier. There is space on the disc for 32 characters of information. May be overridden using the \-V command line option. .TP VOLS The Volume Set Name. There is space on the disc for 278 characters of information. .PP .B mkisofs can also be configured at compile time with defaults for many of these fields. See the file defaults.h. .SH AUTHOR .B mkisofs is not based on the standard mk*fs tools for unix, because we must generate a complete copy of an existing filesystem on a disk in the iso9660 filesystem. The name mkisofs is probably a bit of a misnomer, since it not only creates the filesystem, but it also populates it as well. .PP .br Eric Youngdale wrote both the Linux isofs9660 filesystem and the mkisofs utility, and is~ MKISOFS.BCK3 [MKISOFS]MKISOFS.8;1. currently maintaining them. The copyright for the mkisofs utility is held by Yggdrasil Computing, Incorporated. .SH BUGS Any files that have hard links to files not in the tree being copied to the iso9660 filessytem will have an incorrect file reference count. .PP There may be some other ones. Please, report them to the author. .SH FUTURE IMPROVEMENTS Allow specification of multiple paths on the command line to be included in iso9660 filesystem. Can be tricky - directory entries in the root directory need to be properly sorted. .SH AVAILABILITY .B mkisofs is available for anonymous ftp from tsx-11.mit.edu in /pub/linux/BETA/cdrom/mkisofs and many other mirror sites. With the 1.0 release, it is no longer considered to be in beta testing. Most of the bugs that are being discovered now are very minor (and interestingly enough also seem to be present in the YM software). Reports indicate that people are gearing up for production runs using version 1.00. *[MKISOFS]MKISOFS.EXE_ALPHA;1+,4./ 4- 0123 KPWO56#=70>89*̞OGHJv h(=0@o<w=MKISOFSV1.0A11-39$" $( $ ($^ $Jm$( 8 CMA$TIS_SHR_0018 DECC$SHR_0014& LIBOTS_001@>SYS$PUBLIC_VECTORS_0010 h0 FxUsage: 0@"` w w`'&HOMEr&0 @  '@%0 & pUsing "%s" @`$wctx=binRRIP_1991Awp(B0S`8 @"h rfm=fix$eP&P08@$ %#$%#0%$%0&0"  &0]p$#P$##%$#h %s %%mrs=2048e & 2p yUfop=ctgC@ 08"P 0"p0 F@ 0"  ....DIR;10"00 0 0 F@p0 @< 0(0" 0"@ &0 0 00 @< 0@0 0 X!P F 0 (#@| P"$  0 8'000h 0%%d %d %s &@...&0 H(@| p$0&pFatal goof p@]P&#%mkisofs v1.05%$# 0 "8 $$$CD001F&d  %@& 0"H20`0 10 H 0 2p p!`'0 0 h- 0 &0 0h w0H$0 @%@< 0 0 @"@< h 0@0 e0 %4d %5d %s F0 d0 h-  p@%   0@%@ &Fatal goof ;1p&@`. &'0` C $%& TRANS.TBL..F%$%s.%3.3d%s@$h%c %-34s%s P$0hh 0 MP %rr_moved./rr_moved0"B0 0%~p0"(B0 0"T |8Excluded: %s F %s ({p&~0 "U #%#}fD %s 0&0 hR0 0 0S@< 0 e0 @ F0 &@ '0"f &0 Pg0 d"h 0"w@ 'ERF  p0"h 0h@'&.SP&ȇ..0 @y  %s F0"ȇ  @''0"@0 Z @$CLOSE0"@< pP$CONNECT$OPEN0 ` $%d..0"~0 F &%.*s]%.*s.DIR;1...0"~ }p"0"|@| 0~0"({0 `'p.DIR;1&]0"y 0CDROMDECVMSPREPPUBLAPPICOPYBIBLABSTVOLSVOLISYSImkisofs [-o outfile] [-R] [-V volid] [-v] [-a] [-T] [-l] [-d] [-V] [-D] [-L] [-p preparer] [-P publisher] [ -A app_id ] [-z] [-x path -x path ...] path %s:%d: field name "%s" unknown %s:%d: equals sign required %s:%d: name required %d extents written (%d Mb) Max brk space used %x Unable to open disc image file PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICSTransparent compression not supported with VMS Application-id string too long Publisher string too long Preparer string too long PT|0hi:o:V:RrfvaTp:P:x:dDlLNzA:Not enougth memory Non zero-length file assigned zero extent. cannot fwrite %d*%d Reported file size is %d extents Starting block is %d Extent overflow processing file %s Cache hit for %s%s%s Path table size(bytes): %d Total directory bytes: %d Total rockridge attributes bytes: %d Total translation table size: %d Predicted = %d, written = %d Number of extents written not what was predicted. Please fix. Total extents actually written = %d Total extents scheduled to be written = %d 0000000000000000%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00Path table lengths do not match %d %d Entry %d not in path tables Continuation entry record length mismatch (%d %d). Unexpected directory length %d %d %s Translation table size mismatch %d %d Fatal error - RR overflow for file %s Using %s for %s%s%s (%s) Unable to generate unique name for file %s Unknown file type %s - ignoring and continuing. Directory loop - fatal goof (%s %lx %lu). File %s is not readable (errno = %d) - ignoring Warning - file %s has an unsupported VMS record format (%d) Already cached directory seen (%s) Symlink %s ignored - continuing. Unable to stat file %s - ignoring and continuing. Overflow of stat buffer Directories too deep %s Unable to open directory %s Unable to locate directory parent Can't allocate memory for excluded filename Can't exclude '%s' - too many entries in table Extension record too long %.*s[000000]000000.DIR;1%.*s[000000]%.*s.DIR;1Ran out of VMS directory contexts $PARSE of root directory failed mkisofs v1.05.mkisofsrc0%8 %@#H#P#Xp#`@&hP&p&( # "~8^@^HcG0[#CGC>C8{4G>޶9mZk(=0b#@ӰBbG4GPZkcG8]@]HP#kG#~^> ^TG~޴ (0>8G [GGCCAZkXBC`b1G@gAZkCCB@bG4CZk= (BC0b4GXDDZk3hB0I@pb4GbZkC, 8BG? wAZk8BGCsAZk@P@B@]"C@ZkxB"bCCTGVeZkXB `bC1G@TG1AZkC;BbGBZk(BC0b4GXDDZk.8BG GIAZk@@B$= C@ZkxBCbGTGfZkCB0@C@ZkXB `bC1G@TGAZkC BbGBZk(BC0b4GXDDZkb BU@bCtG{ZkGhBCpb?"GtGAZk0@C.JF@8F`0@xFG@G#¦ .֢WJJVB֢J 1G&/F#bP:KB4GJZkZk'(F" &.Q2J'JP0BPF f."B4GbPtJJpkZk &,"Bb4GP0HJkZk.qHPJF>0@F.FJ_D B"bBCGG {ZkG,HD8D 0@DB B}"YBbCGG {Zk0@G,HD8DH.RHJH>.J.JXF 0`B/K XG0`BS/SK_.PJ>HC CBG tZk !AGBG 4Gb_Zk= )CGGK?¤BG bCzZkB=!(BC0b4G ECZkBGb4GpZkG]]}ݤ (0=8@#k#TG~^^~ G {G0[iC8{zZk0BTG8b@"zZk`Bhb4G4G~NZkG]]} 0#kG#C~4G@^H^PG0[G8{TlZk BC(b4GrZkCC`GGq1"`2@B _PB4GXbqArZkC$=" 1@@,} 1@ ",ݢGDVB vBXC]xCB@B8CVBXCvBxCVBXCVCB0B;CFG@]rOH]P`#vDJ CFk#4G~^^ ~(GX[GG`{>CrZkCC."###"RCJsJSFC>D.4BwJVJ"F> GDC/{KZYK##[GC?GDC.sJ"RQJSFC>D.wJVJF> GDC/{9HXGZYKrPH[GC?GD#.Q0J2F#>]] }(0#kG`#~^ ^(~08@޴HPX>`^h~px޵G[>$BG GGdCGX~ZkG?! G G GG.WJ>4GIGBE@G4GE~Zk .x'H0@WJF>.PJ>4G6#.G#J BF@G0~Zk.JxF0@ 4GF 0@A0@ 4GxF '.rJ0@4GQ'J2F'>0@G`"d.`JStJgJfB=gB`g/[gK`Gg?0@ 0A F0  0`A0@0٣A" G0@"1D.RTJGJQQB1P F $,$HL.s HRLJSFL>{.d"B4GbPJJviZk$,"Bb4GP0HJiZkFGyJE0A_/XKG?0@Y 0`AXG',GpGKA'H0D'<0@0@K/ݡ0d""yAD0AݱG@0@1D.RSJGJQQB1P F -I..rHQ.J2F.>-."B4GbPJJ(iZk-$ Bb4GPIJkiZkóA0`0A G0@".VJJUBPF-I_,.r HQ,J2F,> 0A0@d.dJ, X@E+@.GJ/KG 0`@C/CK@OG@0`@#,#H?,0`@HD#.#J G.!J؏F c-0`@BKmIc.WBgIcJ B7fA? G%BGxJJ D @'/Y'K8G'?0@ }0`C }tGBp'H0@4GZtNJHD @ ,@HD<0A,DHD< PA g-KgIg=} Af@P7e@G] ](}08@ݤHPX=`]h}pxݥ#kG/$#BbPK4GJhZkx-$ Bb4GPIJhZkr#YB~^^~޴>^~GGGG {#_b#_BGbG CtG|lZk4@G G 1@"7@\@CkG0BTG`b@B}Zk@B"bCxZk|0TG"@B}Zk@xB"BR"bCwZkj0TGX"@B}Zk@fB"BR"bCwZkXh 0 @ XGB?"2Sðb0BNpբ0BղI0CD0"ABz0`Cz<  0 @ 7" bQ0@BQ0B.0¦)0C$P"Y0@CYHb0@G"TG"BH1"bCwZk 04GG b#@Gb#_B4Gb4GuKZkBGbG CtGkZk4@X?BGb4GA[Zk¤C(BS@&tGB b2BBhwZkb#_Ӑ"b#!A$@_Bb4G4GHKZkGGxb#4G{@Cb#_Bb4G4G:KZk @"B" (bCGG2"b#`R"CC3cB@ GC b#GTGz @=TGG`b#ђ H[@B@BGTG |Zk@G "` b#@.GRQJ@>C@4GG b# $$ @4GB4GbJZk(b`B0" hb" CCC4V@W@GGa|ZkC TGB8 bCvZkB4Gb4GJZkð? TG4G`b8G@b# HvH 0 B0F3 P"BQB%T@)"TG *0@ !GF0tIxib#SBTB@t)_"x TG(G @b#0@@GG b#/@Gb#G@Gb#G@ƠG4G @b#@G4G (b#@ӠBG'4GbVZZkB  Cb2@GGtGvZkEB!C3AJbG6aJwvZkG]4G]}ݤ=]} #kG#4G~^^~ G0[G8{gZkCP" ` B(b4G! CxZkpBxb4G4GF.v4JUJF>kGP.0 J?Fs0HRPJ"SFP>F.v4JUJF>kGP.?Fs0H"RPJv4HSFP>F.0 J s JUJ0 F>u!JFP.R@JSFP>GF.TJF>kp.?Ft0H0 JSpJ"tFp>F.xHP J0 WJsJF>p JFP."v4JRAJSFP>GF,@HD<kp.?FP"t2HSrJ0 JtFp>F."xHP JWJ0 F>sJFP.p Jv0JRAJSFP>GF,@HD<k0,0",p"P.1H0.H"a1 H3JPJDqQ JDpqJDDkGP.?Fs0H"RPJw5HSFP>F.0 J sJVJ"F>wJFP.P J"p JR@J SFP>s HF.VJF>v4HFP."R@JSFP>F.r7Jp"UJt3JF>F,@HD<GF0,A3H4D0<k#~^^~ (0޴8@GG! GGGG_0BG8bGGGG8KZkG "G@BGHbGP"sZk`Bhb4G4GGZkL$@`@G]]} (0ݤ8@P#kG#~^^~ (0G(G$HG (,#sJ0B2?JSF,#$C"SB2AJvAJ@#_" 3B2F1!Jv!J@4G b_cG]]} (0@#kG#~^^~ (0޴8G GG.G?" G %b#1@&D4Gq_ %"("d0@FQ&HaBvH$FBѰGG %tG b#@0B4G8bdZk0BG4G8bdZkG]]} (0ݤ8@#kG1B$B0,0H" q.qJ`.xgFJxFxF xgF`xFxgF`,P"1,#0B@HA8HH'H0 B @ @.J.4GJ k k4GkGk k4Gk.J?B 5 BkG#G~^^~ (0GG0G q0@B`30@B?GP_Bb#4GGr_CCG @P0@$"FTB%"%.VJ%>R_`BGhbG bGGDZk 1@0@ @GG@ @ 0@1"Ѣ @18Qqz_Ѣ0 @ @1"e@@`BGhbG%4GdccZkG]]} (0@#k#C~4G^^ ~(G`[Gh{WdZk0B8bC4GTjZk0bTG@?##.q#Hc"PJF>D.P`@XTJ>(2;_Pa@$CG5_G=Pb@xb#TG!_.TG# qHPJC"F>"Dc.c@4G4GSrJc>yJD.!C UJ~ MKISOFS.BCK4 [MKISOFS]MKISOFS.EXE_ALPHA;1|<>_ /GXKG ?GD!c/[bK!c?]] }(0#k#~^^~ (0޴8GG1G 'Gl$TGGpPb#1v J'_C@""Gb!B `DpBTbJ@RrZk %Ѐ@_%Ё@B1C@TvZk?BT1D@vZk:$0 HX D6 F%$F BBN@bTGqZkB4Gb4GEZkD(%Ѐ@_(%" b#H$4G$E PCFGLD:@G G_$ Ё@@DGB1C@T4GMvZkzB1D@THvZkuLĠGG`b#lG_¤C&  Gl$1v J1" XDeEGBG"\$CvZk`BhbC4GDVZkG ¤Ѐ@%4GLD E&%[_GGb#H;_L? @B?"@DR HBb1K@vHGB@HDC31@fqZkƠ$$7 "BC@¤ab+@tGXqZktGBHD@bPqZktGBLD@bHqZkB4Gb4G3EZkF ¤Ѐ@&AB1C@T4GuZk(#Ѐ@ _(àG#GHİ$ Cb#GL_(#?"Ё@H$$@D$àb۠{#xD $@۰Ѐ@ 4G( __#G(xHd$ؠb#@GDLİ_à?"Ё@(&H$$@D_4GHb_cG]]} (0ݤ8@#kGp#"~4G^^ ~(08޴@HP>X^`~hpx޵GGG$P b#GSBEFGGb_ӠBCGG=wZk"G+HB F]CCG GvaI b#4GM_ӠBC=G(wZkG-+@.w!HC ?#9E$ "BF@@9A%FDG3!I4C@M"wZk$-x?D4$@!!H !AO8!I 0 A@.PJ>xM|-YF6@} Ct 3`G."CJxF#X/x#[KHG@E5_B? ABEG:DG A1AICv!J=__#CZE9_X-X# IZIBA0AA CGTwZkE,"X!H H96C} CC"3!IBtMx-@! |M@wZkx͢ BA 6A !I 0 A@ /Y K ? G4Gt BbuaZkBT 4GbpaZkBGb4GkaZk~$CG"GbIF P"s"pBCxbGpZkG4GGG0b#!_BGb4G AeJaZkc¤GP"GEpBp CxboZk]G4GG0b#_}G4GB+aIbvaI Ae+aZkG]] }(08ݤ@HP=X]`}hpxݥ#k#~^^~ (GG`G _,4G$ b0vJABa_cG]]} (0#kGGG1 P,R,2v@J4vJ TBGk TB@4GGk0q`]$@dB)tZkGkG#4G~^^~ (0޴8@H>P^X~`hGX;GGb#!#w!HCG_GG4Gb# _PBCGGuZkDG ¤4GBG& uZkGb#P?@8b_&BCGQ?@uZkb#c G|_G&G0BG b@8b11 @AZk#4G=@1"_qx H,6vJ7JFF,0A0 @ @1"?=@4G G_CG¦tGbICP"ZBC@boZkB4Gb4GCZkj'B"C+,QE+H2F b" C@BHbGGTGWZZk"B"BTG bCnZkBb4G4GBZk%%l!$ 0@DA.s!KPBRAJSFA>Bw4K.VJF>(*CC`_dC(*zC{_J%,Z@ @1v@K_j,{B1v`K_C8q C 8C P@ACw G[`ZE+"B+,@C+HZ.s:HRZJSFZ>.BJT-k!lJJTI LET=e"+,`C1H{.["z2HSrJzF{>k"D- @AI."qIVJF>%+"K. @SJa/A#tZJ[zKtGa?D- @AI."sIVJF> B%K @"A/{TJZTK[GA? B$K B!q.uLI@SlJuFq> GE0B BK/TBKK-qRKLI E=d.tBJ.0BvJk!PJF>D#0A A 0 B*F A#0B4G8b_ZkbGCkB( SFb@C.nZkG]]} (0ݤ8@H=P]X}`hp#kGG [GGGsZk] @GGFGG uZkGkG#4G~ ^(^0~8@H޴PX`>h^p~xG #[GG{C_Zkb#G_B "?"ctZkCXB# lU"0BC>G `bKqZkBC1I@rZkC4G_"Gxb#0@_Ӡ@B"?"M"?tZk¤$ "B?" ?D6tZkB4 @$H/!60HL"/ HhB@KXBY7K2G"JG7J$$F @ $($5sZkGG8b#_ӠXB@0$ 8$@$H$G'sZkGG8b#q_(@'Gb_@4G_@4G_@?"_"@)U_0b@;_;@_;@_ ;@_Ӑb"PBTGBИ@;ftZk(B"GGtZk XBGGrZkGG8b#<_ӈF"(BGGtZk XBF CGrZkGGG8b#*_Ӱ"(BGGsZk XB CGrZkGGG8b#_F"(BGG8sZk XBF CGrZkGGG8b#_(B"8GGsZk XB CGrZkGGG8b#_(B8"GGsZk XB CGrZkGGG8b#_(B"GGsZk XB CGrZkGGG8b#_(B5"4GGsZk(BF"4GGsZk(BW"4GGsZkx${"(B?"h$G!?Hp$ ! x$sZkPB5"]"4GsZkPBF"]"4GsZkBPBW"ݦ4GR"sZk@x$4G_"DhĶ?DDpGxxb#_B"?"-sZk$M"?#0@?D$!60HH.9&KL/@4GJXK_"FJG6Jxb#F9@$_@&4G8BGxb#0 @& 2wHC_4GbGxb#2wH C_4GB@@ bG]ZkB4G b]ZkGGhb#TGI @Ө4G_"Gxb#w_F 0@AFbtGBk!GCbVlZkGb#_bBtG FCbHc!IlZkGBCTG  Eb @(c ?lZkBCgGbG7lZkb¤tGB CFb-lZkB{@FtGb&lZkBw@tGFblZkBs@ItGblZkG ](]G0}8@HݤPX`=h]p}x#k P. 0" p.$? #QJU qJS qJFF JRQJtJuFTF p>qG <F . "yHW JpG[aKW @yD% .0 Dp. "qFT JSpJ>p>4 D pFaHWJFWC P. p. p#?'[JQ {Jm9#FFS {J JR[JtJqF p>TF P>kyGyG0HFF#TG~^^~ (GGGb#G@G"G! _G]G]} (0#k#TG~^^~ (GGGb#G@G "G! _G]G]} (0#k@#4G~`^h^p~x޴>^~G #Gp[G&.& )%,GGx{JA HFC*C3]Zk&E""" H X=).&e. 2HT Ju2HSrJFuF)>&e> 7HD%%/z7H"/ HY 7KXK;GG%%?"?r HD!%..Q JPJ3FF!%>>GGb#K_ GG%! b#C4G_ CB 'E B 1P@bTGkZk@BHb4G4GZkBCCpZk"! BCpZkw@ 7J C`BGhbTGTZkC.PJ> G_GCV@0@JU@BC`w#"#BbxFGCGZnZkGC b#4G_ 0`A+ ?k! `bBtG TGbqBjZk@BHb4G4G~ZkP4E@P GBB@ )TɢMBcTCb޶jZkB0]!CMpZk$'BDC?E1D$EpZkb0@0@sGD`xB0@DBCGD!GCoZk7GGb#4G_"BCT'4E@ -BcGTb>jZkB0]!CpZk$)DBC?D2F$ pZk0@0@GDxɢB)0@BD?GD1D C$AnoZkGGPb#4G_GPb#G4G _4J@G4G b#$_Ө@ ") #E 0B1F@TnZk 0BTL@nZkXBoZk@p@GGb#4GG_C GG_'@_&R" BAX&e" #TGG G(b#6DI$f! ~?%`$Ђ@1?J$PD&.).JU JFC_l@G4Gb#TG'H l pDgEg_Gb#Ё@GTG_B4GbPB!Lİ A`dNZkGGb#4GT_BCXGG`pZkGCb#G4GtG_e4GG0E@C+v`Ib#C)iA%C GGG@ c"(R`BdA1F@`"WoZk+ G0BAA0 HX D T NnZk 0BT CInZkB0BYEÐ" 4GB!aD T :oZk8DǢ0BDzGD' 0 B'_E$K 0DA0@AXE_FtF$Kx+ YA0@AWEBtG_Ab ECBTKiZk@B4GHb4Gm}Zk _ED0D kGa@b#4GG~_F C4@GDE0B.Xj1F@G*`T mZk'0BL@T mZk"XʢBDAbC.#0B\@RJGJlZkB` XdCnZk(BeAGG`]"DpZkBC4G GnZkBX @bZZkXjJ_DBGbGG".iZk@B4GHb4G}Zk #!H  $? "DD@@@0D$#GD$#'B$D2@|xF.}@tɠ+G.&#G@b#JxF/K4GG_"?"_"D @0@ @DGDc`B0@"."JJ%@}@@)?G`]h]p}xݤ=]}#kG#C~4G^^ ~(08޴@HG@[GH{ZZkGb#G4GP_bCG!"@4G4G @?`BbpeG@ SMZkBE@4GbLMZk4G#B(#nZkGb#G%_CGG1"BC4G B?DBb  +MZkT$&G"b#TG `0P2_JR"Pd sPbB=,_ĠGG6Jb#TG Ơl&@!?H! l&p&4G_à4GGtG b#h_Ӹ¤mA?&"B"GTGGCb#C 0vJBC E@GG(@GGb#4G_C" CGG3aB R"B4GbLZkG" b#CTG4GtG-_BmA?&Gb"`" TG&Gb# 0vJBC CCCGG@GGb#4G_C0Z@ GGG3aB R"B4GbLZkG0Z@b#GT4GtG_CGB mA?&`b"cTGGCb#G c Ơ 0vJBCC Ҳ1Z@GG@G]] }(08ݤ@HP#kG#~^^~ GG|0t0 G,q"H DQ.SJKF @Q.q""SJTJ! @2B? G q b#C4GH_GCb#0@TGV_G]]} 0#kG#~^^~ (0G{G# !!8 EDF@F¦TG`B"bCOgZk B(b4G4G:{Zk %"GTGb#!t!|`d0B(3B_d$G_"b#TGt!|0B(%B _`pb#%_eb#c|_G eb#t_G]]} (0@#kG#G~4G^GG({# @G] #kG#4G~ ^ ^ ~ ޴  > ^ ~ ޵ GGGb#GGn @@BCHbG4G_ZkCxCGxb#4G @C`""G BtG`1"(bCfZk G8b#4GDx @GGGG`4G0b#R_ CBGb)G)G )4GCaKZkC G$(%AF %) 8G4G i! 0֢8G?6 %(G htG`" B`C(b @1"CyfZkBb4G4GdzZk 0B ( ( Q@1q`G1 G@Gx4Gxb#D @C8" 0@ABG!GbTG OZkBbGtGTGOZkpBG?"kZkpBGGkZk @P@@`bTGB B s"(bC3fZkBb4G4GzZk0BCGTG-kZkBbCGOZkGC@b#4G@ h"1P@tG!?B B(bCfZkCC0b#V_ GCCb#o_BP" C EGjZkB@]"4GlZkŢB"C6EGjZk @"B4GGlZkB"G4GlZk=% ¥!R K%.,G!-G C`6 h¦H&D"֢Z="8J H]}.KZ].:vJGS qJ]}>{SJRQJGZ]> D6J@[GH G `BtG B#C(bCeZkN`bC¥tG Bk!C(beZkCGO HBP"CRHG D F-jZkDB"CG'jZk>@TGG@b#ђJ_(h"tG`B! B"(b CC}eZkH?&D=1"Z}.Z]"0H].!?HJT J]>FSrJ6vHZ}>wSJG! D=6DJ@]FHG@]"@=@]"4G֒@KBTGWlZkGb#GG_P" BCGiZkB"CGiZk HTG@GRJ@b#ђKF"j_Gh=`RHBP H B D(b 8F F3%HX"gJCC#eZk%pB!xbRHC DDGTG]Zk G`"CGB ! CbFlZk BG`G(bGGeZkGΡP" CBG,"RHTG D &iZk$BCGiZk@G@b#ђJL_@ݥ"C`"G BԒI@}(b>BdZkBb4G4GxZk@ݥTGG@b#ђI_ݥ?&1"`RI B(btGE E E E N" @n"`!BCdZkN ``¥C BtG!(bCdZkBGG0b#4G9_ C ɡGB4Gb˱ GX GIIZkBbCT 4GCIZk\ `+f]" TGGb#0J +bA1?J+f}.i.rJT JtFCC_+¤""BC!v H+G6KAD GhZklTG7J"lp @=l 1&K2J$J2Fl @}pkdAG4G`b#TG_HGGpb#GRHtG D@"Cf_Gt+xZ="|TGHZ].]}.RJQJG FPb#"S qJaASFC _?$Z}.! ].RHZ]" D  D D " " rJT JtFLKL 8K# BP"#CGhZknB!CGhZkhH=b#(R H,D! _ 颷B\0_GG0b#4G_ CGmGGq2ABm!1"_q4GBX. ɢbTHZkT&_&hR"GC !4G@b#G.G PN iGdnCC@ƠC0bGTG`ΰ_`.HݤZ="HaAGTG&HPb# vHHG&HDH]}.Z].S qJ]}>RQJZ]>G_Lˠ&H˰l H l "P""BC"!` ! T ,hZkBT C'hZk=#CCRK G#TKÀ!TKC1N@BtGbfZkB!bC4G0HZkX P" HCBG"RITG E!hZkBCGgZk 0bCGc_ݤ-H,vHI EaSIE=h¦P"%EBV1E@ T CgZkD֢!CG@b#CCGGGG4@GG4Gx8b#}@Gb#_4GG ] ] } ݤ  = ] } ݥ #k#~^^~ (GGGGGGb#GTG(_G bTG_G]]} (0#k#~^^~ (GG G@BE@G$c(CHbbZk8b4G_cG]]} (0#k#G~^^~ (G ;GG! r" `0@BTAB"0@BVAB֢"H" @0BG&C8btGbZkpBGDAB4GChZk`Bhb0@;TZkCTG@"0B8bH"bZkPBGgZkG]]} (0#k#G~G^GG7 GX" A @SCGgZk 0CYC9?G]G #kG]4G #k#TG~^^~ (G {(GG#b# @ @0B@0_tGGG0@@u@J.0 @@TJyJF>/0B@spKXKb#@G?4GP.vJ0 BTGRPJSFP>@:,A:H6D:<G#G_GGTGb#@@_GGb#TG@@_#@ G]_ D]} (0#k`#tG~G^G ^(~08@޴HPX>`^h~px޵G GG ޠGPX;GD^G )!X; Dz8K `C TGDGG G G0@C:Au:J.0`C;Ay;JTJ0@F>. AuK0BWJ0AF>. 6A4GyPKTJ@B0BF>J@].WJF>G},@H<DzBfZk[@BP@G=fZkVBG9gZk GQGG'GǢ)9BACC C16B19B2#B4G0B7AG.y7H0BVJ4AF> HB4,5AhFGvtJA4H@B6D4</0ByPK0B0BXK5AG?G.E4GvUJTJ;AF>.C0`Cx JWJ;AF>g!@8bGGtG1LZk,A aE@ A0b#_Ӱ0b#ǡ).A@@ @_GG 0A ,Aq H .0A -AP JuMJF >.0A/AGTJzJF>//.A4GpvKY/Kb#0A:G/? !-i"GTG 4`ELI E= %.nB E. !DZ-JR MJ2F_ -- TGIGN Ib#AEC@_!GTGb#! A-A,!I@ HEC_%.TG- A.JO IGAb#/F !_ - -$ǡ IGL Ib#?$ EE! ADZD?(@ "CG_"tG@ AG G(@-Gb#Ё@TGNI(@= `E_+(@ #A0b#ǡX"-A )! A A AG_ǡtGG0A.Ar.H.. 0A/AQ.JwJ2F.>.0A -AGVJ{ KF>M/0@ A4GZMKrI[GM? .3A0`BQ J2F >-OI=G.gJ`BChbGTGJZkCC.,1APJ>"#."'#JX"G%F#`.i8CXCJC؅F.)!J C0b#_GPA0@ At J`.!A0 @S`J,QAtF`>.VJ>'G%FG#/##gX"K:[CI)!@@ @0b#_TGPA0@ At J`.!A0 @S`J,1AtF`>.VJ>'sG 0b#X"'7BI7CB B)!_GPA0@ At J`.!A0 @S`JtF`>.VJ>'SGCX"'7BI7CPB BMBeZk GC@'g HAGX"F33BTB)BBG B G!4@!3@ 4G&#@XD8bC#C0 B,uJ0 BC@HtHD<."BGVJtGF>GC0BAf@PAJZk,A*FA@?0b#S_N-G`H 0AJNI @EN=G0A#,#H)? 0b#B_N-G`HJNI 0A @EN= .qI4G m"P JuSJF > E .TJF >Ǣ0b#X"6BYCB B_X"GG)!0@$AmdH- 0@&ALIqH E=.0@A *ATGPJvjJF>.0A.A4GUJzJF>.//AGhrKY.Khb#"!:G.?0A, /AGATGDH!D< pE",%%, HA -H&!DC_ǠGTGhb#@ǰ &Ae,AA!,nHD HdDC _TGGhb#A&-(A),AIF HEC_g 0b#ǡ`@g+G#n@ CAd@ h@`_TGGG0@%AjI- 0@&ANIaIE=, 0A ,At,J@H-AD<l.4GxJ 0ASlJ hEtFl>.WJF> =DgP G7@I$dC@@ @0b#_ǡGGGGb#0A.AeI-0A/AMIpH E=/,0`@#At#JA/H &A0D/<c.4GyJ0@ScJ"tFc> /BG dEX KG ?TGǰ_@0b# GD E6ǡ-A@@ @G_g tGb#G 0`@#AoI-0@A *Aq HMI0@ E= .&AGuFJP J%AF >.4GzJ0@TJ"F>$/BG bEY$K:GG$?TGc_ga@gE0b#_TGG-omIb#,ANIE=G1LAM_G4Gb# _C gBGdDXBtGxe|aeZkG] ](}08@ݤHPX=`]h}pxݥ#k#G~G^G^ ~(0G0[G~cZk0BGGcZk0BGG8BcZkBHbBtQJ BuKyHr J5GTFFSBD!B"G$eZk B@GGeZk B8C @@GGeZk##@ PBXbTGh"^ZkpBxb4G4GqZkG"b#4G_`BCG?"|dZk BGGGdZk=aG]] }(0@#k#G~tG^^G(;G@[dCH{]Zk0B8b4G4GqZkG]] #k #G~G^^~G8;G!aGXq2ABa! \1"_&XqG\G`ݢUuF_X9!CU" x#u?hb4^@X4G8B xc 4`ݲd}5cZk<}(BDC0b3J08CD <fcZk""GBTGb,B]ZkBGb4GuqZkGG$,A$H$<]]}#k#? ~^^~ (G[GGbZkPB`@@H@GaZk.WJ>G BG(bTGHZkC7"$,G BTG(b0HG HZkC B(bGtGTGHZkC$,0@0B4G8bA$H$AZkPBXbCL@GTGFZkGGG]]} (0#kG#G~^^~ (0޴8GGۤG $ G!?Hf"..! $$G?F%B$GԢDFFF"B0@?D@DFG `x"TGBb'@\ZkB&b"4GpZk@@A@`E@4G%"GE 8FTG G(BG0b4G{VZkG]]} (0ݤ8@#kG#G~^G8;Q"G_s"rBFӢ0 @F 0 @F0 @G0 @?$@@A1@G([4G0{VZkG] #kG#G~^^~ G[GGbZkG& @}@R"`.#2"R#JR"F.61BJF2/61B1K+F .61BJ F 61B}B,HR" D61BPB6@CO@`ZkN71B07@}B9##9." 9J9#%F%`x+F# .71B9"J؅F@xFy/71B`KDx Dy.71BqJ%Fx+F 71B}B_ .J9#؅FxF71B7@@"`.:BBuJ21BxkF`CC41@C6B21BCL@C41B BG(bG_Zk CPBCP@61B`Zk16@}B"$ G/w"W#7#K"G$ x G"W.61BSJEFxKF@.61BJإF`xF,61BHD x D 61B}B w.wJ"eF@xkF`61B6@Z#Gz/zKxKG@291B0 9@} C"# ,u"u#HD&x D$U.91 C#SJEFxKF@.91 CJF@xF5.91 C8J%Fx+F 91 C} C" .J؅F`xF91 C"?F@@"CC21BGG9@@ ".}" "J21 Cx F6BCC21 C6BCL@C41BGG B(b^Zk CG0B8bGTGxZkG]]} 0#kG#4G~^^~ (0GGGGxb#G_GG4Gxb#_H$G@BCP G@bZk8G<G7G @"99#7B&G9"&,v?&`Zk4VDxBGb2V@J$D@4$c  4vJB6! H1@6$64G<`ZkDDQ@`b#_XB4G`b`ZkDM@b# _G]]4G} (0@#k#4G~^^~ (G@[GH{G<y`Zk 0B4G<8b"LZk0BG8b4G$LZkc J@pb#D`_G]]} (0#kG# ~#^^~ (0޴8@H>PG_ C#GGGGp{#J_8$  E`G (BGD"! &DGaZk"$ղ ?'8B9#@bG8KC 4G`ZkXB `bC4GGGGqZk ()EBtGwH @H0AJBq0BQ1Bq0BQ0Bq0BQ?Bq0Bq0Bq1BQ0Bp0BJI@PBPBPBPB0PBBbbbZZk#i@b#k_G]]} (0ݤ8@H=P`#k#G~tG^^G0[G_Zk @G AF(aGGGEZkG]G] #kTX  (O`0ONPN :  Pp` p h @0@`O0`P   0@`PP @ 0 p 00 0@`P` ``@ "@ CMA$TIS_SHR@DECC$SHR@LIBOTS@SYS$PUBLIC_VECTORS$ MKISOFSDEC C V5.5-002`TRANSFER$BREAK$GOh read_rcfile N  N  N  N  ^ h h j  _       4  4husageh#     (pget_iso9660_timezone_offset                  ,@0h iso9660_date0o            d d P 0iso9660_file_length                     . " ' ( 'W ' ' / 3 3 3 : :P H    Ph`main    (        :ԁe   4        # % % % )1 - . . . 3  : 9 9  9 9 :  = = J G J L N N _) _ _ _ c84  8pe_mallocp0 i i i l o __main8 ! HASHDEC C V5.5-002add_hash] * * 5 5 5 5 < ?$, @@ find_hash@5 K J J J M Nxadd_directory_hash| \ W W W W W W W W W _ ` b$0 | find_directory_hash5 l k k k n o$(0 name_hash(    add_file_hash>         @`find_file_hash@&    \@delete_file_hashH       0xflush_file_hash>         $ " WRITEDEC C V5.5-002 set_721  4 X@`8 set_722` : @ set_723 @ xset_731 F F F set_732 M M M    get_733 ( T T T T T ` Ph set_733h  [ [ [ [ T!X!xfwriteX!# _ _ a0! W! "'@"h assign_directory_addresses@"6 | |    (l" #write_one_file(#p write_files(#P        ,\# $ H$0  compare_dirsH$m            $$% %%%$%8%@%@ sort_directory@%               $t% &!& generate_root_record&          # # $ $ & ' 0(h"H(assign_file_addressesH( ) ) 7 7 8 8 > B4 B H G H H L e f i m m q q u u u u u w    M M Q S W Y [ 3c 1h,|( <- #h- generate_one_directoryh-                      ~ MKISOFS.BCK4 [MKISOFS]MKISOFS.EXE_ALPHA;1*z              ( 1           L- g- t1X1H build_pathlist1/      1 (2H2  compare_pathsH2    T2222x!2p generate_path_tables2           $  $  # $ # * -0 - 2 2 3  > = = > @ C C C F G G H H( H H( G$ G I G G G I GK G 1 1 1 O O O O@3 P88 memcpy_max8* T T W T 8 8H8  iso_write8 [ [ [ [  c d h h h h s q o t o u u u u u v v { { ~                                          !  009 @! TREEDEC C V5.5-002@ stat_fix@T ? 9, 9 9 9 9 9 9ؼ 9 A8(B stat_filter(B4 D D D D L\B BxB lstat_filterB4 O O O O WB CxC@  sort_n_finishC Z Z Z Z h b i k l m1 t                             rC                                                       @pC C C M %Mpgenerate_reloc_directoryM , , , , 4 5 5 6 6 7 8 : : ? ? @ C B F E E K J K J K P Q Q Q S S T U T U Y Z Z _ \ \! \ ^ _0N 8RhR@increment_nlinkhR e k R S!0S`finish_cl_pl_entries0S\ s s | |   z (\S TTreaddir_add_filesT  T T@ Uscan_directory_treeU         !          &   ( ( ( ( _ ; : ? ? H1 a a k i k i j j j j j o o o q q  } }                                                                                                   2 $ ) ( )LlU b U U U 4dx)d generate_iso9660_directoriesd# 6 6 ; d de  dump_treee! B E F ,e xe$ EXCLUDEDEC C V5.5-002eexcludee:           e ff is_excludedf? "  "  "  &  &  )  ' f(g@g! ROCKDEC C V5.5-002Pg0 add_CE_entryPg + + + / . . . / / 0 0 1 3 2 5g h+hgenerate_rock_ridge_attributesh 8  8 8 A @ 8 8  A  @ @ P P P Q P R P R Q R Z Z( ` ` d c c ` d e g YԨ o p o p p p q q r s s s t t   t                                      BР           ؅                    F H H M M O M O NL\i h h |w)wpgenerate_rr_extension_recordw] V V ] _ a d g j x yt  VMSDEC C V5.5-002@y error_exit@y 0U 0U 0Uhy yhy VMS_parsey 7U 7U 7U 7U 9U 9U :U :U :U ?U :U >U @U @U- @U AU GU FUy  {({pvms_path_fixup({< OU OU TU YU YU$X{ ||8 VMS_readdir|b eU eU eU eU iU iU lU kU oU,| }p~ VMS_closedir~ {U {U0~ ~~pVMS_stat~ U U U U U U4 U U U U U U U U ~ `x open_file U U U U U U U U U U U U U UF U U U U U U U (@  close_file@8 U U U U U U$t ̅vms_write_one_filey U  U U U  U U U U U U U U U 4P ȇreadlinkȇ0 U U U U U $lJ) ](P!%$p$%$$## &0&##0%P$% %###p#@&P&&$&$%@$#@%P$$`$@]C0]J-`@"`! m "@"p!$u-@$ 0!$8%8%-$e0 a@ !.Pg 0T`"(A!l5o@y p"Z!*[MKISOFS]MKISOFS.HLP;1+,I.$/ 4B$- 0123KPWO%56]7;z^89*̞OGHJ81 mkisofs Create an ISO9660 filesystem, with optional Rock Ridge attributes. Format: mkisofs [-RrTvzafdDlL] [-V volid] [-i include-list] [-p preparer] [-P publisher] [-A application_id] [-x path] -o filename path 2 Parameter path - is the path of the directory tree to be copied into the ISO9660 filesystem. Specify this in OpenVMS directory format; relative directory specifications are allowed. 2 Options Command qualifiers are given in UNIX "-" format, and are case sensitive. Enclose uppercase option letters in "" on the command line. -a Include all files on the ISO9660 filesystem. Normally files that contain the characters '~' or '#' will not be included (these are typically backup files for editors under UNIX). Not applicable to OpenVMS. -A application_id Specifies a text string that will be written into the volume header. This should describe the application that will be on the disc. There is space on the disc for 128 characters of information. This parameter can also be set in the file .MKISOFSRC with APPI=id. If specified in both places, the command line version is used. -d Omit trailing period from files that do not have a period. This violates the ISO9660 standard, but it happens to work on many systems. Use with caution. Not an issue for OpenVMS. -D Do not use deep directory relocation, and instead just pack them in the way we see them. This violates the ISO9660 standard, but it works on many systems. Use with caution. Without this flag, directories more than six levels deep are relocated. -f Follow symbolic links when generating the filesystem. When this option is not in use, symbolic links will be entered using Rock Ridge if enabled, otherwise the file will be ignored. Not applicable to OpenVMS. -i include-list Use the specified file as a list of files to add to the directory tree. This is useful for quickly repacking a CD while adding files to it. The format of this file is path1/file=path2 where path1 is the directory in the ISO9660 file system where file should appear and path2 is where to find the file. This option is enabled by conditional compilation, and has not been tested for this OpenVMS release. -l Allow full 32 character filenames. Normally the ISO9660 filename will be in an 8.3 format which is compatible with MS-DOS, even though the ISO9660 standard allows filenames of up to 32 characters. If you use this option, the disc may be difficult to use on a MS-DOS system, but this comes in handy on some other systems (such as the Amiga). Use with caution. -L Allow filenames to begin with a period. Usually, a leading dot is replaced with an underscore in order to maintain MS-DOS compatibility. -N Omit version numbers from ISO9660 file names. This may violate the ISO9660 standard, but no one really uses the version numbers anyway (sez you!). Use with caution. Not recommended for OpenVMS, which supports version numbers. -o filename The name of the file to which the ISO9660 filesystem image should be written. This can be a disk file, a tape drive, or it can correspond directly to the device name of the optical disc writer (not recommended). Note that the output can also be a block special device for a regular disk drive, in which case the disk partition can be mounted and examined to ensure that the premastering was done correctly. On OpenVMS, the same effect is obtained by forcing the filesystem image file to be contiguous, and assigning it to a virtual disk device. This option is required on OpenVMS, where stdout is not compatible with the write operations to the disc image. -P publisher_id Specifies a text string that will be written into the volume header. This should describe the publisher of the CDROM, usually with a mailing address and phone number. There is space on the disc for 128 characters of information. This parameter can also be set in the file .MKISOFSRC with PUBL=id. If specified in both places, the command line version is used. -p preparer_id Specifies a text string that will be written into the volume header. This should describe the preparer of the CDROM, usually with a mailing address and phone number. There is space on the disc for 128 characters of information. This parameter can also be set in the file .MKISOFSRC with PREP=id. If specified in both places, the command line version is used. -R Generate SUSP and RR records using the Rock Ridge protocol to further describe the files on the ISO9660 filesystem. -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 CDROM will be mounted read-only in any case. If any of the special mode bits are set, clear them, because file locks are not useful on a read-only file system, and set-id bits are not desirable for uid 0 or gid 0. -T Generate a file TRANS.TBL in each directory on the CDROM, which can be used on non-Rock Ridge capable systems to help establish the correct file names. There is also information present in the file that indicates the major and minor numbers for block and character devices, and each symlink has the name of the link file given. Not useful on OpenVMS. -V volid Specifies the volume ID to be written into the master block. This parameter can also be set in the file .MKISOFSRC with VOLI=id. If specified in both places, the command line version is used. -v Verbose execution. -x path Exclude path from being written to CDROM. Path must be the complete pathname that results from concatenating the pathname given as command line argument and the path relative to this directory. Multiple paths may be excluded (up to 1000). Example: mkisofs -o cd -x /local/dir1 -x /local/dir2 /local -z Generate special SUSP records for transparently compressed files. This is only of use and interest for hosts that support transparent decompression. This is an experimental feature, and no hosts yet support this, but there are ALPHA patches for Linux that can make use of this feature. It is disabled under OpenVMS. 2 Description MKISOFS is effectively a pre-mastering program to generate the ISO9660 filesystem - it takes a snapshot of a given directory tree, and generates a binary image which will correspond to an ISO9660 filesystem when written to a block device. MKISOFS is also capable of generating the System Use Sharing Protocol records specified by the Rock Ridge Interchange Protocol. This is used to further describe the files in the ISO9660 filesystem to a UNIX host, and provides information such as longer filenames, uid/gid, POSIX permissions, and block and character devices. 3 UNIX_File_Renaming Each file written to the ISO9660 filesystem must have a filename in the 8.3 format (8 characters, period, 3 characters, all upper case), even if Rock Ridge is in use. This filename is used on systems that are not able to make use of the Rock Ridge extensions (such as MS-DOS), and each filename in each directory must be different from the other filenames in the same directory. MKISOFS generally tries to form correct names by forcing the UNIX filename to upper case and truncating as required, but often times this yields unsatisfactory results when there are cases where the truncated names are not all unique. MKISOFS assigns weightings to each filename, and if two names that are otherwise the same are found the name with the lower priority is renamed to have a 3 digit number as an extension (where the number is guaranteed to be unique). An example of this would be the files foo.bar and foo.bar.~1~ - the file foo.bar.~1~ would be written as FOO.000;1 and the file foo.bar would be written as FOO.BAR;1 3 Notes_on_CD_Writing Note that MKISOFS is not designed to communicate with the CD writer directly. Most writers have proprietary command sets which vary from one manufacturer to another, and you need a specialized tool to actually burn the disk. The CDWRITE utility that comes with MKISOFS is capable of communicating with Phillips drives (newer versions of CDWRITE should be available from Yggdrasil). Most writers come with some version of DOS software that allows a direct image copy of an ISO9660 image to the writer. The current version of CDWRITE is available from ftp://ftp.storm.net/pub/cdwrite-2.0beta1.tar.gz Also you should know that most CD writers are very particular about timing. Once you start to burn a disc, you cannot let their buffer empty before you are done, or you will end up with a corrupt disc. Thus it is critical that you be able to maintain an uninterrupted data stream to the writer for the entire time that the disc is being written. 2 Initialization_File MKISOFS looks for the .MKISOFSRC file, first in the current working directory, then in the user's home directory, and then in the directory in which the MKISOFS binary is stored. This file is assumed to contain a series of lines of the form "TAG=value", and in this way you can specify certain options. The case of the tag is not significant. Some fields in the volume header are not settable on the command line, but can be altered through this facility. Comments may be placed in this file, using lines which start with a hash (#) character. MKISOFS can also be reconfigured at compile time with defaults for many of these fields. See the source file DEFAULTS.H. 3 APPI The application identifier should describe the application that will be on the disc. There is space on the disc for 128 characters of information. May be overridden using the -A command line option. The default is an empty string. 3 COPY The copyright information, often the name of a file on the disc containing the copyright notice. There is space in the disc for 37 characters of information. The default is an empty string. 3 ABST The abstract information, often the name of a file on the disc containing an abstract. There is space in the disc for 37 characters of information. The default is an empty string. 3 BIBL The bibliographic information, often the name of a file on the disc containing a bibliography. There is space in the disc for 37 characters of information. The default is an empty string. 3 PREP This should describe the preparer of the CDROM, usually with a mailing address and phone number. There is space on the disc for 128 characters of information. May be overridden using the -p command line option. The default is an empty string. 3 PUBL This should describe the publisher of the CDROM, usually with a mailing address and phone number. There is space on the disc for 128 characters of information. May be overridden using the -P command line option. The default is an empty string. 3 SYSI The System Identifier. There is space on the disc for 32 characters of information. The default on OpenVMS is "DECVMS". 3 VOLI The Volume Identifier. There is space on the disc for 32 characters of information. May be overridden using the -V command line option. The default is "CDROM". 3 VOLS The Volume Set Name. There is space on the disc for 278 characters of information. The default is an empty string. OpenVMS support for ISO9660 volume sets requires that a CDROM be mounted with the /BIND=somename qualifier if the volume set name is either the same as the volume identifier, or the same as the volume set name of another volume already mounted, that has the same volume set sequence number. This is particularly noticable when attempting to mount multiple ISO9660 CDROMs, each of which has an empty volume set name. 2 Author MKISOFS is not based on the standard mk*fs tools for UNIX, because we must generate a complete copy of an existing filesystem on a disk in the ISO9660 filesystem. The name MKISOFS is probably a bit of a misnomer, since it not only creates the filesystem, but populates it as well. Eric Youngdale wrote both the Linux isofs9660 filesystem and the mkisofs utility, and is currently maintaining them. The copyright for the MKISOFS utility is held by Yggdrasil Computing, Incorporated. The modifications in this version for OpenVMS V7.0+ and DEC C V5.2+ are by George Watson . 2 Known_Bugs 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. I don't believe this applies on OpenVMS. There may be some other ones. Please, report them to the author. Problems with the OpenVMS version should be reported to George Watson first. 2 Future_Improvements Allow specification of multiple paths on the command line to be included in ISO9660 filesystem. Can be tricky - directory entries in the root directory need to be properly sorted. Allow specification of file placement in the disk image. This can be an important performance consideration for many applications. 2 Availability MKISOFS is available for anonymous ftp from tsx-11.mit.edu in /pub/linux/BETA/cdrom/mkisofs and many other mirror sites. With the 1.0 release, it is no longer considered to be in beta testing. Most of the bugs that are being discovered now are very minor (and interestingly enough also seem to be present in the YM software). Reports indicate that people are gearing up for production runs using version 1.00. The OpenVMS version is distributed on the DECUS VMSSIG tapes, and may be found at other VMS software sites. *[MKISOFS]MKISOFS.OLB_ALPHA;1+,2./ 4- 0123 KPWO56߀U'7b=89*̞OGHJ% Librarian A09-22fK^'`T=!D _xABSTRACTADD_DIRECTORY_HASH ADD_FILE_HASHADD_HASHALLOW_LEADING_DOTS ALL_FILESAPPIDASSIGN_DIRECTORY_ADDRESSESBIBLIO COMPARE_DIRS COMPARE_PATHS COPYRIGHTDELETE_FILE_HASHf DUMP_TREEEXCLUDEEXTENSION_RECORDEXTENSION_RECORD_EXTENTE_MALLOCFIND_DIRECTORY_HASHASHfFINISH_CL_PL_ENTRIESFLUSH_FILE_HASH FOLLOW_LINKSfFSTATBUFFULL_ISO9660_FILENAMES_TABLESINPATH_TABLE_SIZEPREPARER PUBLISHER RATIONALIZERCOPTfREADDIR_ADD_FILESREADLINK READ_RCFILEf RELOC_DIRROOTf ROOT_STATBUFRR_RELOCATION_DEPTHfSCAN_DIRECTORY_TREESET_721SET_722SET_723SET_731SET_732SET_733SORT_DIRECTORYf SORT_N_FINISHf STAT_FILTERfSTAT_FIXRESSIONUSAGE USE_ROCKRIDGEVERBOSE VOLSET_ID VOLUME_ID__MAINFIND_DIRECTORY_HASH FULL_ISO9660_FILENAMES GENERATE_TABLESMAIN PATH_TABLE_MSTAT_FIX__MAINSEXCLUDEHASHMKISOFSROCKfTREEVMSWRITE NEXT_EXTENT OMIT_PERIODOMIT_VERSION_NUMBER PATH_BLOCKS PATH_TABLE PATH_TABLE_L PATH_TABLE_MGET_733GET_ISO9660_TIMEZONE_OFFSETGOOF ISO9660_DATEISO9660_FILE_LENGTH ISO_WRITE IS_EXCLUDED LAST_EXTENTLAST_EXTENT_WRITTENf LSTAT_FILTERMAIN SYSTEM_IDTRANSPARENT_COMPRESSIONUSAGE USE_ROCKRIDGEVERBOSE VMS_CLOSEDIR VMS_PARSEVMS_PATH_FIXUP VMS_READDIRVMS_STATVMS_WRITE_ONE_FILE VOLSET_ID VOLUME_ID__MAINfGENERATE_ISO9660_DIRECTORIESGENERATE_ONE_DIRECTORYGENERATE_PATH_TABLESGENERATE_ROCK_RIDGE_ATTRIBUTESGENERATE_ROOT_RECORDGENERATE_RR_EXTENSION_RECORDGENERATE_TABLESFIND_FILE_HASH FIND_HASHfFINISH_CL_PL_ENTRIESFLUSH_FILE_HASH FOLLOW_LINKSfFSTATBUFFULL_ISO9660_FILENAMES ~ MKISOFS.BCK2 [MKISOFS]MKISOFS.OLB_ALPHA;1|  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK~ MKISOFS.BCK2 [MKISOFS]MKISOFS.OLB_ALPHA;14DKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklm8mnopqrstuvwxyz{|}~~ MKISOFS.BCK2 [MKISOFS]MKISOFS.OLB_ALPHA;1{|~ MKISOFS.BCK2 [MKISOFS]MKISOFS.OLB_ALPHA;1$1**V1.0CCMKISOFSV1.0 6-MAR-1997 22:21DEC C V5.5-002  $ABS$i$CODE$] $LITERAL$$LINK$($DATA$$BSS$ $READONLY_ADDR$ $READONLY$ROOT NEXT_EXTENT LAST_EXTENT PATH_TABLE_SIZE PATH_TABLE PATH_BLOCKS EXTENSION_RECORD(EXTENSION_RECORD_EXTENT  USE_ROCKRIDGEVERBOSE ALL_FILES  FOLLOW_LINKS RATIONALIZE GENERATE_TABLESPREPARER PUBLISHERAPPID COPYRIGHTBIBLIOABSTRACT VOLSET_ID VOLUME_ID SYSTEM_ID OMIT_PERIOD(TRANSPARENT_CXOMPRESSION OMIT_VERSION_NUMBER RR_RELOCATION_DEPTH(FULL_ISO9660_FILENAMES ALLOW_LEADING_DOTSPRCOPT  PATH_TABLE_L  PATH_TABLE_MGOOF CMA$TIS_ERRNO_GET_ADDRDECC$GA_STDERRDECC$GA_STDOUTDECC$GL_OPTINDDECC$GA_OPTARG DECC$GETOPT DECC$FCLOSEDECC$GXFPRINTF DECC$PERROR DECC$GXPRINTF DECC$FOPEN DECC$FGETS DECC$STRCAT DECC$STRCPY DECC$STRRCHR DECC$STRCMP DECC$STRLEN DECC$STRDUP DECC$EXIT DECC$GETENV DECC$SBRK DECC$MALLOC SORT_N_FINISH( (GOOF( ROOT RELOC_DIR0 NEXT_EXTENT0 LAST_EXTENT0 PATH_TABLE_SIZE0 PATH_TABLE0 PATH_BLOCKS0 & PATH_TABLE_L0 ' PATH_TABLE_M C ROOT_RECORD0) ROOT_RECORD0  USE_ROCKRIDGE0  RATIONALIZE0  FOLLOW_LINKS( VERBOSE0  ALL_FILES0 GENERATE_TABLES0  OMIT_PERIOD8 !OMIT_VERSION_NUMBER8 TRANSPARENT_COMPRESSION8 "RR_RELOCATION_DEPTH8 #FULL_ISO9660_FILENAMES SCAN_DIRECTORY_TREE DUMP_TREE(ASSIGN_DIRECTORY_ADDRESSES STAT_FILTER8J0 ISO9660_FILE_LENGTH ISO_WRITE GENERATE_PATH_TABLES GENERATE_ROOT_RECORD0Jh0 ISO9660_DATE ADD_DIRECTORY_HASH FINISH_CL_PL_ENTRIESSET_733(GENERATE_RR_EXTENSION_RECORD8 EXTENSION_RECORD8 EXTENSION_RECORD_EXTENT0 PREPARER0  PUBLISHER0  COPYRIGHT( BIBLIO0 ABSTRACT( APPID0  VOLSET_ID0  SYSTEM_ID0  VOLUME_ID0JpE_MALLOC DECC$ISALPHA DECC$ISLOWER DECC$TOUPPER DECC$$GA___CTYPET DECC$$GL___CTYPEADECC$__UTC_TIME DECC$__UTCTZ_LOCALTIME DECC$__UTCTZ_GMTIME VMS_PARSEEXCLUDE  DISCIMAGE 0* DISCIMAGE8 $ALLOW_LEADING_DOTS( %RCOPT0Jh READ_RCFILE(JhUSAGE@JpGET_ISO9660_TIMEZONE_OFFSET(J`MAIN(J__MAIN DECC$MAIN DECC$EXIT DECC$$SHELL_HANDLER =# "~8^@^HcG0[#CGC>C8{4G>޶@Zk(=0b#@ӰBbG4G@ZkcG8]@]HP#kG#~^> ^TG~޴ (0>8G [GGCC@ZkXBC`b1G@@ZkCCB@bG@Zk= (BC0b4GXD@Zk3hB0I@pb4G@ZkC, 8BG? @Zk8BGC@Zk@P@B@]"C@ZkxB"bCCTG@ZkXB `bC1G@TG@ZkC;BbG@Zk(BC0b4GXD@Zk.8BG G@Zk@@B$= C@ZkxBCbGTG@ZkCB0@C@ZkXB `bC1G@TG@ZkC BbG@Zk(BC0b4GXD@Zkb BU@bCtG@ZkGhBCpb?"GtG@Zk0@C.JF@8F`0@xFG@G#¦ .֢WJJVB֢J 1G&/F#bP:KB4GJ@Zk'(F" &.Q2J'JP0BPF f."B4GbPtJJ@Zk &,"Bb4GP0HJ@Zk.qHPJF>0@F.FJ_D B"bBCGG@ZkG,HD8D 0@DB B}"YBbCGG@Zk0@G,HD8DH.RHJH>.J.JXF 0`B/K XG0`BS/SK_.PJ>HC CBG @Zk !AGBG 4Gb@Zk= )CGGK?¤BG bC@ZkB=!(BC0b4G E@ZkBGb4G@ZkG]]}ݤ (0=8@#k#TG~^^~ G {G0[iC8{@Zk0BTG8b@"@Zk`Bhb4G4G@ZkG]]} 0#kG#C~4G@^H^PG0[G8{@Zk BC(b4G@ZkCC`GGq1"`2@B _PB4GXbq@ZkC$=" 1@@,} 1@ ",ݢGDVB vBXC]xCB@B8CVBXCvBxCVBXCVCB0B;CFG@]rOH]P`#vDJ CFk#4G~^^ ~(GX[GG`{>C@ZkCC."###"RCJsJSFC>D.4BwJVJ"F> GDC/{KZYK##[GC?GDC.sJ"RQJSFC>D.wJVJF> GDC/{9HXGZYKrPH[GC?GD#.Q0J2F#>]] }(0#kG`#~^ ^(~08@޴HPX>`^h~px޵G[>$BG GGdCG@ZkG?! G G GG.WJ>4GIGBE@G4G@Zk .x'H0@WJF>.PJ>4G6#.G#J BF@G@Zk.JxF0@ 4GF 0@A0@ 4GxF '.rJ0@4GQ'J2F'>0@G`"d.`JStJgJfB=gB`g/[gK`Gg?0@ 0A F0  0`A0@0٣A" G0@"1D.RTJGJQQB1P F $,$HL.s HRLJSFL>{.d"B4GbPJJ@Zk$,"Bb4GP0HJ@ZkFGyJE0A_/XKG?0@Y 0`AXG',GpGKA'H0D'<0@0@K/ݡ0d""yAD0AݱG@0@1D.RSJGJQQB1P F -I..rHQ.J2F.>-."B4GbPJJ@Zk-$ Bb4GPIJ@ZkóA0`0A G0@".VJJUBPF-I_,.r HQ,J2F,> 0A0@d.dJ, X@E+@.GJ/KG 0`@C/CK@OG@0`@#,#H?,0`@HD#.#J G.!J؏F c-0`@BKmIc.WBgIcJ B7fA? G%BGxJJ D @'/Y'K8G'?0@ }0`C }tGBp'H0@4GZtNJHD @ ,@HD<0A,DHD< PA g-KgIg=} Af@P7e@G] ](}08@ݤHPX=`]h}pxݥ#kG/$#BbPK4GJ@Zkx-$ Bb4G =( PIJ@Zkr#YB~^^~޴>^~GGGG {#_b#_BGbG CtG@Zk4@G G 1@"7@\@CkG0BTG`b@B@Zk@B"bC@Zk|0TG"@B@Zk@xB"BR"bC@Zkj0TGX"@B@Zk@fB"BR"bC@ZkXh 0 @ XGB?"2Sðb0BNpբ0BղI0CD0"ABz0`Cz<  0 @ 7" bQ0@BQ0B.0¦)0C$P"Y0@CYHb0@G"TG"BH1"bC@Zk 04GpBxb@ZkGb#_B4Gb4G@ZkBGbG CtG@Zk4@X?BGb4G@Zk¤C(BS@&tGB b2BB@Zkb#_Ӑ"b#!A$@_Bb4G4G@ZkBGb4G@ZkCb#_Bb4G4G@Zk @"B" (bCBG2"b`R"CC3cB@Zk BCbGTG@Zk=TGBbђ H@ZkB@BGTG @Zk@ B "(b@.GRQJ@>C@Zk4G@BHb $$@Zk4GB4Gb@Zk(b`B0" hb" CCC4V@W@GG@ZkC TGB8 bC@ZkB4Gb4G@Zkð? TG4G`b8@B@Hb HvH 0 B0F3 P"BQB%T@Zk)"TG *0@ !BF0tIxibSBTB@Zkt)_"x TG(B @b0@@ZkG B(b@ZkBbG@ZkBbG@ZkƠB4G b@Zk0B4G 8b@ZkBG'4Gb@ZkB  Cb2@GGtG@ZkEB!C3AJbG6aJ@ZkG]4G]}ݤ=]} #kG#4G~^^~ G0[G8{@ZkCP" ` B(b4G! C@ZkpBxb4G4G@ZkG]G]} 0#k4I$G\ DECC$MAIN4JDb# DECC$MAIN4IX@\ DECC$MAIN4lG DECC$EXIT4pb# DECC$EXIT4|@ DECC$EXIT4G DECC$STRCPY4@ DECC$STRCPY4G  DECC$FOPEN4b#h DECC$FOPEN4@  DECC$FOPEN<G(CMA$TIS_ERRNO_GET_ADDR<b#hCMA$TIS_ERRNO_GET_ADDR<$@(CMA$TIS_ERRNO_GET_ADDR40GL DECC$PERROR48b#h DECC$PERROR4H@L DECC$PERROR4PGd DECC$GETENV4 Xb#h DECC$GETENV4`@d DECC$GETENV4lG| DECC$STRLEN4x@| DECC$STRLEN4|G DECC$STRLEN4@ DECC$STRLEN4G DECC$STRCPY4@ DECC$STRCPY4!G DECC$STRCAT4"b#h DECC$STRCAT4!@ DECC$STRCAT4G DECC$FOPEN4b#h DECC$FOPEN4@ DECC$FOPEN<GCMA$TIS_ERRNO_GET_ADDR<b#hCMA$TIS_ERRNO_GET_ADDR<@CMA$TIS_ERRNO_GET_ADDR4G DECC$PERROR4b#h DECC$PERROR 4@ DECC$PERROR4 G4 DECC$STRLEN40@4 DECC$STRLEN4<GP DECC$STRCPY4L@P DECC$STRCPY4 PGh DECC$STRRCHR4Xb#h DECC$STRRCHR4 d@h DECC$STRRCHR4lG DECC$STRCPY4|@ DECC$STRCPY4G DECC$FOPEN4b#h DECC$FOPEN4@ DECC$FOPEN<GCMA$TIS_ERRNO_GET_ADDR<b#hCMA$TIS_ERRNO_GET_ADDR<@CMA$TIS_ERRNO_GET_ADDR4G DECC$PERROR4b#h DECC$PERROR4@ DECC$PERROR4GDECC$GXFPRINTF4b#hDECC$GXFPRINTF4@DECC$GXFPRINTF4 G DECC$FGETS4 b#h DECC$FGETS4 @ DECC$FGETS4(b#h DECC$ISALPHA4'G DECC$ISALPHA4'@ DECC$ISALPHA4G DECC$ISLOWER4b#h DECC$ISLOWER4 @ DECC$ISLOWER4#G4 DECC$TOUPPER4$ b#h DECC$TOUPPER4#0@4 DECC$TOUPPER4dGDECC$GXFPRINTF4pb#hDECC$GXFPRINTF4@DECC$GXFPRINTF4GDECC$GXFPRINTF4b#hDECC$GXFPRINTF4@DECC$GXFPRINTF4xG DECC$STRCMP4@ DECC$STRCMP4%G DECC$STRDUP4&b#h DECC$STRDUP4%@ DECC$STRDUP4GDECC$GXFPRINTF4b#hDECC$GXFPRINTF4@DECC$GXFPRINTF4G  DECC$PERROR4b#h DECC$PERROR4@  DECC$PERROR4 G4 DECC$FCLOSE4(b#h DECC$FCLOSE40@4 DECC$FCLOSE4GDECC$GXFPRINTF4b#DECC$GXFPRINTF4@DECC$GXFPRINTF4GDECC$GXFPRINTF4b#DECC$GXFPRINTF4@DECC$GXFPRINTF4G DECC$EXIT4b# DECC$EXIT4@ DECC$EXIT4G DECC$__UTC_TIME4b#pDECC$__UTC_TIME4@ DECC$__UTC_TIME< G4DECC$__UTCTZ_GMTIME<(b#pDECC$__UTCTZ_GMTIME<0@4DECC$__UTCTZ_GMTIME< `GtDECC$__UTCTZ_LOCALTIME< hb#pDECC$__UTCTZ_LOCALTIME< p@tDECC$__UTCTZ_LOCALTIME< PGlDECC$__UTCTZ_LOCALTIME< \b#hDECC$__UTCTZ_LOCALTIME< h@lDECC$__UTCTZ_LOCALTIME4 G DECC$STRCMP 4 @ DECC$STRCMP40 GD DECC$STRCMP4@ @D DECC$STRCMP4 G DECC$STRCMP4 @ DECC$STRCMP4 G DECC$ISLOWER4 b#0 DECC$ISLOWER4 @ DECC$ISLOWER4# G DECC$TOUPPER4$ b#0 DECC$TOUPPER4# @ DECC$TOUPPER4 G0 DECC$ISLOWER4 b#0 DECC$ISLOWER4, @0 DECC$ISLOWER4#< GT DECC$TOUPPER4$@ b#0 DECC$TOUPPER4#P @T DECC$TOUPPER4G DECC$ISLOWER4b#0 DECC$ISLOWER4@ DECC$ISLOWER4#G DECC$TOUPPER4$b#0 DECC$TOUPPER4#@ DECC$TOUPPER45PGp DECC$GETOPT46Xb#` DECC$GETOPT45l@p DECC$GETOPT4G DECC$STRLEN4@ DECC$STRLEN4GDECC$GXFPRINTF4b#`DECC$GXFPRINTF4@DECC$GXFPRINTF4G  DECC$STRLEN4@  DECC$STRLEN4G4DECC$GXFPRINTF4$b#`DECC$GXFPRINTF40@4DECC$GXFPRINTF4DGT DECC$STRLEN4P@T DECC$STRLEN4dG|DECC$GXFPRINTF4lb#`DECC$GXFPRINTF4x@|DECC$GXFPRINTF4GDECC$GXFPRINTF4b#`DECC$GXFPRINTF4@DECC$GXFPRINTF,3GEXCLUDE,4b#`EXCLUDE,3@EXCLUDE4G DECC$EXIT4b#` DECC$EXIT4@ DECC$EXIT45G DECC$GETOPT46b#` DECC$GETOPT45@ DECC$GETOPT47 G4 DECC$SBRK48(b#` DECC$SBRK470@4 DECC$SBRK4PGhDECC$GXFPRINTF4\b#`DECC$GXFPRINTF4d@hDECC$GXFPRINTF4G DECC$EXIT4b#` DECC$EXIT4@ DECC$EXIT4CG VMS_PARSE4Db#` VMS_PARSE4C@ VMS_PARSE4G DECC$EXIT4b#` DECC$EXIT4@ DECC$EXITD)G$GENERATE_RR_EXTENSION_RECORDD* b#`GENERATE_RR_EXTENSION_RECORDD) @$GENERATE_RR_EXTENSION_RECORD4+(G@ STAT_FILTER4,0b#` STAT_FILTER4+<@@ STAT_FILTER<AHG\ADD_DIRECTORY_HASH<BPb#`ADD_DIRECTORY_HASH<AX@\ADD_DIRECTORY_HASH 4`Gx DECC$STRLEN4t@x DECC$STRLEN<E|GSCAN_DIRECTORY_TREE<Fb#`SCAN_DIRECTORY_TREE<E@SCAN_DIRECTORY_TREE4GG SORT_N_FINISH4Hb#` SORT_N_FINISH4G@ SORT_N_FINISH4G DECC$EXIT4b#` DECC$EXIT4@ DECC$EXIT4G$ DECC$FOPEN4b#` DECC$FOPEN4 @$ DECC$FOPEN48GPDECC$GXFPRINTF4Db#`DECC$GXFPRINTF4L@PDECC$GXFPRINTF4PGd DECC$EXIT4Xb#` DECC$EXIT4`@d DECC$EXITD1GASSIGN_DIRECTORY_ADDRESSESD2b#`ASSIGN_DIRECTORY_ADDRESSESD1@ASSIGN_DIRECTORY_ADDRESSES,9G(SET_733,:b#`SET_733,9$@(SET_733,9<GTSET_733,:Db#`SET_733,9P@TSET_733<-`GtFINISH_CL_PL_ENTRIES<.lb#`FINISH_CL_PL_ENTRIES<-p@tFINISH_CL_PL_ENTRIES<?tGGENERATE_PATH_TABLES<@xb#`GENERATE_PATH_TABLES<?@GENERATE_PATH_TABLES<=GGENERATE_ROOT_RECORD<>b#`GENERATE_ROOT_RECORD<=@GENERATE_ROOT_RECORD4;G DUMP_TREE4<b#` DUMP_TREE4;@ DUMP_TREE4/G ISO_WRITE40b#` ISO_W ~ MKISOFS.BCK2 [MKISOFS]MKISOFS.OLB_ALPHA;1b|RITE4/@ ISO_WRITE47G DECC$SBRK48b#` DECC$SBRK47@ DECC$SBRK4GDECC$GXFPRINTF4b#`DECC$GXFPRINTF4@DECC$GXFPRINTF4G,DECC$GXFPRINTF4b#`DECC$GXFPRINTF4(@,DECC$GXFPRINTF4MG DECC$MALLOC4Nb# DECC$MALLOC4M@ DECC$MALLOC4KG DECC$GXPRINTF4Lb# DECC$GXPRINTF4K@ DECC$GXPRINTF4G DECC$EXIT4b# DECC$EXIT4@ DECC$EXIT =CDROM=DECVMS=PREP=PUBL =APPI(=COPY0=BIBL8=ABST@=VOLSH=VOLIP= SYSI X=mkisofs [-o outfile] [-R] [-V volid] [-v] [-a] [-T] [-l] [-d] [-V] [-D] [-L] [-p prep arer] [-P publisher] [ -A app_id ] [-z] [-x path -x path ...] path =0!%s:%d: field name "%s" unknown  =(%s:%d: equals sign required @= %s:%d: name required X=(%d extents written (%d Mb) x=H9Max brk space used %x Unable to open disc image file =PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER I DENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.H=`VTHE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS=@1Transparent compression not supported with VMS =0!Application-id string too long =(Publisher string too long  =(Preparer string too long <=P T|0h(=(i:o:V:RrfvaTp:P:x:dDlLNzA:H=Not enougth memory =0 h;=0 7DECC$GA_STDERR0DECC$GXFPRINTFX;=  Usage: ` DECC$EXIT=0@";=` DECC$__UTCTZ_GMTIME DECC$__UTC_TIME= DECC$__UTCTZ_LOCALTIME DECC$FGETS DECC$STRRCHR DECC$ISLOWER DECC$FCLOSE DECC$STRCMP=HOME(7DECC$$GA___CTYPET=r@ CMA$TIS_ERRNO_GET_ADDR  DECC$STRCPY7DECC$$GL___CTYPEA=0 ;=@ ; DECC$PERROR DECC$STRLEN%; DECC$FOPEN DECC$GETENV! DECC$STRCAT# DECC$TOUPPER% DECC$STRDUP= Using "%s"  ' DECC$ISALPHA(;=w@= ctx=binP= RRIP_1991A`()GENERATE_RR_EXTENSION_RECORD+ STAT_FILTER -FINISH_CL_PL_ENTRIES/ ISO_WRITE(1ASSIGN_DIRECTORY_ADDRESSES= rfm=fix ;3EXCLUDE;;5 DECC$GETOPT7 DECC$SBRK#;;;!;7 RELOC_DIR;; ;;;=0";=  ;7 DISCIMAGE7DECC$GA_OPTARG ;;;;;;;$;9SET_7337DECC$GL_OPTIND=%s "; ;7DECC$GA_STDOUT= mrs=20480; DUMP_TREE =GENERATE_ROOT_RECORD ?GENERATE_PATH_TABLES AADD_DIRECTORY_HASHC VMS_PARSE ESCAN_DIRECTORY_TREE= fop=ctgG SORT_N_FINISH=08";=P 7DECC$$SHELL_HANDLER=I DECC$MAIN=0"p;=0 K DECC$GXPRINTFM DECC$MALLOC=0" ;=  .X=..`=.DIR;1=0"0;=0 { {==mkisofs v1.05= .mkisofsrcX X66=$ $= $ $ = $ $ = $ $ = A A 6 6 $ $ = $ $= $ $= $ $= $ $= $ $= $ $= $ $= $ $= $ $= $ $= $ $= $ $= $ $= $ $= $ $= , ,4, ,4$ $= $ $ = $ $!= $ $"= $ $#= $ $$=  %4444 44(44044844@44H44P4466 $ $&= $ $'= $ $(= = ==-%$ MKISOFSDEC C V5.5-002? ?= `4=TRANSFER$BREAK$GOP P= 4h4= read_rcfile4= N  N  N  N  ^ h h j  _        4$ $= 4. .=  4=  = : := 44=  = h44= usageh4=,$#    $ $= 4: := 4=  = (4p4=)!get_iso9660_timezone_offset4=                 $ $= 4: := ,4= @ = 04h4= iso9660_date04=xpo            $ $= d4: := d 4= P =   404=!iso9660_file_length 4=jb                    . " ' ( 'W ' ' / 3 3 3 : :P H$ $=  4. .=   4=  = : := P4= h = 4`4= main4=;3    (        :ԁe   4        # % % % )1 - . . . 3  : 9 9  9 9 :  = = J G J L N N _) _ _ _ c8$ $=  44. .=  4=  = : := 84=  = p44=e_mallocp4=910 i i i l o$ $= 4: := 4= ` `= 44= __main84: := 4=  =  'ww \* WATSON MKISOFSt). WATSON WRITED3 WATSON TREEĝ5 WATSON HASHn7 WATSON ROCKE< WATSON VMS U= WATSON EXCLUDE1n.V1.0AAWRITEV1.0 6-MAR-1997 22:21DEC C V5.5-002@ @ $ABS$i"$CODE$ $LITERAL$$LINK$$DATA$$BSS$ $READONLY_ADDR$ $READONLY$ LAST_EXTENT_WRITTEN DECC$STRCPY DECC$STRRCHR DECC$STRCMP DECC$STRLEN DECC$STRERROR DECC$STRDUP DECC$FREE DECC$EXIT DECC$QSORTDECC$GA_STDERR DECC$FREAD DECC$FWRITE DECC$FCLOSEDECC$GXFPRINTFDECC$GXSPRINTF DECC$FOPENROOT LAST_EXTENTPATH_TABLE_SIZE PATH_TABLE PATH_BLOCKS PATH_TABLE_L PATH_TABLE_M ROOT_RECORDVERBOSE@Jx ASSIGN_DIRE CTORY_ADDRESSES0J ISO_WRITE8JGENERATE_PATH_TABLES(GENERATE_ISO9660_DIRECTORIES8JHGENERATE_ONE_DIRECTORY8JGENERATE_ROOT_RECORD ISO9660_DATEADD_HASH FIND_HASH(JGET_733(J0SET_723(J HSET_7330JP SORT_!DIRECTORY EXTENSION_RECORDPREPARER PUBLISHERAPPID VOLSET_ID SYSTEM_ID VOLUME_IDE_MALLOCDECC$__UTC_TIME DECC$__UTC_CTIME DECC$__UTCTZ_LOCALTIME CMA$TIS_ERRNO_GET_ADDR VMS_WRITE_ONE_FILE(JSET_721(JH@SET_722(JSET_731(Jx"SET_7328 LAST_EXTENT_WRITTEN0J@( COMPARE_DIRS0J0( COMPARE_PATHSOTS$MOVEOTS$ZEROOTS$FILL =P.?Fs0H0 JRPJ"SFP>F.v4JUJF>kGP.0 J?Fs0HRPJ"SFP>F.v4JUJF>kGP.?Fs0H"RPJv4HSFP>F.0 J s JUJ0 F>u!JFP.R@JSFP>GF.TJF#>kp.?Ft0H0 JSpJ"tFp>F.xHP J0 WJsJF>p JFP."v4JRAJSFP>GF,@HD<kp.?FP"t2HSrJ0 JtFp>F."xHP JWJ0 F>sJFP.p Jv0JRAJSFP>GF,@HD<k0,0",p"P.1H0.H"a1 H3JPJDqQ JDpqJDDkGP.?Fs0H"RPJw5HSFP>F.0 J sJVJ"F>wJFP.P J"p JR@J SFP>s HF.VJF>v4HFP."R@JSFP>$F.r7Jp"UJt3JF>F,@HD<GF0,A3H4D0<k#~^^~ (0޴8@GG! GGGG_0BG8bGGGG@ZkG "G@BGHbGP"@Zk`Bhb4G4G@ZkL$@`@G]]} (0ݤ8@P#kG#~^^~ (0G(G$HG (,#sJ0B2?JSF,#$C"SB2AJvAJ@#_" 3B2F1!Jv!J@4G b_cG%]]} (0@#kG#~^^~ (0޴8G GG.G?" G %b#1@&D4Gq_ %"("d0@FQ&HaBvH$FBѰ@BG %tGHb@Zk0B4G8b@Zk0BG4G8b@ZkG]]} (0ݤ8@#kG1B$B0,0H" q.qJ`.xgFJxFxF xgF`xFxgF`,P"1,#0B@HA8HH'H0 B @ @.J.4GJ &k k4GkGk k4Gk.J?B 5 BkG#G~^^~ (0GG0G q0@B`30@B?BP_Bb4GG@ZkCCG @P0@$"FTB%"%.VJ%>R_`BGhbG bGG@Zk 1@0@ @GG@ @ 0@1"Ѣ @18Qqz_Ѣ0 @ @1"e@@`BGhbG%4Gdc@ZkG]]} (0@#k#C~4G^^' ~(G`[Gh{@Zk0B8bC4G@Zk0bTG@?##.q#Hc"PJF>D.P`@XTJ>(2;_Pa@$CG5_ B=Pb@(bTG@Zk.TG# qHPJC"F>"Dc.c@4G4GSrJc>yJD.!C UJ>_ /GXKG ?GD!c/[bK!c?]] }(0#k#~^^~ (0޴8GG1G 'Gl$TGBpb1v J@ZkC@""Gb!B `DpBTbJ@R@Zk %Ѐ@(_%Ё@B1C@T@Zk?BT1D@@Zk:$0 HX D6 F%$F BBN@bTG@ZkB4Gb4G@ZkD(%Ѐ@_(%" 8bH$4G$E PCFGLD:@0B G@Zk$ Ё@@DGB1C@T4G@ZkzB1D@T@ZkuLĠBGbl@Zk¤C&  Gl$1v J1" XDeEGBG"\$C@Zk`BhbC4G@ZkG ¤Ѐ@%4GLD) E&%[_0BG8bH@ZkL? @B?"@DR HBb1K@vHGB@HDC31@@ZkƠ$$7 "BC@¤ab+@tG@ZktGBHD@b@ZktGBLD@b@ZkB4Gb4G@ZkF ¤Ѐ@&AB1C@T4G@Zk(#Ѐ@ _(à0B#GHİ$ C8bGL@Zk(#?"Ё@H$$@D$àb۠{#xD $@۰Ѐ@ 4G( __#G(xHd$ؠ8b@0*BDLİ@Zkà?"Ё@(&H$$@D_4GHb_cG]]} (0ݤ8@#kGp#"~4G^^ ~(08޴@HP>X^`~hpx޵G@[G$P H{GSBEFGG@ZkBCGG =@Zk"@B+HB F]CCG GvaIHb4G@ZkBC=G@ZkG-+@.w!HC ?#9E$ "BF@@9A%FDG3!I4C@M"@Zk$-x+?D4$@!!H !AO8!I 0 A@.PJ>xM|-YF6@} Ct 3`G."CJxF#X/x#[KHG@E5_B? ABEG:DG A1AICv!J=__#CZE9_X-X# IZIBA0AA CG@ZkE,"X!H H96C} CC"3!IBtMx-@! |M@Zkx͢ BA 6A !I 0 A@ /Y K ? G4Gt Bb@ZkBT 4Gb@ZkBGb4G@Zk~$CG"GbIF P"s"pBCxbG,@ZkG4GGG0b#!_BGb4G Ae@Zkc¤GP"GEpBp Cxb@Zk]G4GG0b#_}G4GB+aIbvaI Ae@ZkG]] }(08ݤ@HP=X]`}hpxݥ#k#~^^~ (GG`G _,4G$ b0vJABa_cG]]} (0#kGGG1 P,R,2v@J4vJ TBGk TB@4GGk0q`]$@dB@-ZkGkG#4G~^^~ (0޴8@H>P^X~`hGX;[G{!#w!HCG@ZkGB4Gb@ZkPBCGG@ZkDG ¤4GBG& @ZkBbP?@8b@Zk&BCGQ?@@Zkb#c G|_G&G0BG b@8b11 @@Zk#4G=@1"_qx H,6vJ7JFF,0A0 @ @1"?=@4G G_CG¦tGbICP"ZBC@b@ZkB4Gb.4G@Zkj'B"C+,QE+H2F b" C@BHbGGTG@Zk"B"BTG bC@ZkBb4G4G@Zk%%l!$ 0@DA.s!KPBRAJSFA>Bw4K.VJF>(*CC`_dC(*zC{_J%,Z@ @1v@K_j,{B1v`K_C8q C 8C P@ACw G[`ZE+"B+,@C+HZ.s:HRZJSFZ>.BJT-k!lJJTI LET=e"+,`C1H{.["z2HSrJzF{>k"D- @A/I."qIVJF>%+"K. @SJa/A#tZJ[zKtGa?D- @AI."sIVJF> B%K @"A/{TJZTK[GA? B$K B!q.uLI@SlJuFq> GE0B BK/TBKK-qRKLI E=d.tBJ.0BvJk!PJF>D#0A A 0 B*F A#0B4G8b@ZkbGCkB( SFb@C@ZkG]]} (0ݤ8@H=P]X}`hp#kGG [G0GG@Zk] @GGFGG@ZkGkG#4G~ ^(^0~8@H޴PX`>h^p~xG #[GG{C@Zkb#G_B "?"@ZkCXB# lU"0BC>G `b@ZkBC1I@@ZkC4G_"Gxb#0@_Ӡ@B"?"M"@Zk¤$ "B?" ?D@ZkB4 @$H/!60HL"/ HhB@KXBY7K2G"JG7J$$F @ $($@ZkGG8b#_ӠX1B@0$ 8$@$H$G@ZkGG8b#q_(@'Gb_@4G_@4G_@?"_"@)U_0b@;_;@_;@_ ;@_Ӑb"PBTGBИ@;@Zk(B"GG@Zk XBGG@ZkGG8b#<_ӈF"(BGG@Zk XBF CG@ZkGGG8b#*_Ӱ"(BGG@Zk XB CG@ZkGGG8b#_F"(BGG8@Zk XBF CG@ZkGGG8b#_(B"8GG@Zk 2XB CG@ZkGGG8b#_(B8"GG@Zk XB CG@ZkGGG8b#_(B"GG@Zk XB CG@ZkGGG8b#_(B5"4GG@Zk(BF"4GG@Zk(BW"4GG@Zkx${"(B?"h$G!?Hp$ ! x$@ZkPB5"]"4G@ZkPBF"]"4G = @ZkBPBW"ݦ4GR"@Zk@x$4G_"DhĶ?DDpGxxb#_B"?"@Zk$M"?#0@?D$!60HH.9&KL/3@4GJXK_"FJG6Jxb#F9@$_@&4G8BGxb#0 @& 2wHC_4GbGxb#2wH C_4GB@@ bG@ZkB4G b@ZkxBGbTG@Zk4G_"Gxb#w_F 0@AFbtGBk!GCb@ZkGb#_bBtG FCbHc!@ZkGBCTG  Eb @(c @ZkBCgGbG@Zkb¤tGB CFb@ZkB{@Ft4Gb@ZkBw@tGFb@ZkBs@ItGb@ZkG ](]G0}8@HݤPX`=h]p}x#k4G DECC$FWRITE4b# DECC$FWRITE4@ DECC$FWRITE4GDECC$GXFPRINTF4b#DECC$GXFPRINTF4@DECC$GXFPRINTF4G DECC$EXIT45b# DECC$EXIT4@ DECC$EXIT< GVMS_WRITE_ONE_FILE< b#VMS_WRITE_ONE_FILE< @VMS_WRITE_ONE_FILE4G DECC$FREE4b# DECC$FREE4@ DECC$FREE4G DECC$FREE4b#6 DECC$FREE4@ DECC$FREE4pGE_MALLOC4xb#PE_MALLOC4@E_MALLOC4%G DECC$QSORT4&b#P DECC$QSORT4%@ DECC$QSORT4tG DECC$FREE4|b#P DECC$FREE47@ DECC$FREE4GDECC$__UTC_TIME4b#DECC$__UTC_TIME4@DECC$__UTC_TIME<+G DECC$__UTCTZ_LOCALTIME<,b#DECC$__UTCTZ_LOCALTIME<+ @ DECC$__UTCTZ_LOCALTIME4)t G ISO9660_DATE4* b# ISO9660_DATE4) @8 ISO9660_DATE4p G FIND_HASH4x b# FIND_HASH4 @ FIND_HASH4 G DECC$GXFPRINTF4 b#DECC$GXFPRINTF4 @ DECC$GXFPRINTF4 G DECC$STRCMP4 @ DECC$STRCMP4 G DECC$STRCMP49 @ DECC$STRCMP4H G` DECC$GXFPRINTF4P b#DECC$GXFPRINTF4\ @` DECC$GXFPRINTF4` Gt DECC$EXIT4h b# DECC$EXIT4p @t DECC$EXIT4 b#ADD_HASH4 G ADD_HASH4 @ ADD_HASH:4 G DECC$STRCMP4 @ DECC$STRCMP4 G DECC$STRCMP4 @ DECC$STRCMP4 G4 E_MALLOC4( b#E_MALLOC 40 @4 E_MALLOC4 G DECC$STRCPY4 @ DECC$STRCPY4 G ; DECC$STRDUP4 b# DECC$STRDUP4 @ DECC$STRDUP4 G ADD_HASH4 b#ADD_HASH4 @ ADD_HASH4 GP DECC$GXFPRINTF4 b#DECC$GXFPRINTF4L @P DECC$GXFPRINTF4` G DECC$GXFPRINTF4t <b#DECC$GXFPRINTF4 @ DECC$GXFPRINTF4 G DECC$GXFPRINTF4 b#DECC$GXFPRINTF4 @ DECC$GXFPRINTF4 G DECC$GXFPRINTF4 b#DECC$GXFPRINTF4 @ DECC$GXFPRINTF4 G DECC$EXIT4 b# DECC$EXIT=4 @ DECC$EXIT4 G DECC$STRCMP4@ DECC$STRCMP4GDADD_HASH44b#ADD_HASH4@@DADD_HASH4b#ADD_HASH4GADD_HASH4@ADD_HASH4GE_M>ALLOC4b#E_MALLOC4@E_MALLOC4GOTS$ZERO4@OTS$ZERO4GE_MALLOC4b#E_MALLOC4@E_MALLOC4G0OTS$ZERO4,@0OTS$ZERO4 dG?OTS$MOVE4 @OTS$MOVE4 tGOTS$MOVE4 @OTS$MOVE4 GOTS$MOVE4 @OTS$MOVE4G, DECC$FREE4 b# DECC$FREE4(@, DECC$FREE4,G@ DECC$FREE4@8b# DECC$FREE4<@@ DECC$FREE4@GT DECC$FREE4Hb# DECC$FREE4P@T DECC$FREE4GDECC$GXFPRINTF4b#DECC$GXFPRINTF4@DECC$GXFPRINTF4G DECC$FREE4b# DECC$FREEA4@ DECC$FREE4GDECC$GXFPRINTF4b#DECC$GXFPRINTF4 @DECC$GXFPRINTF48GT DECC$FREE4@b# DECC$FREE4P@T DECC$FREE4G DECC$STRCMP4@ DECC$STRCMP4GBE_MALLOC4b#E_MALLOC4@E_MALLOC4G$E_MALLOC4b#E_MALLOC4 @$E_MALLOC4(G@OTS$ZERO 4<@@OTS$ZERO4PGdOTS$ZERO4`@dOTS$ZERO4dCG|E_MALLOC4hb#E_MALLOC4x@|E_MALLOC4GOTS$ZERO4@OTS$ZERO4%G DECC$QSORT4&b# DECC$QSORT4%@ DECC$QSORT4hGDECC$GXFPRINTF4xb#DECC$GXFPRINTF ~ MKISOFS.BCK2 [MKISOFS]MKISOFS.OLB_ALPHA;1LCD4|@DECC$GXFPRINTF4G DECC$EXIT4b# DECC$EXIT4@ DECC$EXIT4'G DECC$STRRCHR4(b# DECC$STRRCHR4'@ DECC$STRRCHR4GDECC$GXFPRINTF4b#DECC$GXFPRINTF4@DECEC$GXFPRINTF4G DECC$EXIT4b# DECC$EXIT4@ DECC$EXIT4G DECC$FREE4b# DECC$FREE4@ DECC$FREE4G0DECC$GXFPRINTF4b#DECC$GXFPRINTF4,@0DECC$GXFPRINTF4 xGF DECC$STRLEN4 @ DECC$STRLEN4 GOTS$MOVE4 @OTS$MOVE4GDECC$__UTC_TIME4b#DECC$__UTC_TIME4@DECC$__UTC_TIME40GDOTS$ZERO4@@DOTS$ZERO4!TGDECC$GXSPRINTF4"Gb#DECC$GXSPRINTF4!@DECC$GXSPRINTF4G DECC$STRCPY4@ DECC$STRCPY4GOTS$ZERO4@OTS$ZERO4GOTS$ZERO4@OTS$ZERO4 $Gd DECC$STRLEN4 `@d DECC$STRLENH4 xG DECC$STRLEN4 @ DECC$STRLEN4 0GHOTS$MOVE4 D@HOTS$MOVE4HG\OTS$FILL4X@\OTS$FILL4 `Gp DECC$STRLEN4 l@p DECC$STRLEN4GOTS$FILL4@IOTS$FILL4 G DECC$STRLEN4 @ DECC$STRLEN4GOTS$FILL4@OTS$FILL4 G DECC$STRLEN4 @ DECC$STRLEN4G,OTS$FILL4(@,OTS$FILL4 0GD DECC$STRLEN4 @J@D DECC$STRLEN4XGpOTS$FILL4l@pOTS$FILL4 tG DECC$STRLEN4 @ DECC$STRLEN4GOTS$FILL4@OTS$FILL` ` 4 G DECC$STRLEN4 @ DECC$STRLEN4GOTS$FILLK4@OTS$FILL4 G DECC$STRLEN4  @ DECC$STRLEN4$G8OTS$FILL44@8OTS$FILL48GLOTS$FILL4H@LOTS$FILL4LG`OTS$FILL4\@`OTS$FILL4hGOTSL$FILL4@OTS$FILL4 GOTS$MOVE4 @OTS$MOVE4 GOTS$MOVE4 @OTS$MOVE4 GOTS$MOVE4 @OTS$MOVE4 G OTS$ZERO4 @ OTS$ZERO4 GM! DECC$FREE4 b# DECC$FREE4!@! DECC$FREE4!G! DECC$FREE4!b# DECC$FREE4!@! DECC$FREED#!G B4 B H G H H L e f i m m q q u u u u u w    M M Q S W Y [ 3c 1h,$ $`= \ 4: := 4=    = #H44=$generate_one_directoryH4=                                    a( 1           L$ $= 4. .=  G4=  = : := T4= X = 4X4=build_pathlist4=80/      $ $= 4: := b4=  = (404= compare_paths(4=(     $ $= 44b b= `4t44= xK K= !44="generate_path_tables4=          c $  $  # $ # * -0 - 2 2 3  > = = > @ C C C F G G H H( H H( G$ G I G G G I GK G 1 1 1 O O O O@$ $= 4: := 04= d = p44= memcpy_maxp4=3+* T T W T $ $= 4: := 4= H = 44= iso_write4= [ [ [ [  c d h h h h s q o t oe u u u u u v v { { ~                                          !  0$ $= 4: := "4=  =  wwg1 B3V1.0@@TREEV1.0 6-MAR-1997 22:21DEC C V5.5-0028 8 $ABS$i$$CODE$ $LITERAL$$LINK$$DATA$$BSS$ $READONLY_ADDR$ $READONLY$8FSTATBUF 8 ROOT_STATBUF RELOC_DIR DECC$FREE DECC$EXIT DECC$STRCATh DECC$STRCHR DECC$STRCPY DECC$STRCMP DECC$STRLEN DECC$STRDUPDECC$__UTC_TIME CMA$TIS_ERRNO_GET_ADDR DECC$ACCESSDECC$GA_STDERRDECC$GXFPRINTFDECC$GXSPRINTF DECC$OPENDIR0J( SORT_N_FINISHROOT0 RELOC_DIRPATH_TABLE_SIZE USE_ROCKRIDGE RATIONALIZE FOLLOW_LINKSiVERBOSE ALL_FILESGENERATE_TABLES OMIT_VERSION_NUMBER RR_RELOCATION_DEPTH FULL_ISO9660_FILENAMES8J0SCAN_DIRECTORY_TREE0J$ DUMP_TREE0J`8 STAT_FILTER ISO9660_FILE_LENGTH@J`#GENERATE_ISO9660_DIRECTORIES GENERATE_ONE_DIRECTORY ISO9660_DATE ADD_DIRECTORY_HASH FIND_DI0ijRECTORY_HASHFLUSH_FILE_HASH DELETE_FILE_HASHFIND_FILE_HASH ADD_FILE_HASH8J@FINISH_CL_PL_ENTRIESGET_733SET_723SET_733SORT_DIRECTORY(GENERATE_ROCK_RIDGE_ATTRIBUTESE_MALLOC IS_EXCLUDEDVMS_PATH_FIXUP VMS_READDIR VMS_CLOSEDIRVMS_STAT0 FSTATBUF0 k ROOT_STATBUF0JSTAT_FIX0J( LSTAT_FILTER8JREADDIR_ADD_FILESOTS$ZEROOTS$MOVE = P. 0" p.$? #QJU qJS qJFF JRQJtJuFTF p>qG <F . "yHW JpG[aKW @yD% .0 Dp. "qFT JSpJ>p>4 D pFaHWJFWC P. p. p#?'[JQ {Jm9#FFS {J JR[JtJlqF p>TF P>kyGyG0HFF#TG~^^~ (G[G{G@ZkG"G! _G]G]} (0#k#TG~^^~ (G([G0{G@ZkG "G! _G]G]} (0#k@#4G~`^h^p~x޴>^~G #Gp[G&.& )%,GGx{JA HFC*C@Zk&E""" H X=).&e. 2HT Ju2HSrJFuFm)>&e> 7HD%%/z7H"/ HY 7KXK;GG%%?"?r HD!%..Q JPJ3FF!%>>GBb@Zk GB%!bC4G@Zk CB 'E B 1P@bTG@Zk@BHb4G4G@ZkBCC@Zk"! BC@Zkw@ 7J C`BGhbTG@ZkC.PJ> G_GCV@0@JU@BC`w#"#BbxFGCG@ZkBCb4G@Zk 0`A+ ?k! `bBtG TGbqB@Zk@BHb4G4G@ZkP4E@P nGBB@ )TɢMBcTCb޶@ZkB0]!C@Zk$'BDC?E1D$@Zkb0@0@sGD`xB0@DBCGD!GC@Zk7BGb4G@Zk"BCT'4E@ -BcGTb>@ZkB0]!C@Zk$)DBC?D2F$ @Zk0@0@GDxɢB)0@BD?GD1D C$A@ZkpBGxb4G@ZkpBxbG4G@Zk4J@B4Gb@Zk@ ") #E 0B1F@oT@Zk 0BTL@@ZkXB@Zk@p@BGb4GG@ZkC GG_'@_&R" BAX&e" #TGB Gb6DI$f! ~?%`$Ђ@1?J$PD&.).JU JFC@Zkl@B4GbTG'H l pDgE@Zk B(bЁ@GTG@ZkB4GbPB!Lİ A`d@ZkBGb4GT@ZkBCXGG@Zk@BCHbG4GtG@Zke4GB0E@C+v`IbC)iA%C GGpG@Zk c"(R`BdA1F@`"@Zk+ G0BAA0 HX D T @Zk 0BT C@ZkB0BYEÐ" 4GB!aD T @Zk8DǢ0BDzGD' 0 B'_E$K 0DA0@AXE_FtF$Kx+ YA0@AWEBtG_Ab ECBTK@Zk@B4GHb4G@Zk _ED0D kPBa@Xb4GG@ZkF C4@GDE0B.Xj1F@G*`T @Zk'0BL@T @Zk"XʢBDAbC.#0B\@RJGJ@ZkB` qXdC@Zk(BeAGG`]"@ZkBC4G G@ZkBX @b@ZkXjJ_DBGbGG"@Zk@B4GHb4G@Zk #!H  $? "DD@@@0D$#GD$#'B$D2@|xF.}@tɠ+G.�B@8bJxF/K4GG@Zk"?"_"D @0@ @DGDc`B0@"."JJ%@}@@)?G`]h]p}xݤ=]r}#kG#C~4G^^ ~(08޴@HG@[GH{@ZkpBxbG4G@ZkbCG!"@4G4G @?`BbpeG@ @ZkBE@4Gb@Zk4G#B(@ZkpBxbG@ZkCGG1"BC4G B?DBb  @ZkT$&B"bTG `0P2_JR"Pd sPbB=@ZkĠGB6JbTG Ơl&@!?H! l&p&4G@Zkàs4GBtG b@Zk¤mA?&"B"BTGGCbC 0vJBC E@GG@ZkpBGxb4G@ZkC" CGG3aB R"B4Gb@ZkB" bCTG4GtG =@ZkBmA?&Bb"`" TG&Gb 0vJBC CCCGG@ZkpBGxb4G@ZkC0Z@ GGG3aB R"B4Gbt@ZkB0Z@bGT4GtG@ZkCGB mA?&`b"cTGBCbG c Ơ 0vJBCC Ҳ1Z@GG@ZkG]] }(08ݤ@HP#kG#~^^~ GG|0t0 G,q"H DQ.SJKF @Q.q""SJTJ! @2B? 0B q 8bC4G@Zk BC(b0@TG@ZkG]]} 0#kG#~^^~ (0G{G# !!8 EDF@uF¦TG`B"bC@Zk B(b4G4G@Zk %"BTGb!t!|`d0B(3B@Zkd$B_"bTGt!|0B(%B@Zk`pb#%_eb#c|_G eb#t_G]]} (0@#kG#G~4G^G [({@ZkG] #kG#4G~ ^ ^ ~ ޴  > ^ ~ ޵ G[G{GG@Zk@BCHbG4G@ZkCvxCpBxb4G@ZkC`""G BtG`1"(bC@Zk Bb4GDx@ZkGG BG`4G(b@Zk CBGb)G)G )4GC@ZkC G$(%AF %) 8G4G i! 0֢8G?6 %(G htG`" B`C(b @1"C@ZkBb4G4G@Zk 0B ( ( Q@1q`G1 G@pwBx4Gxb@ZkC8" 0@ABG!GbTG @ZkBbGtGTG@ZkpBG?"@ZkpBGG@Zk @P@@`bTGB B s"(bC@ZkBb4G4G@Zk0BCGTG@ZkBbCG@ZkPBCXb4G@Zk h"1P@tG!?B B(bC@ZkCC0b#V_ GCCb#o_BP" C EG@ZkB@]"4G@ZkŢB"C6EG@Zk @"B4GG@ZkB"G4G@Zk=% ¥!R Kx%.,G!-G C`6 h¦H&D"֢Z="8J H]}.KZ].:vJGS qJ]}>{SJRQJGZ]> D6J@[GH G `BtG B#C(bC@ZkN`bC¥tG Bk!C(b@ZkCGO HBP"CRHG D F@ZkDB"CG@Zk>@TGB@bђJ@Zk(h"tG`B! B"(b CC@ZkH?&D=1"Z}.Z]"0H].!?HJT J]>FSrJ6vHZ}>wSJG! D=6DJ@]FHyG@]"@=@]"4G֒@KBTG@ZkBbGG@ZkP" BCG@ZkB"CG@Zk HTG@BRJ@bђKF"@ZkGh=`RHBP H B D(b 8F F3%HX"gJCC@Zk%pB!xbRHC DDGTG@Zk G`"CGB ! Cb@Zk BG`G(bGG@ZkGΡP" CBG,"RHTG D &@Zk$BCG@Zk@B@bђJ@Zkz@ݥ"C`"G BԒI@}(b>B@ZkBb4G4G@Zk@ݥTGB@bђI@Zkݥ?&1"`RI B(btGE E E E N" @n"`!BC@ZkN ``¥C BtG!(bC@ZkB BG(b4G@Zk C ɡGB4Gb˱ GX G@ZkBbCT 4G@Zk\ `+f]" TGBb0J +bA1?J+f}.i.rJT JtFC@Zk+¤""BC!v H+G6KAD G@ZklTG7{J"lp @=l 1&K2J$J2Fl @}pkdApB4GxbTG@ZkHBGbGRHtG D@"C@ZkGt+xZ="|TGHZ].]}.RJQJB Fb"S qJaASFC@Zk?$Z}.! ].RHZ]" D  D D " " rJT JtFLKL = 8K# BP"#CG@ZknB!CG@ZkhH=b#(R H,D! _ 颷B\0_ BG(b4G@Zk CGmGGq2ABm!|1"_q4GBX. ɢbT@ZkT&_&hR"PBC !4GXbG.G PN iGdnCC@ZkƠC0bGTG`ΰ_`.HݤZ="HaABTG&Hb vHHG&HDH]}.Z].S qJ]}>RQJZ]>G@ZkLˠ&H˰l H l "P""BC"!` ! T @ZkBT C@Zk=#CCRK G#TKÀ!TKC1N@BtGb@ZkB!bC4G@ZkX P" HCBG"RITG E!@Zk}BCG@Zk 0bCGc_ݤ-H,vHI EaSIE=h¦P"%EBV1E@ T C@ZkD֢!CPBXbCCGGGG@ZkGB4Gxb@ZkGb#_4GG ] ] } ݤ  = ] } ݥ #k#~^^~ (GGGG0BG8bGTG@ZkG bTG_G]]} (0#k#~^^~ (GG G@BE@G$~c(CHb@Zk8b4G_cG]]} (0#k43\GpVMS_STAT44db#`VMS_STAT43l@pVMS_STAT43GVMS_STAT44b#(VMS_STAT43@VMS_STAT4tGDECC$__UTC_TIME4b#DECC$__UTC_TIME4@DECC$__UTC_TIME4'XGdFLUSH_FILE_HASH4(\b#FLUSH_FILE_HASH4'`@dFLUSH_FILE_HASH4pGFIND_FILE_HASH4xb#FIND_FILE_HASH4@FIND_FILE_HASH4GDECC$GXFPRINTF4b#DECC$GXFPRINTF4@DECC$GXFPRINTF4!G DECC$EXIT4"b# DECC$EXIT4!@ DECC$EXIT4G DECC$STRCPY4@ DECC$STRCPY4G DECC$STRLEN4@ DECC$STRLEN4G DECC$STRCHR4b# DECC$STRCHR4@ DECC$STRCHR4%dGDECC$GXSPRINTF4&hb#DECC$GXSPRINTF4%|@DECC$GXSPRINTF4GFIND_FILE_HASH4b#FIND_FILE_HASH4@FIND_FILE_HASH4GDECC$GXFPRINTF4b#DECC$GXFPRINTF4@DECC$GXFPRINTF4!G 3 [MKISOFS]MKISOFS.8;1`ۜdAonݿs9<_W%q0|r`MѩvevGS-W1DOJ4K'Z;kO*#P̡D=kz@mE0zK珟_{[JkLZ_)0EA<Hוb_Qg:<wA]q6lxEi-=ޘo)ޯOfe(i]v\LjojetQ(O. ;iNCM,7|#z .p}zGQ='-O#Tx z?_ {6mKMp\ VRz5Iu,> LrfZ@AR?R &}/Փ9oh~T9bM`;㳫uJD1N)Svg=/K}h9Dۍ(vqEPA; Niv-zw9eAk2lnW2+HWz4<*ley <9?)"qn$}e!URJ \2 SVCMPV($VZ],z*:%{uL\MrHw6-;BBo`Bf~jO,HIJfZP^"Pb&A\h-]|P Xޑ]yB 3.UCKN 0pfUGHtm0 |:C%.ZEiϊF$=ioTE=nyh/9SHwl“gF־"!&v6_dԎ+XyRШ3p|?4c DQN߿Ny-Wul 'HWm!m'6Ưi: 'Ǚa1g6`48םRG/G ݿk[Ӻ@\/=9 >tM"yy s@vdzbD:Pb?V]iچQjys#nz {I^jIo9>A"0:8\ΟIJLcPç!yN ~pB"Iӿ;d|# >JQݍ Qc~u4f)2Kg?xNU*߿T|:OŔۤ:;jľ5"ޖ7~cwCgf$nIhAFV=$=o&b2*\y g_HKoo.{Q^uz ECI5T̩y`ܖz>N/["Ǧ4ǥ ,jpLOxIi5%F=Ԇr_1Q7@,o9i 1xMrv:#W6QB8~.dON'A!>d}e$R 6taid/[]PMR@+N hZhAOj R\F JQ}e$(Q)CDa#qa\#|#+AMwXd :q#Z·)j8ػ*^/sʜOR"of}7>މAZo4a+.o 6"0WaoH[s<'~n<~4~*$=W ITʟ|ȍR~UoyqC=50/жY/닭Ɵb%XF7qދz(ęы{zw1g!oq}^{˰'89xҁu j+qLpkb S8w|tΚwj,a}%iGW0l7ֱd-RK_BOʡۓyNJrJHD%lVK8S%-Udp,`OHz }9&?-E K=" )CUTxA u ZkxtbL@_@[HwRh= pQHdE)f?.0@|w3Ya298eUSZJmhY(Lfݔj: sj)i7b2vP fКlӼ0ta;w[^d/fV1NreWu(iNWHLRn=e̙l=ζֆhcJ2~%6|&l 5ihH'95䒧> k/cj.ۛ@ӟrJ"فطcݵG;NPf(0k!'eDu'p/^>c!Jdh6r<Ae?9*>Nr^gKݖ4deg:m"[΃\nj `di{ѣ%K,2aVO%$$oI, (O|c^M+$}U4>'̹#ikà$aZ G4>! 鷝/|;6q5ߔƚ}~WwvƟ*>koFM%wCY) =g/I_'*nnr?mjd'U/o"VHMK..gBmnYx;`}}-&lFؠ2dUL9d!}bQ0;k\q 0 vGyg <>O04ݭ{1{C6v pE*,7/k'w/N'FlMTPn:c>lxlƪZ@)ak3PmОUVcyb{>o6@Y )(e@`: y (zv$ .@`}p>za9fMBu)uWp9EGz+3 zj6aI@5rt}E8]1V4v7T.|2 @8wk/^4m9FHVs,a ?g,~ZS2ADGV(2>H][xmK;D&;i'#:: j񆈃'Za ~idw?NN$1,&MrԿfBOA|kKvi]=8;Y+fSs1Haq;$>G`,vgn)ӑdf,4̰nUTOlT( 1@!E1t~}ah@4 z鄔r-wdjai_I'Vx4cqbbr)0`q'W~Vǭ|ƢlCak 3t7xtSnbeu P0܄s/w`%7yaC}uZă'&Vz,m?攚SJhɶƘ2O|qTƌ Y6)(K(lt3+ت̻IPXrk̫GĐ߈faHG`:Z֝W=u=wzt.vS;`&igjl):s |B!e8h50J3q vn.:-/( Y^oN@2igjQNǯ'b>eQEn?G9l[a.}Ԩ`*c 9{4j9|QGp?(i<^^9/Y7w*/_N l诶@&|"}E]dsc-4p8xن:E Hzyi]c$xL}2<c Lki@_Ǫ^-wzgG:/vsFzApuEZԁGh`5L49cp?&r=gK/zbYSѤ^L'To(@G{ Ma$h K{aۑ;JW3f/06/v"Vc.F?\Vr5~ݲswDq5>I(׸:C S(\ u)6+5Igr${X:h?hƳHjx}Jiɖ|%L6v̻ۧ25YaVCn"?,H;ղ@7=y~lѕ(hF4iYUW+3q'?]. Eщ"g3u@mxARHh]9i8݅.`w0\6 .ԍz^#*=u>;zM[aA2G1Lf+Oy[n:N^kأ;epl%"f"t[oM D e|C^( m¢c6J50d:},B*ZBS/kذ":h܁|o+N+o(G{($ hXDz(s5ľy6qf;ha e% s{(4.(72h1#p{0Dd-Dx{[#f$O׫TCX6 7lv%TTm\(tH*)8h;ckZI/-zklSxHC pPV Ts7 朑,6ꤒ5ˊI&ZFƜl->,TnllVc(R0Wp4Hɫ,Hm`2n>3⋪UZ(/q,9YE;rèc+L2Ic8θ&->#By,yo!:73oTyw,duK`bӨe҄U1oZ4xd^eR)p+_5ݶC^<)]P95m3.I*x9#)*c*49}PdIT,sJ}E}(It*Ujs#ҋASkg5*HbNogSI}]6 4+?mY[I XE'Z^H4_*/mgzE8|`vCo@BNL]BT]&GKq Y }BeI$c((W0v_ Kn)`3O>B+Wjl<[f_eI _k`z S&t)/\o5M1ث~ t`5BgA1n5?K5LVI{> rnA)c!e^-~%ዑSxtieAA!Eq"e [Z<N4ڟ\9Q;O&=^xzoxN`Por?~s1Z rUNڿX~vBDdQUhivQ-+k/\as7B{X@'AՓk|LS[EOJqqGNfpDƕhóKYna@zcٴ e@@* ֯i@D-(۰*met$ƒFDX)Dg$f9N(Hf#:RǏ3s\)%o3IGQVeK,u@>#UjVeӢpRz@`w.U3 ,` HvAO^_ ܐ^^LE044,TTLvRGJmO<.Snl?}InmE~;ma)>n DABߍ")"e'8\g9K@3O;;&c+"Q 'l=eofo7uJmi)@Q- 5nWf3Sgd rk({c}"Nja\~ZK _'>:bR f': ,{Ti^~Eo7w4eP]Xl4ލD84n٭E2#fbS!!O nm:in>?Vؕ~Su6@_1(lOr1c aWb(RЁ5i0I־ػ8٢'#+)#h2XTUQHXFL$,XqY6]2:ujWTu\W+-C0^^Ykf4#*FYT0Y=j\"*M}K%$Qijolup:|#> O& BO7Z%9#S,@1Jh1>@IQ*6)!nuֻTG{k(i d|) JtjKP#TF疉";P%…ylbh!K3%Msq^C)lF|5"o [8:FGH?kqk3q-`6jG7Qf)uhdi%iWĸo8"_~ZQ!Lhb|#5d%efCd1y\;bɃj5-u=|Ør~X8,pME6K)O }3='|E 9QIBI=;Dc<nA=(fXPb]0sD[N XDXCWi>_4WF\W>1`]k)JUST :r#rqms^V `WTqB9Yix_VnknYRkToy )R/Fۃ2P[ۏ{vc,Ӯ^!l;0shu&q]"^_2I Hos4" XtȺж? )\GF.d1Y `pSM?r]qy#yj6g-}A'YFkUnK vVeqQC5iҲO_ x"YvF~eb ](TiEeп`tI4Ly9rg#)UVb 'b/a =e518ABS =ѣ0bB[ۧ/T\'r_Ӛ$ XZ(FP _W:ɠQNOa(Wҿ%D*ow%m5НX@%$QZp$b MVUf?bsy-E0fқۨGAd:-=[+-tS 0XI+bAb_C<Fi8M W7\_eb9R +c= Jj!n\gynʶH@W[P XR޳zS{jkapNHFIsh0wk#;*`vh0(kP;*v@|0"f94N"EöB&WG}eWi6O%OgCs[(v,;+H<O_5gzJg[.O@g8U ҟM"$c]Mc̨`c`7Y8D ΦnjS"F^ `8!L&4qtPR#NGY H Q%z]¼EH Bܞ:hMTԷϤ Hm86SF8ۡuucpZ`.Ku&m 1eXA"6,%F F6[T[4je6O<&1:{cSQGf:&E"xMj9Ks:'G+ip|qvBoθhCPuqr <;ъx*;%7am,P/>/urӌ?< ū޿,tpw1 *{єľݭ" |Rוg>.&!9 ]۔ޚ@ tnQJYf^b5ZO][o=jYp"g/\mc^^ ]WdspuhNST;B7v!93l>'fK\RS0XLZD7m>GMoV Obuoc=u_DO8vIyKaqg 9Y5< >A%nQ{`\m^ğMKQ7Xƒ!:wNwQ:*W e"+|H\wri (Wd@t=VMuFZ+A~nk)IXZ;G)YAiO@_`PgJuIvf0 M"Nzf6ʬD ET 0s߀&u`p<YH *M˰Rm 8Nt~H@]MV!_>uLHnQ P몬C D$O;P[Tv6' {@^cL[0Oj[Y QfEBJ" V@_;C)DksU&817p ^_rO|:ҰAFXCß _ IlIY2xYV@Rbh[<9f Z0 #X&XuD^Yz 5= IcND`y6pxmGz_ " PTCWN3?5VZGIsP{Rgva6LvSYwzTz/e 1"ksqB#kpg`G[pVd iK Z QH}:Df4rP{ϧp>G,uQ*8}RkXP昭T bUSnMy6![Iut~@a$qDٳVV\E/ #g| -V;ݔުuG|Uh 0c&hWJPO Xlؠ^YQ2e!'2U[SA-dMP [?:0UXv_O|5C2R@\>O&+(gKboPh7V^ u:qm}X4Dx[Sf4cRAN Ft}q=Jt{V^f % AUӭ DR$_aj]xf^!~(qoGpm]ù8wUIxrо~U@$#<;E- C9s4}]SdNwN!.FEu-JIE`a9c$ǦL2%"uSƾ !NzTLM>o?OB'k4moXrLI [Re5qQFs@(87W] _DME4nC~[:cN.M*Lo6LGulhR}v^hXyU]h@n@.u}5 A\ZGE JwR/@Xix\rBT[NgjZ \^UCKk\O,PV#*JcsZSF%SNSXWp6mV2lh @/.]l[@E1aU[aR WVT=gABbSJ*Q&w IZy_ N a W\6O"7&Fs7rN]:ꫝC4[Υa_E+|xsRBI[\8ƩmlC\WS1̵xe4( @hkqwj+1Y~G姦\NZ)ޡ.K 5i@Yz:9lI4/ ;)h WHA|#T(Mu }C}Q(tϏx'w|l0FyA` F:+DRt۟KB'$#fz孰D`xZIM#w$Ҟ ^FM+3W+ *dqO_ 7 pcj 8d"柧`[Ⱥd5:?Rw?F2y&U 6HG/M!AWz|يεHtqv3/Q G}2FZ4?\( B읎JES佻wOEU]-=/z?fT5Z$P$Tw  GH\ª${#TO&1EWf2ا^ R*Esf: Lr_+`l ?u m$ aWLE4j C:.iX趗SK/\ɰ{ws^dž鶭X $D!'Pv#<՜_YVbQu BP{rSvs =6џ^O Ueߣ B 2 :B%oq pf=rș*~,jTXRP%f 9nV?@M` u RhF& !C/eTWR[]X)H\ ? 49?F> % $R*pIsJ\`S\8R۱(ElG"_SR&*vߜF? Z:ǡk*b+re@uk0c'x(ax{-ø5#h#{ 16_;s+mPe.wC q^˒{o E1L#_็ᶷMFYQZg~ < W`|t qhAbZdƫAFwcb F?gen^ .aD8cgP nzHngBea$AnraJ"fxDb-̏'qH7c{gS, xLXQyT ־c[˙eq 9}s:KJ3<A9n/aZN:`!bZyv#iz{ *qȯEXIc؟z}0kk{Ki0\"""d&!a|n sx\r7(xj OGq9lA;= Gb=:yqY\3eϞp`" AgPj`BEtJ `J!SG.]E){ S" C549#mOJY6mOOȮ,_db=N ׷+/i<ʪFBiT2瞤5-FXѝv|2$/&߈Ea kk} ߰h˶29v ÛxY7o + E"GDr7pƛ(ybU;,*906NTr" a35k~'.*%crCq+)vi\~ RCy)T|S15T`Z/Y .ʙ -Hij6uxI 5 _.'s;S MhX 8Wӭ{pdk®fvYQJ޹hc+,&D^vVx2C2p17Me#5#0q;H !dAê2qc0]͸78*¢r>FVS ָWT[HK4E1d+_g&0$1oÐٰ|xRe?dQ,B zoAJ1,NR=son8A,JDpJb=/`5 A~ #@BdY['TX =" (G4mܢ&|G)Mh-c|_1UڒaӅ,L=MNʨ %8{-ԟOW҉Ro2Eu0@7K9/F PTR^[E,ujZI >ڲD{{:Ċ#J@cC M#69o^v6n$gfm E?UuAUܘʲ@AR)L:CjK{ -λ__u0{NtH C7@Q:dbSQW^ E޿7ԱT-|DO*(;=?X$6(byJ7Df_L%WcRw6q ^ u@N36U=2Gr/6xTtIEd[ ELʂWwB^/DsPr05fLVO6I\\ %:tTAJ:A<mIQ&sPA, Sw9 'є؈soV7yFeC>%?O| Kb/n-0\iwf`w񘓥0/?` /Eɹ#@gM 8L&r 8OJ@d^Aih<OBKc6JLš)ѷv!:Tip0PbS st=mNQBTqpP ϐV3c 3[SI JVI ĂE`%d)K1`pX_NEu Jl_*e+sT֨ zFWd)-9jB爯Pvߧh f'iߕBUpNWrT[TCW44I7$FDDU(^&X"+ ,F*n$MfcL=1QBa mb 7Y-sUJKmcyhKy>g1!4ɾC~ڮ[ VuhvKOtoe*kl޵ q6*;)lA=ҷ_&ܡNAl4Ow &g؋KzU_^= yB׳0&1 ["J[~HH]l,a׋j'it˱H_u΢~*/2& `gY6;>CHe,ltMSw. n/)e%'K22S{shql$UedA'wVJwa*kFk'g]QA -dr)Tw)6ˀ |~'|mϿL_JVfŚ{۔ksg?O\qr5-I,WOpna)%\ȼ>8\JJ$aRX ruX`V+Fi7ʘ\(>P8#Bs\p2R.yֶ$FTL*W+]*vZpr?.-2-`ye=?.VڑmքUlrgv+Jt?&Vt@cq9MNH2!+.sEi(/OMss>;-P):;NȀ?P (e4$3zq4Im=in0e2aBD[a.策)hsxH|ԁفfq$%|k'{g'#6P?YeLUtFt1`[- #ؐ(b._4;.e+fo%9F6G/L/29fLqx=3Zj {/."xÃQ~*ɠd9ҶIEB(Vi@O*êvz|f#w;Om:wEvGM|Xޠ$Js0S#זsW-`A)cC<)2PiV} IJ6=b-W g~ b6_2R*P 敀*es[]I'V;ރ~hu@XQO] ǒIl} yI= EG2F%%'ZO1zi;/zY[cCi~DF-KZj.69RdnaD^ dc5CzZ j!FXY߁\>ȌEwX$UTk(h)x} %t;gX6fO̷20K0(ldW$%kR Pvwnc-C HrHֳ8RhpQ#Cg mNG$;Ag&X.ֽ뗯6A6KWQGs)qhxEh?DQh uF3|y\.-\N6>z.k,= B ,&#sܬD5$9CRVO$X]kvp𕁯ƆJzk>H-޾3~A/\Xo;U Wv鿽qOM !> < G$+ ۖK5=#=yں# @F0 FYYI7*a0zNOp}8px(myT'[\"_@ #QǫӋ|kJ ݅Xl ϋ Zr 647ע"fJflaW@eUX-ƄruJ0>X PSek׏WAL>4,||֜v[ɎԴ)LJRʔ?{6 .[yMXW+'b ~&6 <&KiG|A<"+Kt8!r F,j-FD.b"Igm%DZER2Le䶰#d*Ds4VFǼx eAr  %] WnWQg~~2 EE@d:u8:7M%;~|tNNCGY׬hGӧSaD,At*f|r<>5ٔUȲ~ŒK,ʰc%-<NZRk7D:m/&/(serKf) [0(,kHdÁŢ$4ylr/S>P͔ѝ祕1x貒Mn+Rz>2[!0*7Sqy@vxCy)1Tτ6*g JB7/ӌoI"j! p|G/ om}>Ry_,bGmy S⛷aQNwBKi,Vle'zg2CX4 uڋ˥r+I+y@ړPЈj8|8A ʉi2xKu"oyx|_(2@abϮ f2 lݘ>dmG-x$i^jT~=iF5znRoVCO۱)T_z=ft6u*;OE05޿%ŊMcq?4F>DriQݱ)#L1,& drkhfohkZk it.}\(Tsb(%ɮUq-p2?IJqA$*5TlK8Lǧ¾()\e)=z `D V飯{:ئ`~L^hGiLݠ;G[{rv[7e"K<5a|>ʒd8 &BJ M"B /I^l 9_}L.\1|5'O_dq%O 0a>} (ryd>1HJ 2+fgۄF/*e%g$ d ԅ|a~OG&,!=|f7-$~f;?&vy=<{}'3)}4%|B4[:;])*Z[L+x[,xHzV*^SW%2^hXf7m%4\0;~k]}qf,W ILk6s!&KC:7-1':=E%NJl?Cvhe/yejOi`gf,t?:t+İ+>aQׅ%%>80QTu>qs )@J}^>r6CQxsi)~{~ hc!K TIB >!#g 4i8Y;O %bH &<$I3u#-&K ޑu>v(S!-w |wH&jmπ_~0,'L8{59Sמ@խ 6$ vqmwx(jUg0n{m oEʍ,[~]hkwgr vF/螂_I{u&k?*#ؖ!e$Z WE@Z!aݺ*F\B "Fa?& t>yE t;FQ?3g躲U#!%Wz7mØ#? Xy9ma:yLO2sʿװN'vTyg6j/5Ha,ė.Øwp e! <xY|{v:V=tuwLLtS\oLV"ř0Df!~M0$_nXh Ii&O1+'0b+-Uiv1djMjdO9a wz\S< Or'<%}+Ŭ6,{Mbz;]N|nεs gl\:52|sP}g+g,&&>)&y2 4&d=!cko~+UzdQ^,6BqH>()"j^2s+_񍩲ੴ b2B(F9)pc*eZ3 }iMSngIٖXfK+({" 3(@/1R.&q$ tjfm͊Bc6q5CG?x }R{Z2=s&Sy;OIt|NؖUh$SтwajԦTðΓ=Ncz#'"WT}|Hr} Utsgib3LXN93x|na(z7٪Xja i-iqc8Dy16yLfWx*|eSL|=_@1JHupfR@g/Eqczr wᠬ5K0?oR)4*c[aYSYk 2qpfn n.JjerEc?d'z.pqiД/.V.=gG#^Wo7D `exJr+"=%? RIza C)W!Ao+|o>i>kkgLQz0)26vR' -n2$f}':c[byΟ&h+X(*Jx9b`·~/vP3,kڸR>=Ʊ@)7,_P"satyЕ2xs**Ӭ# > ++޺(k!7lRi++8hzie A^gpG12h*5#SJL \R*` b*|-_vVCY yb]P2}bk.`-bX ĥ.':yQ*k)ku zҒ bg7&CushruSXO1i ]"e$14دbMDnl&H0 4&bݞV>~"Ia.tqZ@<*T0л o)Uk6c,=NN5NV7 jm98$WBe]bR )?O3Mnj? OtKqh[.vӿ25u1YWf ̝pj{=:hg$.b/+!? ArdHjv PLjl.dWidǔ$sgl)|Qg 3e=XXUST+Ԭ嬊pcJE/g!Vli=,%j}A$rPzB-ɹs#̛IT@,aSq˜'$*2˨?w_Eٸưc'Tn.E?tnf5R;XfikJX=Զ82e`fDi'`cg)>juFvttvTk$[ .N-pa}cv 7k@m pjsEiVv_!fPN_g6!J4z$N5"%h`فb!/Hg>037&3,5 ?e|eԅ!ѦGL5S9=Bs&ϛ1!0o-b1,܊|c:~yݑ)K+gh6?޲Bc,Rמ-<{2zR^23xJ ^yMy$S@bTeC#T".sum}]#*fe. v {HCe =|XUWR 655 H`6sSFZ~r3{^%! Omu]nww|~,=#pu?a/9/tfg=>i50ey1u=RR@W|:LhcZmlTql>3:bl&)}BW<.q5a.mqO+7;3]ev73?34~,#x,Bf" SI=b#0 VMS_CLOSEDIR4=@ VMS_CLOSEDIR4 G8E_MALLOC40b#0E_MALLOC44@8E_MALLOC4<Gl DECC$STRDUP4Db#0 DECC$STRDUP4h@l DECC$STRDUP4G4DECC$GXFPRINTF4b#0DECC$GXFPRINTF40@4DECC$GXFPRINTF4!4GH DECC$EXIT4"8b#0 DECC$EXIT4!D@H DECC$EXIT45G VMS_READDIR46b#0 VMS_READDIR45@ VMS_READDIR4G DECC$STRCHR4b#0 DECC$STRCHR4@ DECC$STRCHR4G DECC$STRCHR4b#0 DECC$STRCHR4@ DECC$STRCHR4G DECC$STRLEN4@ DECC$STRLEN4G DECC$STRLEN4@ DECC$STRLEN44GLDECC$GXFPRINTF4<b#0DECC$GXFPRINTF4H@LDECC$GXFPRINTF4!LG` DECC$EXIT4"Pb#0 DECC$EXIT4!\@` DECC$EXIT4`Gt DECC$STRCPY4p@t DECC$STRCPY4;tG DECC$STRCAT4<xb#0 DECC$STRCAT4;@ DECC$STRCAT4EG IS_EXCLUDED4Fb#0 IS_EXCLUDED4E@ IS_EXCLUDED4GDECC$GXFPRINTF4b#0DECC$GXFPRINTF4@DECC$GXFPRINTF4G DECC$STRCMP4@ DECC$STRCMP4 G,OTS$MOVE4 (@,OTS$MOVE40GL DECC$STRCMP4H@L DECC$STRCMP4 XGhOTS$MOVE4 d@hOTS$MOVE 4 hG|OTS$MOVE4 x@|OTS$MOVE48GTDECC$GXFPRINTF4Hb#0DECC$GXFPRINTF4P@TDECC$GXFPRINTF4hGDECC$GXFPRINTF4xb#0DECC$GXFPRINTF4|@DECC$GXFPRINTF4G DECC$STRCMP4@ DECC$STRCMP4G DECC$STRCMP4@ DECC$STRCMP<?GFIND_DIRECTORY_HASH<@b#0FIND_DIRECTORY_HASH<?@FIND_DIRECTORY_HASH4G$DECC$GXFPRINTF4 b#0DECC$GXFPRINTF4 @$DECC$GXFPRINTF4 GOTS$MOVE4 @OTS$MOVE<AGADD_DIRECTORY_HASH<Bb#0ADD_DIRECTORY_HASH<A@ADD_DIRECTORY_HASH4G DECC$STRCMP4@ DECC$STRCMP4G DECC$STRCMP4@ DECC$STRCMP<A G0ADD_DIRECTORY_HASH<Bb#0ADD_DIRECTORY_HASH<A,@0ADD_DIRECTORY_HASH4LGDECC$GXFPRINTF4Tb#0DECC$GXFPRINTF4@DECC$GXFPRINTF4GG DECC$ACCESS4Hb#0 DECC$ACCESS4G@ DECC$ACCESS<7GCMA$TIS_ERRNO_GET_ADDR<8b#0CMA$TIS_ERRNO_GET_ADDR<7@CMA$TIS_ERRNO_GET_ADDR4GDECC$GXFPRINTF4b#0DECC$GXFPRINTF4 @DECC$GXFPRINTF4(GP DECC$STRCMP4L@P DECC$STRCMP4TGd DECC$STRCMP4`@d DECC$STRCMP<?lGFIND_DIRECTORY_HASH<@tb#0FIND_DIRECTORY_HASH<?|@FIND_DIRECTORY_HASH4GDECC$GXFPRINTF4b#0DECC$GXFPRINTF4@DECC$GXFPRINTF4!G DECC$EXIT4"b#0 DECC$EXIT4!@ DECC$EXIT<AGADD_DIRECTORY_HASH<Bb#0ADD_DIRECTORY_HASH<A@ADD_DIRECTORY_HASH4GTDECC$GXFPRINTF4b#0DECC$GXFPRINTF4P@TDECC$GXFPRINTF4hGDECC$GXFPRINTF4tb#0DECC$GXFPRINTF4@DECC$GXFPRINTF4GE_MALLOC4b#0E_MALLOC4@E_MALLOC4G DECC$STRDUP4b#0 DECC$STRDUP4@ DECC$STRDUP4G DECC$STRDUP4b#0 DECC$STRDUP4@ DECC$STRDUP4/G4 ISO9660_DATE40b#0 ISO9660_DATE 4/0@4 ISO9660_DATE4@Gp DECC$STRCMP4l@p DECC$STRCMP,GSET_723,b#0SET_723,@SET_723<GISO9660_FILE_LENGTH<b#0ISO9660_FILE_LENGTH<@ISO9660_FILE_LENGTH,1$GLSET_733,2,b#0SET_733,1H@LSET_7334G DECC$STRCMP4@ DECC$STRCMP4G DECC$STRCMP4@ DECC$STRCMP4( G< E_MALLOC40 b#0E_MALLOC48 @< E_MALLOC4 G DECC$STRDUP4 b#0 DECC$STRDUP4 @  DECC$STRDUPD) G GENERATE_ROCK_RIDGE_ATTRIBUTESD* b#0GENERATE_ROCK_RIDGE_ATTRIBUTESD) @ GENERATE_ROCK_RIDGE_ATTRIBUTES,1(!Gp!SET_733,24!b#0SET_733,1l!@p!SET_7334!G! DECC$STRCMP4!@! DECC$STRCMP4!G! DECC$STRCMP4!@! DECC$STRCMP4%"G"DECC$GXSPRINTF4&"b#0DECC$GXSPRINTF4%"@"DECC$GXSPRINTF4"G0" DECC$STRDUP4 "b#0 DECC$STRDUP4,"@0" DECC$STRDUP4@"Gd" DECC$STRCMP4`"@d" DECC$STRCMP4h"Gx" DECC$STRCMP4t"@x" DECC$STRCMP4"G" DECC$STRCMP4"@" DECC$STRCMPD)"G#GENERATE_ROCK_RIDGE_ATTRIBUTESD*"b#0GENERATE_ROCK_RIDGE_ATTRIBUTESD)#@#GENERATE_ROCK_RIDGE_ATTRIBUTES4= #G4# VMS_CLOSEDIR4>,#b#0 VMS_CLOSEDIR4=0#@4# VMS_CLOSEDIR<#G#GENERATE_ONE_DIRECTORY<#b#`GENERATE_ONE_DIRECTORY<#@#GENERATE_ONE_DIRECTORY4H$Gl$DECC$GXFPRINTF4d$b#DECC$GXFPRINTF4h$@l$DECC$GXFPRINTF0 0=peTranslation table size mismatch %d %d Fatal error - RR overflow for file %s h=(Using %s for %s%s%s (%s) =8-Unable to generate unique name for file %s =@2Unknown file type %s - ignoring and continuing. =8,Directory loop - fatal goof (%s %lx %lu).  =@2File %s is not readable (errno = %d) - ignoring X=H>Warning - file %s has an unsupported VMS record format (%d) =0%Already cached directory seen (%s) =0#Symlink %s ignored - continuing. =@4Unable to stat file %s - ignoring and continuing.  =(Overflow of stat buffer @=(Directories too deep %s `=(Unable to open directory %s =,$Unable to locate directory parent ( ( =0;=0 $;=0 7DECC$GA_STDERR= %4d %5d %s H;DECC$GXFPRINTF=0 #;=0 `; GENERATE_ONE_DIRECTORYSET_723 DECC$STRDUP DELETE_FILE_HASH ;8OTS$MOVE GET_733 ISO9660_FILE_LENGTHSORT_DIRECTORY DECC$STRCHR DECC$__UTC_TIME= Fatal goof @=;1PE_MALLOC DECC$STRCPYFIND_FILE_HASH=.=;7 USE_ROCKRIDGE DECC$STRLEN=0` (;= ;7PATH_TABLE_SIZE DECC$STRCMP! DECC$EXIT= TRANS.TBL=.. # ADD_FILE_HASH%DECC$GXSPRINTF7ROOT7OMIT_VERSION_NUMBER 'FLUSH_FILE_HASH= %s.%3.3d%sp7 FULL_ISO9660_FILENAMES()GENERATE_ROCK_RIDGE_ATTRIBUTES= %c %-34s%s+ DECC$FREE8OTS$ZERO7GENERATE_TABLES/ ISO9660_DATE1SET_733=0  ;=P  ;= rr_moved= ./rr_moved(=0";=0 7 RATIONALIZE3VMS_STAT=0"8;=0 =0";= 5 VMS_READDIR=Excluded: %s =F %s  7CMA$TIS_ERRNO_GET_ADDR9VMS_PATH_FIXUP; DECC$STRCAT= VMS_CLOSEDIR ?FIND_DIRECTORY_HASH AADD_DIRECTORY_HASH=0 ";= 7 FOLLOW_LINKS7RR_RELOCATION_DEPTH0;7 ALL_FILESC DECC$OPENDIRE IS_EXCLUDED=D %s 7VERBOSEG DECC$ACCESS=0 x;=0 =0 @;=@< X X66=A A6-6 A A 6-6 $ $ = : :=*"! TREEDEC C V5.5-002 = 44=stat_fix4=]UT ? 9, 9 9 9 9 9 9ؼ 9: := 4= 8 = 84`4= stat_filter84==54 D D D D L$ $= l4: := 4= x = 4(4= lstat_filter4==54 O O O O W$ $= 4: := 4= x = (44= sort_n_finish(4= Z Z Z Z h b i k l m1 t                             rC                                                       @$ $= 4. .=  '4=  = . .=  '4=  = : :=  4=  # #= % 44=&generate_reloc_directory 4= , , , , 4 5 5 6 6 7 8 : : ? ? @ C B F E E K J K J K P Q Q Q S S T U T U Y Z Z _ \ \! \ ^ _0$ $= $ 4: := H4=  = x44=increment_nlinkx4=& e k $ $= 4: :=  4=  = !@44="finish_cl_pl_entries@4=e]\ s s | |   z ($ $= l4: := 4=  = 44=readdir_add_files4=!  $ $= 4: := 4= @M M=  404=!scan_directory_tree4=         !          &   ( ( ( ( _ ; : ? ? H1 a a k i k i j j j j j o o o q q  } }                                                                                                   2 $ ) ( )L$ $= |4. .=  !4=  = . .=   4=  = . .=  4=  = . .=  4=  = : := D#4= x = )#4`4=*"generate_iso9660_directories#4=,$# 6 6 ; $ $= #4: := #4=  = $44= dump_tree$4=*"! B E F $ $= <$4: := $4=  =  $ww1 5V1.0@@HASHV1.0 6-MAR-1997 22:21DEC C V5.5-002  $ABS$i$CODE$- $LITERAL$`$LINK$"$DATA$$BSS$ $READONLY_ADDR$ $READONLY$ DECC$FREE DECC$EXITDECC$GA_STDERRDECC$GXFPRINTF DECC$STRCMP0JADD_HASH0JP@ FIND_HASH8J0ADD_DIRECTORY_HASH8J FIND_DIRECTORY_HASH0JpFLUSH_FILE_HASH8JDELETE_FILE_HASH0J@FIND_FILE_HASH0J ADD_FILE_HASHE_MALLOC =#~^^~ (GGL0G HP@ Hc `@0B ~ MKISOFS.BCK2 [MKISOFS]MKISOFS.OLB_ALPHA;1wTG8bH"@Zk B4G(b4G@Zkp#G`B6Jhb"0D"l#G4G2v J1v Jr"`V@J2AJ1@4@2@5D@ZkP"D@$HC$@lcv`J5JF`pH LC@G]]} (0#kGG6JV JF2!JBaB2@""4DGkGA?@!!HB  9v K1G `pF`GkGG6$H#F~Q"^V J^4!J~B B(tB0GG @0["8{GGvFG4G@Zk "E@%HC! %@tH@3_JtF`G]]} (0@#kG6JV JF2!JBaB2@""4DGkG0A?@!!H"B  9v K1G `pF`Gk0,G0H 0.P"0B!HQ2Jp.2H'Jv@J1!J@@pJ@@`0,P"0BA2H4Hp.'H1HvJ!!H@@pJ@@_Dk#4G~^^~ G`[GGh{G@ZkCGd@5u_P¦ V @@G]]} 0#kG#G~^GG_Ӏ@@ H "B GxG VdC@ZkG]G #kG] #k#G~B^GG_Ӡ "W@05G GG]4G #kGPW06[4G{@ZkG]G #k#~^^~ (0G;G "a G B4G(b@ZkG G@?G]]} (0@#k4HG`DECC$GXFPRINTF4Pb#DECC$GXFPRINTF4\@`DECC$GXFPRINTF4`Gt DECC$EXIT4hb# DECC$EXIT4p@t DECC$EXIT4|GE_MALLOC4b#E_MALLOC4@E_MALLOC4G@E_MALLOC4$b#0E_MALLOC4<@@E_MALLOC4GE_MALLOC4b#E_MALLOC4@E_MALLOC4 G DECC$STRCMP4 @ DECC$STRCMP4XGh DECC$FREE4`{# DECC$FREE4d@h DECC$FREE4G DECC$FREE4b#p DECC$FREE4@ DECC$FREEM M=5-Non zero-length file assigned zero extent.  =0 ;=0  DECC$EXITDECC$GXFPRINTF7DECC$GA_STDERR;;`E_MALLOC=0 ;=@<  DECC$FREE=0(;=0";= =0"@;=  DECC$STRCMP=0 ;=0 =0;=0 ;=@< =0@; 666666 X X66=: :=*"! HASHDEC C V5.5-002 = 44=add_hash4=f^] * * 5 5 5 5 < ?$$ $= ,4: := 4= @ = @4P4= find_hash@4=>65 K J J J M NN N= x44=  = 404= add_directory_hash4=}| \ W W W W W W W W W _ ` b$$ $= 04: := |4=  =  4 4=!find_directory_hash4=>65 l k k k n oN N= 4$4=  = (44= name_hash(4=  : := 4=  = 44= add_file_hash4=G?>       $ $= 4: :=  4=  = @44=find_file_hash@4=/'&    $ $= \4N N= 44=  = 44=delete_file_hash4=QIH       $ $= 4N N= 04x4=  = 4p4=flush_file_hash4=G?>         $$ $= 4: := 4=  =  wwb17V1.0@@ROCKV1.0 6-MAR-1997 22:21DEC C V5.5-002  $ABS$i$CODE$ $LITERAL$T$LINK$$DATA$(A$BSS$ $READONLY_ADDR$ $READONLY$ DECC$EXITDECC$GA_STDERRDECC$GXFPRINTF DECC$STRCHR DECC$STRNCPY DECC$STRCMP DECC$STRLEN ISO9660_DATESET_733@JGENERATE_ROCK_RIDGE_ATTRIBUTES@J@xGENERATE_RR_EXTENSION_RECORDE_MALLOCREADLINKOTS$MOVEOTS$ZERO =#TG~^^~ (G {(G0[#8{ @ @0B@@ZktGGG0@@u@J.0 @@TJyJF>/0B@spKXK8b@G?4GP.vJ0 BTGRPJSFP>@:,A:H6D:<0B#G@ZkG0BTG8b@@@Zk0BG8bTG@@@Zk#@ G]_ D]} (0#k`#tG~G^G ^(~08@޴HPX>`^h~px޵G GG ޠGPX;GD^G )!X; Dz8K `C TGDGG G G0@C:Au:J.0`C;Ay;JTJ0@F>. AuK0BWJ0AF>. 6A4GyPKTJ@B0BF>J@].WJF>G},@H<Dz@Zk[@BP@G@ZkVBG@Zk GQGG'GǢ)9BACC C16B19B2#B4G0B7AG.y7H0BVJ4AF> HB4,5AhFGvtJA4H@B6D4</0ByPK0B0BXK5AG?G.E4GvUJTJ;AF>.C0`Cx JWJ;AF>g!@8bGGtG@Zk,A aE@ A0b#_Ӱ0b#ǡ).A@@ @_GG 0A ,Aq H .0A -AP JuMJF >.0A/AGTJzJF>//.A4GpvKY/Khb0A:G/? !-i"`BTG 4`ELI E= %.nB E. !DZ-JR MJ2F@Zk -- TGI`BN IhbAEC@@Zk!`BTGhb! A-A,!I@ HEC@Zk%.TG- A.JO I`BAhb/F !@Zk - -$ǡ IpBL Ixb?$ EE! ADZD?(@ "CG_"tG@Zk A`B G(@-GhbЁ@TGNI(@= `E@Zk+(@ #A0b#ǡX"-A )! A A AG_ǡtGG0A.Ar.H.. 0A/AQ.JwJ2F.>.0A -AGVJ{ KF>M/0@ A4GZMKrI[GM? .3A0`BQ J2F >-OI=G.gJ`BChbGTG@ZkCC.,1APJ>"#."'#JX"G%F#`.i8CXCJC؅F.)!J C0b#_GPA0@ At J`.!A0 @S`J,QAtF`>.VJ>'G%FG#/##gX"K:[CI)!@@ @0b#_TGPA0@ At J`.!A0 @S`J,1AtF`>.VJ>'sG 0b#X"'7BI7CB B)!_GPA0@ At J`.!A0 @S`JtF`>.VJ>'SGCX"'7BI7CPB BMB@Zk GC@'g HAGX"F33BTB)BBG B G!4@!3@ 4G&#@XD8bC#C0 B,uJ0 BC@HtHD<."BGVJtGF>GC0BAf@PA@Zk,A*FA@?0b#S_N-G`H 0AJNI @EN=G0A#,#H)? 0b#B_N-G`HJNI 0A @EN= .qI4G m"P JuSJF > E .TJF >Ǣ0b#X"6BYCB B_X"GG)!0@$AmdH- 0@&ALIqH E=.0@A *ATGPJvjJF>.0A.A4GUJzJF>.//AGhrKY.K(b"!:G.?0A, /A BATGDH!D< pE",%%, HA -H&!DC@ZkǠ BTG(b@ǰ &Ae,AA!,nHD HdDC@ZkTG B(bA&-(A),AIF HEC@Zkg 0b#ǡ`@g+G#n@ CAd@ h@`_TGGG0@%AjI- 0@&ANIaIE=, 0A ,At,J@H-AD<l.4GxJ 0ASlJ hEtFl>.WJF> =DgP G7@I$dC@@ @0b#_ǡGG`BGhb0A.AeI-0A/AMIpH E=/,0`@#At#JA/H &A0D/<c.4GyJ0@ScJ"tFc> /BG dEX KG ?TGǰ@Zk@0b# GD E6ǡ-A@@ @G_g tGhbG 0`@#AoI-0@A *Aq HMI0@ E= .&AGuFJP J%AF >.4GzJ0@TJ"F>$/BG bEY$K:G`B$?TG@Zkga@gE0b#_TG`B-omIhb,ANIE= =G1LA@ZkB4Gb@ZkC gBGdDXBtGxe|@ZkG] ](}08@ݤHPX=`]h}pxݥ#k#G~G^G^ ~(0G0[G~@Zk0BGG@Zk0BGG8B@ZkBHbBtQJ BuKyHr J5GTFFSBD!B"G@Zk B@GG@Zk B8C @@GG@Zk##@ PBXbTGh"@ZkpBxb4G4G@ZkB"b4G@Zk`BCG?"@Zk BGGG@Zk=aG]] }(0@#k,0GXSET_733,<b#SET_733,T@XSET_733,b#SET_733,GSET_733,@SET_733,GSET_733,b#SET_733,@SET_733, G@SET_733,(b#SET_733,<@@SET_7334G DECC$STRCMP4@ DECC$STRCMP4G DECC$STRCMP4@ DECC$STRCMP4G$ DECC$STRLEN4 @$ DECC$STRLEN4GD DECC$STRNCPY40b# DECC$STRNCPY4@@D DECC$STRNCPY,b#SET_733, G\SET_733,X@\SET_733,tGSET_733,|b#SET_733,@SET_733,GSET_733,b#SET_733,@SET_733,GSET_733,b#SET_733,@SET_7334,GpREADLINK44b#READLINK4l@pREADLINK,xGSET_733,b#SET_733,@SET_7334G DECC$STRCHR4b# DECC$STRCHR4@ DECC$STRCHR4 G DECC$STRLEN4 @ DECC$STRLEN4$ b# DECC$STRNCPY4 G DECC$STRNCPY4 @ DECC$STRNCPY4 b# ISO9660_DATE40 Gt ISO9660_DATE4p @t ISO9660_DATE4x G ISO9660_DATE4 b# ISO9660_DATE4 @ ISO9660_DATE4 G ISO9660_DATE4 b# ISO9660_DATE4 @ ISO9660_DATE, GSET_733,b#SET_733,@SET_733,b#SET_733,xGSET_733,@SET_733,GSET_733,b#SET_733,@SET_7334 GE_MALLOC4b#E_MALLOC4 @E_MALLOC4G,OTS$MOVE4(@,OTS$MOVE4G DECC$STRLEN4@ DECC$STRLEN4G DECC$STRLEN| |4@ DECC$STRLEN4G DECC$STRLEN4@ DECC$STRLEN4G OTS$MOVE4@ OTS$MOVE4 G4OTS$MOVE40@4OTS$MOVE44GPOTS$MOVE4L@POTS$MOVE4\GtDECC$GXFPRINTF4`b#@DECC$GXFPRINTF4p@tDECC$GXFPRINTF4 tG DECC$EXIT4 xb#@ DECC$EXIT4 @ DECC$EXIT4 GE_MALLOC4b#@E_MALLOC4 @E_MALLOC4 GOTS$ZERO4 @OTS$ZERO4GOTS$MOVE4@OTS$MOVE< <=$Extension record too long  =0 ;=0 ;;SET_733=0"x;=@ 8OTS$MOVEp DECC$STRLEN7DECC$GA_STDERR=ERDECC$GXFPRINTF8OTS$ZERO; DECC$EXIT E_MALLOC=0";=  ISO9660_DATE DECC$STRNCPY DECC$STRCMP=.(=SP DECC$STRCHRREADLINK= ..0 0=X X66=: :=*"! ROCKDEC C V5.5-002 = 44= add_CE_entry4= + + + / . . . / / 0 0 1 3 2 5$ $= 04: := p4=  = +44=,$generate_rock_ridge_attributes4= 8  8 8 A @ 8 8  A  @ @ P P P Q P R P R Q R Z Z( ` ` d c c ` d e g YԨ o p o p p p q q r s s s t t   t                                      BР           ؅                    F H H M M O M O  NL$ $=  4. .=  4=  = . .=  4=  = : := ,4=  = )x4@4=*"generate_rr_extension_recordx4=f^] V V ] _ a d g j $ $= 4: := 4= t =   ww1sD<V1.0??VMSV1.0 6-MAR-1997 22:21DEC C V5.5-002  $ABS$i$CODE$ $LITERAL$$LINK$$DATA$$BSS$ $READONLY_ADDR$ $READONLY$DECC$GA_RMS_NAMDECC$GA_RMS_FABDECC$GA_RMS_RAB SYS$CLOSE SYS$CONNECTSYS$OPEN SYS$PARSESYS$READDECC$__UTC_STATDECC$GA_STDERR DECC$FWRITEDECC$GXFPRINTFDECC$GXSPRINTF DECC$READDIR DECC$CLOSEDIR DECC$STRCAT DECC$STRNCPY DECC$STRRCHR DECC$STRCMP DECC$STRLEN DECC$STRDUP DECC$FREE DECC$EXITE_MALLOC0JHh VMS_PARSE0JVMS_PATH_FIXUP0Jh VMS_READDIR0Jh VMS_CLOSEDIR0JVMS_STAT LAST_EXTENT_WRITTEN8Jx VMS_WRITE_ONE_FILE0JPREADLINKOTS$MOVEOTS$ZERO =#G~tG^^G(;G@[dCH{@Zk0B8b4G4G@ZkG]] #k #G~G^^~G8;G!aGXq2ABa! \1"_&XqG\G`ݢUuF_X9!CU" x#u?hb4^@X4G8B xc 4`ݲd}@Zk<}(BDC0b3J08CD <@Zk""GBTGb,B@ZkBGb4G@ZkGG$,A$H$<]]}#k#? ~^^~ (G[GG@ZkPB`@@H@G@Zk.WJ>G BG(bTG@ZkC7"$,G BTG(b0HG @ZkC B(bGtGTG@ZkC$,0@0B4G8bA$H$<@Zkd,Gq$HCCdHqDd<.G0BuDJ8b0@TJ4GF>@ZkPBXbCL@GTG@ZkGGG]]} (0#kG#G~^^~ (0޴8GGۤG $ G!?Hf"..! $$G?F%B$GԢDFFF"B0@?D@DFG `x"TGBb'@@ZkB&b"4G@Zk@@A@`E@4G%"GE 8FTG G(BG0b4G@ZkG]]} (0ݤ8@#kG#G~^G8;Q"G_s"rBFӢ0 @F 0 @F0 @G0 @?$@@A1@G([4G0{@ZkG] #kG#G~^^~ G[GG@ZkG& @}@R"`.#2"R#JR"F.61BJF2/61B1K+F .61BJ F 61B}B,HR" D61BPB6@CO@@ZkN71B07@}B9##9." 9J9#%F%`x+F# .71B9"J؅F@xFy/71B`KDx Dy.71BqJ%Fx+F 71B}B_ .J9#؅FxF71B7@@"`.:BBuJ21BxkF`CC41@C6B21BCL@C41B BG(bG@Zk CPBCP@61B@Zk16@}B"$ G/w"W#7#K"G$ x G"W.61BSJEFxKF@.61BJإF`xF,61BHD x D 61B}B w.wJ"eF@xkF`61B6@Z#Gz/zKxKG@291B0 9@} C"# ,u"u#HD&x D$U.91 C#SJEFxKF@.91 CJF@xF5.91 C8J%Fx+F 91 C} C" .J؅F`xF91 C"?F@@"CC21BGG9@@ ".}" "J21 Cx F6BCC21 C6BCL@C41BGG B(b@Zk CG0B8bGTG@ZkG]]} 0#kG#4G~^^~ (0G([GG0{G@Zk(BG4G0b@ZkH$G@BCP G@Zk8G<G7G @"99#7B&G9"&,v?&@Zk4VDxBGb2V@J$D@4$c  4vJB6! H1@6$64G<@ZkDDQ@`b#_XB4G`b@ZkDM@b# _G]]4G} (0@#k#4G~^^~ (G@[GH{G<@Zk 0B4G<8b@Zk0BG8b4G$@Zkc J@pb#D`_G]]} (0#kG# ~#^^~ (0޴8@H>PG_ C#GGGGp{#J_8$  E`G (BGD"! &DG@Zk"$ղ ?'8B9#@bG8KC 4G@ZkXB `bC4GGGG@Zk ()EBtGwH @H0AJBq0BQ1Bq0BQ0Bq0BQ?Bq0Bq0Bq1BQ0Bp0BJI@PBPBPBPB0PBBbb@Zk#i@b#k_G]]} (0ݤ8@H=P`#k#G~tG^^G0[G@Zk @G AF(aGGG@ZkG]G] #k4(G<DECC$GXFPRINTF40b#DECC$GXFPRINTF48@<DECC$GXFPRINTF4<GP DECC$EXIT 4@b# DECC$EXIT4L@P DECC$EXIT4(GD DECC$STRLEN4@@D DECC$STRLEN4+HGx SYS$PARSE4,Tb#H SYS$PARSE4+t@x SYS$PARSE4GDECC$GXFPRINTF4b#HDECC$GXFPRINTF4@DECC$GXFPRINTF4G DECC$EXIT4b#H DECC$EXIT4@ DECC$EXIT4 G DECC$STRLEN4@ DECC$STRLEN4G4 DECC$STRCMP40@4 DECC$STRCMP4%HG\ DECC$STRRCHR4&Pb# DECC$STRRCHR4%X@\ DECC$STRRCHR4%pG DECC$STRRCHR4&xb# DECC$STRRCHR4%@ DECC$STRRCHR4%G DECC$STRRCHR4&b# DECC$STRRCHR4%@ DECC$STRRCHR4'G DECC$STRDUP4(b# DECC$STRDUP4'@ DECC$STRDUP4'G DECC$STRDUP4(b# DECC$STRDUP4'@ DECC$STRDUP4)G8 DECC$STRCAT4* b# DECC$STRCAT4)4@8 DECC$STRCAT4 G4DECC$GXFPRINTF4(b#DECC$GXFPRINTF40@4DECC$GXFPRINTF44GL DECC$EXIT4<b# DECC$EXIT4H@L DECC$EXIT4#G DECC$READDIR4$b# DECC$READDIR4#@ DECC$READDIR4!`Gp DECC$CLOSEDIR4"h{#h DECC$CLOSEDIR4!l@p DECC$CLOSEDIR4G DECC$STRLEN4@ DECC$STRLEN4XGl DECC$STRCMP4h@l DECC$STRCMP4GDECC$GXSPRINTF4b#DECC$GXSPRINTF4@DECC$GXSPRINTF4G DECC$STRCMP4@ DECC$STRCMP4 G DECC$GXSPRINTF4 b#DECC$GXSPRINTF4 @ DECC$GXSPRINTF4 G DECC$__UTC_STAT4 b#DECC$__UTC_STAT4 @ DECC$__UTC_STAT4 h G E_MALLOC4t b#E_MALLOC4 | @ E_MALLOC4  G E_MALLOC4 b#E_MALLOC4  @ E_MALLOC4 G OTS$MOVE4 @ OTS$MOVE4 G$ DECC$STRLEN4 @$ DECC$STRLEN4, G SYS$OPEN44 b#SYS$OPEN4 @ SYS$OPEN4 G SYS$CONNECT4 b# SYS$CONNECT4 @ SYS$CONNECT 4 $ G< SYS$CLOSE4 , b# SYS$CLOSE4 8 @< SYS$CLOSE4 @ GX DECC$FREE4 L b# DECC$FREE4 T @X DECC$FREE4 X Gp DECC$FREE4 ` b# DECC$FREE4 l @p DECC$FREE4< G` OTS$ZERO4\ @` OTS$ZERO4p G SYS$READ4x b#xSYS$READ4 @ SYS$READ4 G DECC$FWRITE4 b#x DECC$FWRITE4 @ DECC$FWRITE4 G@DECC$GXFPRINTF44b#xDECC$GXFPRINTF4<@@DECC$GXFPRINTF4G DECC$STRLEN4@ DECC$STRLEN4G DECC$STRNCPY4a#P DECC$STRNCPY4@ DECC$STRNCPY =(%.*s[000000]000000.DIR;1 =H<%.*s[000000]%.*s.DIR;1Ran out of VMS directory contexts `=*"$PARSE of root directory failed 0 0=0 ;=   %s (7DECC$~ MKISOFS.BCK2 [MKISOFS]MKISOFS.OLB_ALPHA;1nGA_STDERR DECC$EXITDECC$GXFPRINTF=0";=   DECC$STRNCPY DECC$STRLEN=0" ;=0 ; DECC$FREE SYS$CLOSE=$CLOSE=0"@ ;=@<  E_MALLOC7DECC$GA_RMS_FAB8OTS$MOVE7DECC$GA_RMS_RAB@ SYS$CONNECT= $CONNECT`SYS$OPEN=$OPENx=0  ;=` 7LAST_EXTENT_WRITTEN8OTS$ZEROSYS$READ=%d.. DECC$FWRITE=0";=0 DECC$GXSPRINTF DECC$__UTC_STAT;0 DECC$STRCMP= %.*s]%.*s.DIR;1X=.`=..h=0";= ! DECC$CLOSEDIR;=0"h;=@| # DECC$READDIR=0";=0 % DECC$STRRCHR' DECC$STRDUP=.DIR;10) DECC$STRCAT=]H=0"h;= p+ SYS$PARSE7DECC$GA_RMS_NAMq q6|66|6 X X66=9 9=)!  VMSDEC C V5.5-002 = 44= error_exit4=(  0U 0U 0U$ $= (4: := P4= h = h4H4= VMS_parseh4= 7U 7U 7U 7U 9U 9U :U :U :U ?U :U >U @U @U- @U AU GU FU$ $= 4: := 4=  = 44=vms_path_fixup4=E=< OU OU TU YU YU$$ $= 4: := D4=  = h44= VMS_readdirh4=kcb eU eU eU eU iU iU lU kU oU,$ $= 4: := 4= p = 4h4= VMS_closedir4=! {U {U$ $= 4: := p4=  = 44=VMS_stat4= U U U U U U4 U U U U U U U U $ $= 4: :=  4= 5 5= @ 44= open_file@ 4= U U U U U U U U U U U U U UF U U U U U U U$ $= t 4: :=  4=  =  44= close_file 4=A98 U U U U U U$$ $= 4 4: :=  4=  =  4x4= vms_write_one_file 4=zy U  U U U  U U U U U U U U U 4$ $=  4: := T4=  = 4P4=readlink4=910 U U U U U$ $= 4: := 4= l =  ww 1`T=V1.0CCEXCLUDEV1.0 6-MAR-1997 22:21DEC C V5.5-002  $ABS$i$CODE$a $LITERAL$$LINK$$DATA$$BSS$ $READONLY_ADDR$ $READONLY$DECC$GA_STDERRDECC$GXFPRINTF DECC$MALLOC DECC$STRCPY DECC$STRCMP DECC$STRLEN(J EXCLUDE0J IS_EXCLUDED =#G~^^~ (G ;GG! r" `0@BTAB"0@BVAB֢"H" @0BG&C8btG@ZkpBGDAB4G@Zk`Bhb0@@ZkCTG@"0B8bH"@ZkPBG@ZkG]]} (0#k#G~G^GG7 GX" A @SCG@Zk 0CYC9?G]G  #kG]4G #k4xGDECC$GXFPRINTF4b#DECC$GXFPRINTF4@DECC$GXFPRINTF4G DECC$STRLEN4@ DECC$STRLEN4G DECC$MALLOC4b# DECC$MALLOC4@ DECC$MALLOC4GDECC$GXFPRINTF4  b#DECC$GXFPRINTF4@DECC$GXFPRINTF4G DECC$STRCPY4@ DECC$STRCPY4 LGd DECC$STRCMP4 `@d DECC$STRCMP =8.Can't allocate memory for excluded filename 0=91Can't exclude '%s' - too many entries in table \ \=0  ;=0 ;0DECC$GXFPRINTF7DECC$GA_STDERR; DECC$STRCPY DECC$MALLOC DECC$STRLEN=0";=  DECC$STRCMPX X66== ==-%$ EXCLUDEDEC C V5.5-002 = 44= exclude4=C;:           $ $= 04: := 4=  = 44= is_excluded4=H@? "  "  "  &  &  )  ' $ $= <4N N= 44=  =  ww*[MKISOFS]README.;1+,6. / 4 V- 0123KPWO 56_M7D܈ 89*̞OGHJNote: There is a feature which can be optionally compiled into mkisofs that allows you to merge arbitrary directory trees into the image you are creating. You need to compile with -DADD_FILES for my changes to take effect. Thanks to Ross Biro biro@yggdrasil.com. This program requires a lot of virtual memory to run since it builds all of the directories in memory. The exact requirements depend upon a lot of things, but for Rock Ridge discs 12Mb would not be unreasonable. Without RockRidge and without the translation tables, the requirements would be considerably less. The cdwrite utility is maintained separately from mkisofs by yggdrasil.com. It is enclosed here as a convenience, since the two programs are often useful together. ***************************** Notes for version 1.05 Added support for '-r' switch. This is very similar to -R for Rock Ridge, but echos of the development environment are removed (i.e. uid/gid set to 0, and permissions of the files are canonicalized). Useful in applications where a distribution medium is being produced. ***************************** Notes for version 1.04 No notes for 1.04. ***************************** Notes for version 1.03 No notes for 1.03. ***************************** Notes for version 1.02. Minor bugfixes here and there. Support for compiled in defaults for many of the text fields in the volume header are now present, and there is also support for a file ".mkisofsrc" that can also read settings for these parameters. A short script "Configure" was added to allow us to set up special compile options that depend upon the system that we are running on. This should help stamp out the sphaghetti-isms that were starting to grow up in various places in the code. You should get more meaningful error messages if you run out of memory. ***************************** Notes for version 1.1. The big news is that SUSP CE entries are now generated for extremely long filenames and symlink names. This virtually guarantees that there is no limit (OK, well, about 600Mb) for file name lengths. I have tested this as well as I can, and it seems to work with linux. This would only be used very rarely I suspect. Also, I believe that support for VMS is done. You must be careful, because only Stream-LF and FIxed length record files can be recorded. The rest are rejected with error messages. Perhaps I am being too severe here. There is a bugfix in the sorting of entries on the disc - we need to stop comparing once we reach the ';' character. There are four new options -z -d -D -l -V. Some of these tell mkisofs to relax some of the iso9660 restrictions, and many systems apparently do not really seem to mind. Use these with caution. Some diagnostic programs to scan disc images are in the diag directory. These are not as portable as mkisofs, and may have some bugs. Still they are useful because they can check for bugs that I might have introduced as I add new features. ***************************** Notes for version 1.0. In version 1.0, the date fields in the TF fields were fixed - previously I was storing st_ctime as the file creation time instead of the file attribute change time. Thanks to Peter van der Veen for pointing this out. I have one slight concern with this change, however. The Young Minds software is definitely supplying 3 dates (creation, modification and access), and I would strongly suspect that they are incorrectly putting the file attribute change time in the file creation slot. I would be curious to see how the different RRIP filesystems treat this. Anyway, this is something to keep in the back of your mind. The symlink handling was not quite correct in 0.99 - this is now fixed. Only some systems seemed to have been affected by this bug. A command line option is now present to allow you to specifically exclude certain files from the distribution. The case where you do not have permissions to read a directory is now handled better by mkisofs. The directory that cannot be opened is converted into a zero-length file, and processing continues normally. A few portability things have been fixed (hopefully). *[MKISOFS]README.VMS;1+,'. / 4M - 0123KPWO 56 mD7mD89*̞OGHJMThe original distribution of mkisofs v1.05 is available by anonymous ftp fromKtsx-11.mit.edu in /pub/linux/BETA/cdrom/mkisofs. The changes made to this (version (v1.05.vms7) had three purposes:/ - compile cleanly using DEC C V5.2 and later;F - use the new runtime routines included with OpenVMS V7.0 and later;@ - deal directly (and correctly) with OpenVMS directory syntax.KPlease report any problems building or using this software using the above >compiler and operating system combination to George Watson at watson_g@eisner.decus.org.KThis software and the modifications made to it are covered by the terms of =the GNU General Public License included in this distribution.*[MKISOFS]SRC.DIR;1+,). / 4 - 0123 KPWO 567v 77v 89*̞OGHJI CHANGELOG.CONFIG.H+ DEFAULTS.HDIAG.DIR= EXCLUDE.C. EXCLUDE.H/HASH.C0 ISO9660.H MKISOFS.CH MKISOFS.H5ROCK.C7TREE.C< VMS.CVMS.HWRITE.C*[MKISOFS.SRC]CHANGELOG.;1+,.6/ 4L61-)0123KPWO756>C7<2C89*̞OGHJ$Wed May 14 14:28:58 1997 George Watson (watson_g@eisner.decus.org) * write.c, mkisofs.c (version_string): change to 1.05.vms7. * iso9660.h, write.c: add ISO_PATH_TABLE_LEN and ISO_DIRECTORY_RECORD_LEN defined values. The root directory record was not being sized correctly. * defaults.h, vms.h, mkisofs.c, tree.c, vms.c, write.c: changes to OpenVMS support, to take advantage of the new runtime support in OpenVMS V7+ and DEC C V5.2+. Also, regularize the handling of VMS directory path format. * mkisofs.hlp: OpenVMS format help file, based on man page. * rewrote all prototypes and function declarations to use ANSI format unconditionally. 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 : * 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 * tree.c: Port to Solaris 2.4. Prefer 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 on VMS systems. * tree.c: Include and "vms.h" on VMS systems. * mkisofs.h (PATH_SEPARATOR, SPATH_SEPARATOR): New macros that define the ascii character that separates the last directory component from the filename. * tree.c, mkisofs.c: Use them. * vms.c: New file. Contains version of getopt, strdup, opendir, readdir and closedir. * vms.h: New file. Defines S_IS* macros. Define gmtime as localtime, since gmtime under VMS returns NULL. Sat Jan 15 13:57:42 1994 Eric Youngdale (eric@esp22) * mkisofs.h (transparent_compression): New prototype. * mkisofs.c (transparent_compression): Declare, use '-z' option to turn on. * tree.c: Change TRANS.TBL;1 to TRANS.TBL (version gets added later, if required). * rock.c: If transparent compression requested, verify file is really suitable (check magic numbers), and extract correct file length to store in SUSP record. Sat Jan 15 01:57:42 1994 Eric Youngdale (eric@esp22) * write.c (compare_dirs): Bugfix for patch from Jan 6. * mkisofs.h (struct directory_entry): Add element total_rr_attr_size. (struct file_hash): Add element ce_bytes. * write.c (iso_write): Update last_extent_written, as required, and check it against last_extent as a sanity check. (generate_one_directory): If ce_bytes is non-zero, allocate a buffer and fill it with the CE records. Also, update the extent and offset entries in the CE SUSP field and output after directory is written. (assign_directory_addresses): Allow for CE sectors after each directory. * tree.c (sort_n_finish): Set field ce_bytes by summing the sizes of all CE blocks in each files RR attributes. Do not count these bytes for main directory. * rock.c (generate_rock_ridge_attributes): Generate CE entries to break up large records into manageable sizes. Allow long names to be split, and allow long symlinks to be split. Allow splitting before each SUSP field as well, to make sure we do not screw outselves. Thu Jan 6 21:47:43 1994 Eric Youngdale (eric@esp22) Bugfix. * write.c (compare_dirs): Only compare directory names up to the ';' for the version number. Add four new options: (1) Full 31 character filenames, (2) Omit version number, (3) Omit trailing period from filenames, (4) Skip deep directory relocation. * iso9660.h: Allow 34 characters for filename. * mkisofs.8: Update for new options. * mkisofs.c: Add flag variables for new options. Mention new options in usage(), tell getopt about new options, and set appropriate flags when new options are specified. * mkisofs.c (iso9660_file_length): Implement new options. * mkisofs.h: Declare flag variables for new options. * tree.c (sort_n_finish): Increase declaration of newname and rootname to 34 characters. If full_iso9660_filenames in effect, use different rules for making unique names. * tree.c (scan_directory_tree): Use RR_relocation_depth instead of constant for threshold for starting deep directory relocation. Wed Jan 5 01:32:34 1994 John Brezak (brezak@ch.hp.com) * Makefile.bsd: New file. For NetBSD. * rock.c, tree.c: Do not include sys/sysmacros.h for NetBSD. Fri Dec 31 13:22:52 1993 Eric Youngdale (eric@esp22) * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.00. * tree.c (scan_directory_tree): Handle case where we do not have permissions to open a directory. * write.c (xfwrite): New function - wrapper for fwrite, except that we print message and punt if write fails. * write.c: Move include of mkisofs.h and iso9660.h until after string.h and stdlib.h is included. * write.c: Do not attempt to use strerror on sun systems. Thu Dec 9 13:17:28 1993 R.-D. Marzusch (marzusch@odiehh.hanse.de) * exclude.c, exclude.h: New files. Contains list of files to exclude from consideration. * Makefile: Compile exclude.c, add dependencies to other files. * mkisofs.8: Describe -x option. * mkisofs.c: Include exclude.h, handle -x option. Fri Dec 10 01:07:43 1993 Peter van der Veen (peterv@qnx.com) * mkisofs.c, mkisofs.h: Moved declaration of root_record. * mkisofs.h: Added prototype for get_733(). * write.c(iso_write), tree.c, rock.c(generate_rock_ridge_attributes): Added defines for QNX operation system * rock.c(generate_rock_ridge_attributes): symbolic links should not have CONTINUE component flag set unless there are multiple component records, and mkisofs does not generate these. st_ctime was stored as the creation time, changed to attribute time. QNX has a creation time, so that is stored as well under QNX. Thu Oct 28 19:54:38 1993 Eric Youngdale (eric@kafka) * mkisofs.c, Makefile (version_string): Bump to 0.99. * write.c(iso_write): Put hour, minute, second into date fields in volume descriptor. * write.c (iso_write): Set file_structure_version to 1, instead of ' ' (Seems to screw up Macs). Sun Oct 17 01:13:36 1993 Eric Youngdale (eric@kafka) * mkisofs.c, Makefile (version_string): Bump to 0.98. Increment nlink in root directory when rr_moved directory is present. * tree.c (increment_nlink): New function. * tree.c (finish_cl_pl_entries): Call increment_nlink for all references to the root directory. * tree.c (root_statbuf): New variable. * tree.c (scan_directory_tree): Initialize root_statbuf when we stat the root directory. * tree.c (generate_reloc_directory): Use root_statbuf when generating the Rock Ridge stuff for the ".." entry in the reloc_dir. * tree.c (scan_directory_tree): Use root_statbuf when generating the ".." entry in the root directory. Sat Oct 16 10:28:30 1993 Eric Youngdale (eric@kafka) Fix path tables so that they are sorted. * tree.c (assign_directory_addresses): Move to write.c * write.c (generate_path_tables): Create an array of pointers to the individual directories, and sort it based upon the name and the parent path table index. Then update all of the indexes and repeat the sort until the path table indexes no longer need to be changed, and then write the path table. Fix problem where hard links were throwing off the total extent count. * write.c (iso_write): Call assign_file_addresses, and then use last_extent to determine how big the volume is. * write.c (generate_one_directory): Decrement n_data_extents for hard links to non-directories so that the expected number of extents is written correctly. * write.c(assign_file_addresses): New function. Fri Oct 15 22:35:43 1993 Eric Youngdale (eric@kafka) The standard says we should do these things: * tree.c (generate_reloc_directory): Add RR attributes to the rr_moved directory. * mkisofs.c(main): Change ER text strings back to recommended values. Tue Oct 12 21:07:38 1993 Eric Youngdale (eric@kafka) * mkisofs.c, Makefile (version_string): Bump to 0.97. * tree.c (scan_directory_tree): Do not insert PL entry into root directory record (i.e. !parent) * tree.c (finish_cl_pl_entries): Do not rely upon name comparison to locate parent - use d_entry->self instead, which is guaranteed to be correct. * mkisofs.h: New variable n_data_extents. * tree.c: Declare and initialize n_data_extents to 0. (scan_directory_tree) for non-directories, add ROUND_UP(statbuf.st_size) to n_data_extents. (sort_n_finish): Increment n_data_extents for translation tables, as appropriate. * write.c(iso_write): Add n_data_extents to the volume_space_size field. * hash.c(add_hash): If size != 0 and extent == 0, or if size == 0 and extent != 0, then complain about inserting this into the hash table. Kind of a sanity check. Sat Oct 9 16:39:15 1993 Eric Youngdale (eric@kafka) * mkisofs.c, Makefile (version_string): Bump to 0.96. Numerous bugfixes, thanks to a one-off disc from rab@cdrom.com. * write.c(generate_one_directory): Wait until after we have filled in the starting_extent field to s_entry before calling add_hash. This fixes a problem where the hash table gets an extent of 0 for all regular files, and this turns up when you have hard links on the disc. (The hash table allows us to have each hard link point to the same extent on the cdrom, thereby saving some space). * tree.c(scan_directory_tree): Set statbuf.st_dev and statbuf.st_ino to the UNCACHED numbers for symlinks that we are not following. This prevents the function find_hash from returning an inode that cooresponds to the file the symlink points to, which in turn prevents generate_one_directory from filling in a bogus file length (should be zero for symlinks). * tree.c(scan_directory_tree): Always call p~ MKISOFS.BCK)[MKISOFS.SRC]CHANGELOG.;1L6lstat 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 late.r 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. *[MKISOFS.SRC]CONFIG.H;2+,+. / 4 -)0123KPWO 56Π7 89*̞OGHJ/* #define USE_TERMIOS */ *[MKISOFS.SRC]DEFAULTS.H;2+,. / 4N -)0123KPWO 56C7f!C89*̞OGHJ/* * Header file defaults.h - assorted default values for character strings in * the volume descriptor. */ /* 14-May-1997 George Watson (watson_g@eisner.decus.org): add DECVMS sysid. */ #define PREPARER_DEFAULT NULL #define PUBLISHER_DEFAULT NULL #define APPID_DEFAULT NULL #define COPYRIGHT_DEFAULT NULL #define BIBLIO_DEFAULT NULL #define ABSTRACT_DEFAULT NULL #define VOLSET_ID_DEFAULT NULL #define VOLUME_ID_DEFAULT "CDROM" #ifdef __QNX__ #define SYSTEM_ID_DEFAULT "QNX" #endif #ifdef __osf__ #define SYSTEM_ID_DEFAULT "OSF" #endif #ifdef __VMS #define SYSTEM_ID_DEFAULT "DECVMS" #endif #ifndef SYSTEM_ID_DEFAULT #define SYSTEM_ID_DEFAULT "LINUX" #endif *[MKISOFS.SRC]DIAG.DIR;1+,=. / 4 -)0123 KPWO 56: 7r@89*̞OGHJIDUMP.C> ISODUMP.C? ISOINFO.C@ISOVFY.CA MAKEFILE.BREADME.C*[MKISOFS.SRC.DIAG]DUMP.C;1+,>. / 4 x-=0123KPWO 56V577X 89*̞OGHJ/* * File dump.c - dump a file/device both in hex and in ASCII. Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "../config.h" #include #ifdef USE_TERMIOS #include #include #else #include #endif #include FILE * infile; int file_addr; unsigned char buffer[256]; unsigned char search[64]; #define PAGE 256 #ifdef USE_TERMIOS struct termios savetty; struct termios newtty; #else struct termio savetty; struct termio newtty; #endif reset_tty(){ #ifdef USE_TERMIOS if(tcsetattr(0, TCSANOW, &savetty) == -1) #else if(ioctl(0, TCSETAF, &savetty)==-1) #endif { printf("cannot put tty into normal mode\n"); exit(1); } } set_tty(){ #ifdef USE_TERMIOS if(tcsetattr(0, TCSANOW, &newtty) == -1) #else if(ioctl(0, TCSETAF, &newtty)==-1) #endif { printf("cannot put tty into raw mode\n"); exit(1); } } /* Come here when we get a suspend signal from the terminal */ onsusp () { /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */ signal(SIGTTOU, SIG_IGN); reset_tty (); fflush (stdout); signal(SIGTTOU, SIG_DFL); /* Send the TSTP signal to suspend our process group */ signal(SIGTSTP, SIG_DFL); /* sigsetmask(0);*/ kill (0, SIGTSTP); /* Pause for station break */ /* We're back */ signal (SIGTSTP, onsusp); set_tty (); } crsr2(int row, int col){ printf("\033[%d;%dH",row,col); } showblock(int flag){ unsigned int k; int i, j; lseek(fileno(infile), file_addr, 0); read(fileno(infile), buffer, sizeof(buffer)); if(flag) { for(i=0;i<16;i++){ crsr2(i+3,1); printf("%8.8x ",file_addr+(i<<4)); for(j=15;j>=0;j--){ printf("%2.2x",buffer[(i<<4)+j]); if(!(j & 0x3)) printf(" "); }; for(j=0;j< 16;j++){ k = buffer[(i << 4) + j]; if(k >= ' ' && k < 0x80) printf("%c",k); else printf("."); }; } }; crsr2(20,1); printf(" Zone, zone offset: %6x %4.4x ",file_addr>>11, file_addr & 0x7ff); fflush(stdout); } getbyte() { char c1; c1 = buffer[file_addr & (PAGE-1)]; file_addr++; if ((file_addr & (PAGE-1)) == 0) showblock(0); return c1; } main(int argc, char * argv[]){ char c; int nbyte; int i,j; if(argc < 2) return 0; infile = fopen(argv[1],"rb"); for(i=0;i<30;i++) printf("\n"); file_addr = 0; /* Now setup the keyboard for single character input. */ #ifdef USE_TERMIOS if(tcgetattr(0, &savetty) == -1) #else if(ioctl(0, TCGETA, &savetty) == -1) #endif { printf("stdin must be a tty\n"); exit(1); } newtty=savetty; newtty.c_lflag&=~ICANON; newtty.c_lflag&=~ECHO; newtty.c_cc[VMIN]=1; set_tty(); signal(SIGTSTP, onsusp); do{ if(file_addr < 0) file_addr = 0; showblock(1); read (0, &c, 1); if (c == 'a') file_addr -= PAGE; if (c == 'b') file_addr += PAGE; if (c == 'g') { crsr2(20,1); printf("Enter new starting block (in hex):"); scanf("%x",&file_addr); file_addr = file_addr << 11; crsr2(20,1); printf(" "); }; if (c == 'f') { crsr2(20,1); printf("Enter new search string:"); fgets(search,sizeof(search),stdin); while(search[strlen(search)-1] == '\n') search[strlen(search)-1] = 0; crsr2(20,1); printf(" "); }; if (c == '+') { while(1==1){ while(1==1){ c = getbyte(&file_addr); if (c == search[0]) break; }; for (j=1;joA7m 89*̞OGHJ./* * File isodump.c - dump iso9660 directory information. * Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "../config.h" #include #ifdef USE_TERMIOS #include #include #else #include #endif #include FILE * infile; int file_addr; unsigned char buffer[2048]; unsigned char search[64]; #define PAGE sizeof(buffer) #define ISODCL(from, to) (to - from + 1) int isonum_731 (char * p) { return ((p[0] & 0xff) | ((p[1] & 0xff) << 8) | ((p[2] & 0xff) << 16) | ((p[3] & 0xff) << 24)); } int isonum_733 (unsigned char * p) { return (isonum_731 (p)); } struct iso_primary_descriptor { unsigned char type [ISODCL ( 1, 1)]; /* 711 */ unsigned char id [ISODCL ( 2, 6)]; unsigned char version [ISODCL ( 7, 7)]; /* 711 */ unsigned char unused1 [ISODCL ( 8, 8)]; unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */ unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */ unsigned char unused2 [ISODCL ( 73, 80)]; unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ unsigned char unused3 [ISODCL ( 89, 120)]; unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */ unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */ unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */ unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */ unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */ unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */ unsigned char publisher_id [ISODCL (319, 446)]; /* achars */ unsigned char preparer_id [ISODCL (447, 574)]; /* achars */ unsigned char application_id [ISODCL (575, 702)]; /* achars */ unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */ unsigned char unused4 [ISODCL (883, 883)]; unsigned char application_data [ISODCL (884, 1395)]; unsigned char unused5 [ISODCL (1396, 2048)]; }; struct iso_directory_record { unsigned char length [ISODCL (1, 1)]; /* 711 */ unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */ unsigned char extent [ISODCL (3, 10)]; /* 733 */ unsigned char size [ISODCL (11, 18)]; /* 733 */ unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */ unsigned char flags [ISODCL (26, 26)]; unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */ unsigned char interleave [ISODCL (28, 28)]; /* 711 */ unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ unsigned char name_len [ISODCL (33, 33)]; /* 711 */ unsigned char name [1]; }; #ifdef USE_TERMIOS struct termios savetty; struct termios newtty; #else struct termio savetty; struct termio newtty; #endif reset_tty(){ #ifdef USE_TERMIOS if(tcsetattr(0, TCSANOW, &savetty) == -1) #else if(ioctl(0, TCSETAF, &savetty)==-1) #endif { printf("cannot put tty into normal mode\n"); exit(1); } } set_tty(){ #ifdef USE_TERMIOS if(tcsetattr(0, TCSANOW, &newtty) == -1) #else if(ioctl(0, TCSETAF, &newtty)==-1) #endif { printf("cannot put tty into raw mode\n"); exit(1); } } /* Come here when we get a suspend signal from the terminal */ onsusp () { /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */ signal(SIGTTOU, SIG_IGN); reset_tty (); fflush (stdout); signal(SIGTTOU, SIG_DFL); /* Send the TSTP signal to suspend our process group */ signal(SIGTSTP, SIG_DFL); /* sigsetmask(0);*/ kill (0, SIGTSTP); /* Pause for station break */ /* We're back */ signal (SIGTSTP, onsusp); set_tty (); } crsr2(int row, int col){ printf("\033[%d;%dH",row,col); } int parse_rr(unsigned char * pnt, int len, int cont_flag) { int slen; int ncount; int extent; int cont_extent, cont_offset, cont_size; int flag1, flag2; unsigned char *pnts; char symlink[1024]; int goof; /* printf(" RRlen=%d ", len); */ symlink[0] = 0; cont_extent = cont_offset = cont_size = 0; ncount = 0; flag1 = flag2 = 0; while(len >= 4){ if(ncount) printf(","); else printf("["); printf("%c%c", pnt[0], pnt[1]); if(pnt[3] != 1) { printf("**BAD RRVERSION"); return; }; ncount++; if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1; if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2; if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4; if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8; if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16; if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32; if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64; if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128; if(strncmp(pnt, "PX", 2) == 0) { extent = isonum_733(pnt+12); printf("=%x", extent); }; if(strncmp(pnt, "CE", 2) == 0) { cont_extent = isonum_733(pnt+4); cont_offset = isonum_733(pnt+12); cont_size = isonum_733(pnt+20); printf("=[%x,%x,%d]", cont_extent, cont_offset, cont_size); }; if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) { extent = isonum_733(pnt+4); printf("=%x", extent); }; if(strncmp(pnt, "SL", 2) == 0) { int cflag; cflag = pnt[4]; pnts = pnt+5; slen = pnt[2] - 5; while(slen >= 1){ switch(pnts[0] & 0xfe){ case 0: strncat(symlink, pnts+2, pnts[1]); break; case 2: strcat (symlink, "."); break; case 4: strcat (symlink, ".."); break; case 8: if((pnts[0] & 1) == 0)strcat (symlink, "/"); break; case 16: strcat(symlink,"/mnt"); printf("Warning - mount point requested"); break; case 32: strcat(symlink,"kafka"); printf("Warning - host_name requested"); break; default: printf("Reserved bit setting in symlink", goof++); break; }; if((pnts[0] & 0xfe) && pnts[1] != 0) { printf("Incorrect length in symlink component"); }; if((pnts[0] & 1) == 0) strcat(symlink,"/"); slen -= (pnts[1] + 2); pnts += (pnts[1] + 2); }; if(cflag) printf("+"); printf("=%s", symlink); symlink[0] = 0; }; len -= pnt[2]; pnt += pnt[2]; if(len <= 3 && cont_extent) { unsigned char sector[2048]; lseek(fileno(infile), cont_extent << 11, 0); read(fileno(infile), sector, sizeof(sector)); flag2 |= parse_rr(§or[cont_offset], cont_size, 1); }; }; if(ncount) printf("]"); if (!cont_flag && flag1 != flag2) printf("Flag %x != %x", flag1, flag2, goof++); return flag2; } int dump_rr(struct iso_directory_record * idr) { int len; unsigned char * pnt; len = idr->length[0] & 0xff; len -= sizeof(struct iso_directory_record); len += sizeof(idr->name); len -= idr->name_len[0]; pnt = (unsigned char *) idr; pnt += sizeof(struct iso_directory_record); pnt -= sizeof(idr->name); pnt += idr->name_len[0]; if((idr->name_len[0] & 1) == 0){ pnt++; len--; }; parse_rr(pnt, len, 0); } showblock(int flag){ unsigned int k; int i, j; int line; struct iso_directory_record * idr; lseek(fileno(infile), file_addr, 0); read(fileno(infile), buffer, sizeof(buffer)); for(i=0;i<60;i++) printf("\n"); fflush(stdout); i = line = 0; if(flag) { while(1==1){ crsr2(line+3,1); idr = (struct iso_directory_record *) &buffer[i]; if(idr->length[0] == 0) break; printf("%3d ", idr->length[0]); printf("[%2d] ", idr->volume_sequence_number[0]); printf("%5x ", isonum_733(idr->extent)); printf("%8d ", isonum_733(idr->size)); printf ((idr->flags[0] & 2) ? "*" : " "); if(idr->name_len[0] == 1 && idr->name[0] == 0) printf(". "); else if(idr->name_len[0] == 1 && idr->name[0] == 1) printf(".. "); else { for(j=0; jname_len[0]; j++) printf("%c", idr->name[j]); for(j=0; j<14 -idr->name_len[0]; j++) printf(" "); }; dump_rr(idr); printf("\n"); i += buffer[i]; if (i > 2048 - sizeof(struct iso_directory_record)) break; line++; }; }; printf("\n"); printf(" Zone, zone offset: %6x %4.4x ",file_addr>>11, file_addr & 0x7ff); fflush(stdout); } getbyte() { char c1; c1 = buffer[file_addr & (PAGE-1)]; file_addr++; if ((file_addr & (PAGE-1)) == 0) showblock(0); return c1; } main(int argc, char * argv[]){ char c; char buffer[2048]; int nbyte; int i,j; struct iso_primary_descriptor ipd; struct iso_directory_record * idr; if(argc < 2) return 0; infile = fopen(argv[1],"rb"); file_addr = 16 << 11; lseek(fileno(infile), file_addr, 0); read(fileno(infile), &ipd, sizeof(ipd)); idr = (struct iso_directory_record *) &ipd.root_directory_record; file_addr = isonum_733(idr->extent); file_addr = file_addr << 11; /* Now setup the keyboard for single character input. */ #ifdef USE_TERMIOS if(tcgetattr(0, &savetty) == -1) #else if(ioctl(0, TCGETA, &savetty) == -1) #endif { printf("stdin must be a tty\n"); exit(1); } newtty=savetty; newtty.c_lflag&=~ICANON; newtty.c_lflag&=~ECHO; newtty.c_cc[VMIN]=1; set_tty(); signal(SIGTSTP, onsusp); do{ if(file_addr < 0) file_addr = 0; showblock(1); read (0, &c, 1); if (c == 'a') file_addr -= PAGE; if (c == 'b') file_addr += PAGE; if (c == 'g') { crsr2(20,1); printf("Enter new starting block (in hex):"); scanf("%x",&file_addr); file_addr = file_addr << 11; crsr2(20,1); printf(" "); }; if (c == 'f') { crsr2(20,1); printf("Enter new search string:"); fgets(search,sizeof(search),stdin); while(search[strlen(search)-1] == '\n') search[strlen(search)-1] = 0; crsr2(20,1); printf(" "); }; if (c == '+') { while(1==1){ while(1==1){ c = getbyte(&file_addr); if (c == search[0]) break; }; for (j=1;j outfile * To generate a "find" like list of files: * isoinfo -f -i imagefile */ #include "../config.h" #include #include #include #ifdef __svr4__ #include #else extern int optind; extern char *optarg; /* extern int getopt (int __argc, char **__argv, char *__optstring); */ #endif FILE * infile; int use_rock = 0; int do_listing = 0; int do_find = 0; char * xtract = 0; struct stat fstat_buf; char name_buf[256]; char xname[256]; unsigned char date_buf[9]; unsigned char buffer[2048]; #define PAGE sizeof(buffer) #define ISODCL(from, to) (to - from + 1) int isonum_731 (char * p) { return ((p[0] & 0xff) | ((p[1] & 0xff) << 8) | ((p[2] & 0xff) << 16) | ((p[3] & 0xff) << 24)); } int isonum_733 (unsigned char * p) { return (isonum_731 (p)); } struct iso_primary_descriptor { unsigned char type [ISODCL ( 1, 1)]; /* 711 */ unsigned char id [ISODCL ( 2, 6)]; unsigned char version [ISp~ MKISOFS.BCK@=[MKISOFS.SRC.DIAG]ISOINFO.C;1z.ODCL ( 7, 7)]; /* 711 */ unsigned char unused1 [ISODCL ( 8, 8)]; unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */ unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */ unsigned char unused2 [ISODCL ( 73, 80)]; unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ unsigned char unused3 [ISODCL ( 89, 120)]; unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */ unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */ unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */ unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */ unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */ unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */ unsigned char publisher_id [ISODCL (319, 446)]; /* achars */ unsigned char preparer_id [ISODCL (447, 574)]; /* achars */ unsigned char application_id [ISODCL (575, 702)]; /* achars */ unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */ unsigned char unused4 [ISODCL (883, 883)]; unsigned char application_data [ISODCL (884, 1395)]; unsigned char unused5 [ISODCL (1396, 2048)]; }; struct iso_directory_record { unsigned char length [ISODCL (1, 1)]; /* 711 */ unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */ unsigned char extent [ISODCL (3, 10)]; /* 733 */ unsigned char size [ISODCL (11, 18)]; /* 733 */ unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */ unsigned char flags [ISODCL (26, 26)]; unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */ unsigned char interleave [ISODCL (28, 28)]; /* 711 */ unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ unsigned char name_len [ISODCL (33, 33)]; /* 711 */ unsigned char name [1]; }; int parse_rr(unsigned char * pnt, int len, int cont_flag) { int slen; int ncount; int extent; int cont_extent, cont_offset, cont_size; int flag1, flag2; unsigned char *pnts; char symlink[1024]; int goof; symlink[0] = 0; cont_extent = cont_offset = cont_size = 0; ncount = 0; flag1 = flag2 = 0; while(len >= 4){ if(pnt[3] != 1) { printf("**BAD RRVERSION"); return; }; ncount++; if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1; if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2; if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4; if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8; if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16; if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32; if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64; if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128; if(strncmp(pnt, "PX", 2) == 0) { fstat_buf.st_mode = isonum_733(pnt+4); fstat_buf.st_nlink = isonum_733(pnt+12); fstat_buf.st_uid = isonum_733(pnt+20); fstat_buf.st_gid = isonum_733(pnt+28); }; if(strncmp(pnt, "NM", 2) == 0) { strncpy(name_buf, pnt+5, pnt[2] - 5); name_buf[pnt[2] - 5] = 0; } if(strncmp(pnt, "CE", 2) == 0) { cont_extent = isonum_733(pnt+4); cont_offset = isonum_733(pnt+12); cont_size = isonum_733(pnt+20); }; if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) { extent = isonum_733(pnt+4); }; if(strncmp(pnt, "SL", 2) == 0) { int cflag; cflag = pnt[4]; pnts = pnt+5; slen = pnt[2] - 5; while(slen >= 1){ switch(pnts[0] & 0xfe){ case 0: strncat(symlink, pnts+2, pnts[1]); break; case 2: strcat (symlink, "."); break; case 4: strcat (symlink, ".."); break; case 8: if((pnts[0] & 1) == 0)strcat (symlink, "/"); break; case 16: strcat(symlink,"/mnt"); printf("Warning - mount point requested"); break; case 32: strcat(symlink,"kafka"); printf("Warning - host_name requested"); break; default: printf("Reserved bit setting in symlink", goof++); break; }; if((pnts[0] & 0xfe) && pnts[1] != 0) { printf("Incorrect length in symlink component"); }; if((pnts[0] & 1) == 0) strcat(symlink,"/"); slen -= (pnts[1] + 2); pnts += (pnts[1] + 2); if(xname[0] == 0) strcpy(xname, "-> "); strcat(xname, symlink); }; symlink[0] = 0; }; len -= pnt[2]; pnt += pnt[2]; if(len <= 3 && cont_extent) { unsigned char sector[2048]; lseek(fileno(infile), cont_extent << 11, 0); read(fileno(infile), sector, sizeof(sector)); flag2 |= parse_rr(§or[cont_offset], cont_size, 1); }; }; return flag2; } int dump_rr(struct iso_directory_record * idr) { int len; unsigned char * pnt; len = idr->length[0] & 0xff; len -= sizeof(struct iso_directory_record); len += sizeof(idr->name); len -= idr->name_len[0]; pnt = (unsigned char *) idr; pnt += sizeof(struct iso_directory_record); pnt -= sizeof(idr->name); pnt += idr->name_len[0]; if((idr->name_len[0] & 1) == 0){ pnt++; len--; }; parse_rr(pnt, len, 0); } struct todo { struct todo * next; char * name; int extent; int length; }; struct todo * todo_idr = NULL; char * months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; dump_stat() { int i; char outline[80]; memset(outline, ' ', sizeof(outline)); if(S_ISREG(fstat_buf.st_mode)) outline[0] = '-'; else if(S_ISDIR(fstat_buf.st_mode)) outline[0] = 'd'; else if(S_ISLNK(fstat_buf.st_mode)) outline[0] = 'l'; else if(S_ISCHR(fstat_buf.st_mode)) outline[0] = 'c'; else if(S_ISBLK(fstat_buf.st_mode)) outline[0] = 'b'; else if(S_ISFIFO(fstat_buf.st_mode)) outline[0] = 'f'; else if(S_ISSOCK(fstat_buf.st_mode)) outline[0] = 's'; else outline[0] = '?'; memset(outline+1, '-', 9); if( fstat_buf.st_mode & S_IRUSR ) outline[1] = 'r'; if( fstat_buf.st_mode & S_IWUSR ) outline[2] = 'w'; if( fstat_buf.st_mode & S_IXUSR ) outline[3] = 'x'; if( fstat_buf.st_mode & S_IRGRP ) outline[4] = 'r'; if( fstat_buf.st_mode & S_IWGRP ) outline[5] = 'w'; if( fstat_buf.st_mode & S_IXGRP ) outline[6] = 'x'; if( fstat_buf.st_mode & S_IROTH ) outline[7] = 'r'; if( fstat_buf.st_mode & S_IWOTH ) outline[8] = 'w'; if( fstat_buf.st_mode & S_IXOTH ) outline[9] = 'x'; sprintf(outline+11, "%3d", fstat_buf.st_nlink); sprintf(outline+15, "%4o", fstat_buf.st_uid); sprintf(outline+20, "%4o", fstat_buf.st_gid); sprintf(outline+33, "%8d", fstat_buf.st_size); memcpy(outline+42, months[date_buf[1]-1], 3); sprintf(outline+46, "%2d", date_buf[2]); sprintf(outline+49, "%4d", date_buf[0]+1900); for(i=0; i<54; i++) if(outline[i] == 0) outline[i] = ' '; outline[54] = 0; printf("%s %s %s\n", outline, name_buf, xname); } extract_file(struct iso_directory_record * idr) { int extent, len, tlen; unsigned char buff[2048]; extent = isonum_733(idr->extent); len = isonum_733(idr->size); while(len > 0) { lseek(fileno(infile), extent << 11, 0); tlen = (len > sizeof(buff) ? sizeof(buff) : len); read(fileno(infile), buff, tlen); len -= tlen; extent++; write(1, buff, tlen); } } parse_dir(char * rootname, int extent, int len){ unsigned int k; char testname[256]; struct todo * td; int i, j; struct iso_directory_record * idr; if( do_listing) printf("\nDirectory listing of %s\n", rootname); while(len > 0 ) { lseek(fileno(infile), extent << 11, 0); read(fileno(infile), buffer, sizeof(buffer)); len -= sizeof(buffer); extent++; i = 0; while(1==1){ idr = (struct iso_directory_record *) &buffer[i]; if(idr->length[0] == 0) break; memset(&fstat_buf, 0, sizeof(fstat_buf)); name_buf[0] = xname[0] = 0; fstat_buf.st_size = isonum_733(idr->size); if( idr->flags[0] & 2) fstat_buf.st_mode |= S_IFDIR; else fstat_buf.st_mode |= S_IFREG; if(idr->name_len[0] == 1 && idr->name[0] == 0) strcpy(name_buf, "."); else if(idr->name_len[0] == 1 && idr->name[0] == 1) strcpy(name_buf, ".."); else { strncpy(name_buf, idr->name, idr->name_len[0]); name_buf[idr->name_len[0]] = 0; }; memcpy(date_buf, idr->date, 9); if(use_rock) dump_rr(idr); if( (idr->flags[0] & 2) != 0 && (idr->name_len[0] != 1 || (idr->name[0] != 0 && idr->name[0] != 1))) { /* * Add this directory to the todo list. */ td = todo_idr; if( td != NULL ) { while(td->next != NULL) td = td->next; td->next = (struct todo *) malloc(sizeof(*td)); td = td->next; } else { todo_idr = td = (struct todo *) malloc(sizeof(*td)); } td->next = NULL; td->extent = isonum_733(idr->extent); td->length = isonum_733(idr->size); td->name = (char *) malloc(strlen(rootname) + strlen(name_buf) + 2); strcpy(td->name, rootname); strcat(td->name, name_buf); strcat(td->name, "/"); } else { strcpy(testname, rootname); strcat(testname, name_buf); if(xtract && strcmp(xtract, testname) == 0) { extract_file(idr); } } if( do_find && (idr->name_len[0] != 1 || (idr->name[0] != 0 && idr->name[0] != 1))) { strcpy(testname, rootname); strcat(testname, name_buf); printf("%s\n", testname); } if(do_listing) dump_stat(); i += buffer[i]; if (i > 2048 - sizeof(struct iso_directory_record)) break; } } } usage() { fprintf(stderr, "isoinfo -i filename [-l] [-R] [-x filename] [-f]\n"); } main(int argc, char * argv[]){ char c; char buffer[2048]; int nbyte; char * filename = NULL; int i,j; struct todo * td; struct iso_primary_descriptor ipd; struct iso_directory_record * idr; if(argc < 2) return 0; while ((c = getopt(argc, argv, "i:Rlx:f")) != EOF) switch (c) { case 'f': do_find++; break; case 'R': use_rock++; break; case 'l': do_listing++; break; case 'i': filename = optarg; break; case 'x': xtract = optarg; break; default: usage(); exit(1); } if( filename == NULL ) { fprintf(stderr, "Error - file not specified\n"); exit(1); } infile = fopen(filename,"rb"); if( infile == NULL ) { fprintf(stderr,"Unable to open file %s\n", filename); exit(1); } lseek(fileno(infile), 16<<11, 0); read(fileno(infile), &ipd, sizeof(ipd)); idr = (struct iso_directory_record *) &ipd.root_directory_record; parse_dir("/", isonum_733(idr->extent), isonum_733(idr->size)); td = todo_idr; while(td) { parse_dir(td->name, td->extent, td->length); td = td->next; } fclose(infile); } *[MKISOFS.SRC.DIAG]ISOVFY.C;1+,A.$/ 4$ -=0123KPWO%56[7 89*̞OGHJ:/* * File isovfy.c - verify consistency of iso9660 filesystem. * Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include FILE * infile; #define PAGE sizeof(buffer) #define ISODCL(from, to) (to - from + 1) struct iso_primary_descriptor { unsigned char type [ISODCL ( 1, 1)]; /* 711 */ unsigned char id [ISODCL ( 2, 6)]; unsigned char version [ISODCL ( 7, 7)]; /* 711 */ unsigned char unused1 [ISODCL ( 8, 8)]; unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */ unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */ unsigned char unused2 [ISODCL ( 73, 80)]; unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ unsigned char unused3 [ISODCL ( 89, 120)]; unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */ unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */ unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */ unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */ unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */ unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */ unsigned char publisher_id [ISODCL (319, 446)]; /* achars */ unsigned char preparer_id [ISODCL (447, 574)]; /* achars */ unsigned char application_id [ISODCL (575, 702)]; /* achars */ unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */ unsigned char unused4 [ISODCL (883, 883)]; unsigned char application_data [ISODCL (884, 1395)]; unsigned char unused5 [ISODCL (1396, 2048)]; }; struct iso_directory_record { unsigned char length [ISODCL (1, 1)]; /* 711 */ unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */ unsigned char extent [ISODCL (3, 10)]; /* 733 */ unsigned char size [ISODCL (11, 18)]; /* 733 */ unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */ unsigned char flags [ISODCL (26, 26)]; unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */ unsigned char interleave [ISODCL (28, 28)]; /* 711 */ unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ unsigned char name_len [ISODCL (33, 33)]; /* 711 */ unsigned char name [38]; }; int isonum_721 (char * p) { return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); } int isonum_731 (char * p) { return ((p[0] & 0xff) | ((p[1] & 0xff) << 8) | ((p[2] & 0xff) << 16) | ((p[3] & 0xff) << 24)); } int isonum_722 (char * p) { return ((p[1] & 0xff) | ((p[0] & 0xff) << 8)); } int isonum_732 (char * p) { return ((p[3] & 0xff) | ((p[2] & 0xff) << 8) | ((p[1] & 0xff) << 16) | ((p[0] & 0xff) << 24)); } int isonum_733 (unsigned char * p) { return (isonum_731 (p)); } char lbuffer[1024]; int iline; int rr_goof; int dump_rr(struct iso_directory_record * idr){ int len; char * pnt; len = idr->length[0] & 0xff; len -= (sizeof(struct iso_directory_record) - sizeof(idr->name)); len -= idr->name_len[0]; pnt = (char *) idr; pnt += (sizeof(struct iso_directory_record) - sizeof(idr->name)); pnt += idr->name_len[0]; if((idr->name_len[0] & 1) == 0){ pnt++; len--; }; rr_goof = 0; parse_rr(pnt, len, 0); return rr_goof; } int parse_rr(unsigned char * pnt, int len, int cont_flag) { int slen; int ncount; int flag1, flag2; int extent; unsigned char *pnts; int cont_extent, cont_offset, cont_size; char symlink[1024]; iline += sprintf(lbuffer+iline," RRlen=%d ", len); cont_extent = cont_offset = cont_size = 0; symlink[0] = 0; ncount = 0; flag1 = flag2 = 0; while(len >= 4){ if(ncount) iline += sprintf(lbuffer+iline,","); else iline += sprintf(lbuffer+iline,"["); iline += sprintf(lbuffer+iline,"%c%c", pnt[0], pnt[1]); if(pnt[0] < 'A' || pnt[0] > 'Z' || pnt[1] < 'A' || pnt[1] > 'Z') { iline += sprintf(lbuffer+iline,"**BAD SUSP %d %d]", pnt[0], pnt[1], rr_goof++); return flag2; }; if(pnt[3] != 1) { iline += sprintf(lbuffer+iline,"**BAD RRVERSION", rr_goof++); return flag2; }; ncount++; if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1; if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2; if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4; if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8; if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16; if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32; if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64; if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128; if(strncmp(pnt, "CE", 2) == 0) { cont_extent = isonum_733(pnt+4); cont_offset = isonum_733(pnt+12); cont_size = isonum_733(pnt+20); iline += sprintf(lbuffer+iline, "=[%x,%x,%d]", cont_extent, cont_offset, cont_size); }; if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) { extent = isonum_733(pnt+4); iline += sprintf(lbuffer+iline,"=%x", extent); if(extent == 0) rr_goof++; }; if(strncmp(pnt, "SL", 2) == 0) { pnts = pnt+5; slen = pnt[2] - 5; while(slen >= 1){ switch(pnts[0] & 0xfe){ case 0: strncat(symlink, pnts+2, pnts[1]); break; case 2: strcat (symlink, "."); break; case 4: strcat (symlink, ".."); break; case 8: strcat (symlink, "/"); break; case 16: strcat(symlink,"/mnt"); iline += sprintf(lbuffer+iline,"Warning - mount point requested"); break; case 32: strcat(symlink,"kafka"); iline += sprintf(lbuffer+iline,"Warning - host_name requested"); break; default: iline += sprintf(lbuffer+iline,"Reserved bit setting in symlink", rr_goof++); break; }; if((pnts[0] & 0xfe) && pnts[1] != 0) { iline += sprintf(lbuffer+iline,"Incorrect length in symlink component"); }; if((pnts[0] & 1) == 0) strcat(symlink,"/"); slen -= (pnts[1] + 2); pnts += (pnts[1] + 2); }; if(symlink[0] != 0) { iline += sprintf(lbuffer+iline,"=%s", symlink); symlink[0] = 0; } }; len -= pnt[2]; pnt += pnt[2]; if(len <= 3 && cont_extent) { unsigned char sector[2048]; lseek(fileno(infile), cont_extent << 11, 0); read(fileno(infile), sector, sizeof(sector)); flag2 |= parse_rr(§or[cont_offset], cont_size, 1); }; }; if(ncount) iline += sprintf(lbuffer+iline,"]"); if (!cont_flag && flag1 && flag1 != flag2) iline += sprintf(lbuffer+iline,"Flag %x != %x", flag1, flag2, rr_goof++); return flag2; } int dir_count = 0; int dir_size_count = 0; int ngoof = 0; check_tree(int file_addr, int file_size, int parent_addr){ unsigned char buffer[2048]; unsigned int k; int rflag; int i, i1, j, goof; int extent, size; int line; int orig_file_addr, parent_file_addr; struct iso_directory_record * idr; i1 = 0; orig_file_addr = file_addr >> 11; /* Actual extent of this directory */ parent_file_addr = parent_addr >> 11; if((dir_count % 100) == 0) printf("[%d %d]\n", dir_count, dir_size_count); #if 0 printf("Starting directory %d %d %d\n", file_addr, file_size, parent_addr); #endif dir_count++; dir_size_count += file_size >> 11; if(file_size & 0x3ff) printf("********Directory has unusual size\n"); for(k=0; k < (file_size >> 11); k++){ lseek(fileno(infile), file_addr, 0); read(fileno(infile), buffer, sizeof(buffer)); i = 0; while(1==1){ goof = iline=0; idr = (struct iso_directory_record *) &buffer[i]; if(idr->length[0] == 0) break; iline += sprintf(&lbuffer[iline],"%3d ", idr->length[0]); extent = isonum_733(idr->extent); size = isonum_733(idr->size); iline += sprintf(&lbuffer[iline],"%5x ", extent); iline += sprintf(&lbuffer[iline],"%8d ", size); iline += sprintf (&lbuffer[iline], "%c", (idr->flags[0] & 2) ? '*' : ' '); if(idr->name_len[0] > 33 || idr->name_len[0] < 0) iline += sprintf(&lbuffer[iline],"File name length=(%d)", idr->name_len[0], goof++); else if(idr->name_len[0] == 1 && idr->name[0] == 0) { iline += sprintf(&lbuffer[iline],". "); rflag = 0; if(orig_file_addr !=isonum_733(idr->extent)) iline += sprintf(&lbuffer[iline],"***** Directory has null extent.", goof++); if(i1) iline += sprintf(&lbuffer[iline],"***** . not first entry.", rr_goof++); } else if(idr->name_len[0] == 1 && idr->name[0] == 1) { iline += sprintf(&lbuffer[iline],".. "); rflag = 0; if(parent_file_addr !=isonum_733(idr->extent)) iline += sprintf(&lbuffer[iline],"***** Directory has null extent.", goof++); if(i1 != 1) iline += sprintf(&lbuffer[iline],"***** .. not second entry.", rr_goof++); } else { if(i1 < 2) iline += sprintf(&lbuffer[iline]," Improper sorting.", rr_goof++); for(j=0; jname_len[0]; j++) iline += sprintf(&lbuffer[iline],"%c", idr->name[j]); for(j=0; j<14 -idr->name_len[0]; j++) iline += sprintf(&lbuffer[iline]," "); rflag = 1; }; if(size && extent == 0) iline += sprintf(&lbuffer[iline],"****Extent==0, size != 0", goof++); #if 0 /* This is apparently legal. */ if(size == 0 && extent) iline += sprintf(&lbuffer[iline],"****Extent!=0, size == 0", goof++); #endif if(idr->flags[0] & 0xfd) iline += sprintf(&lbuffer[iline],"Flags=(%x) ", idr->flags[0], goof++); if(idr->flags[0] & 0xfd) iline += sprintf(&lbuffer[iline],"Flags=(%x) ", idr->flags[0], goof++); if(idr->interleave[0]) iline += sprintf(&lbuffer[iline],"Interleave=(%d) ", idr->interleave[0], goof++); if(idr->file_unit_size[0]) iline += sprintf(&lbuffer[iline],"File unit size=(%d) ", idr->file_unit_size[0], goof++); if(idr->volume_sequence_number[0] != 1) iline += sprintf(&lbuffer[iline],"Volume sequence number=(%d) ", idr->volume_sequence_number[0], goof++); goof += dump_rr(idr); iline += sprintf(&lbuffer[iline],"\n"); if(goof){ ngoof++; lbuffer[iline++] = 0; printf("%x: %s", orig_file_addr, lbuffer); }; if(rflag && (idr->flags[0] & 2)) check_tree((isonum_733(idr->extent)) << 11, isonum_733(idr->size), orig_file_addr << 11); i += buffer[i]; i1++; if (i > 2048 - sizeof(struct iso_directory_record)) break; }; file_addr += sizeof(buffer); }; fflush(stdout); } /* This function simply dumps the contents of the path tables. No consistency checking takes place, although this would proably be a good idea. */ struct path_table_info{ char * name; unsigned int extent; unsigned short index; unsigned short parent; }; check_path_tables(int typel_extent, int typem_extent, int path_table_size){ int file_addr; int count; int j; char * pnt; char * typel, *typem; /* Now read in the path tables */ typel = (char *) malloc(path_table_size); lseek(fileno(infile), typel_extent << 11, 0); read(fileno(infile), typel, path_table_size); typem = (char *) malloc(path_table_size); lseek(fileno(infile), typem_extent << 11, 0); read(fileno(infile), typem, path_table_size); j = path_table_size; pnt = typel; count = 1; while(j){ int namelen, extent, index; char name[32]; namelen = *pnt++; pnt++; extent = isonum_731(pnt); pnt += 4; index = isonum_721(pnt); pnt+= 2; j -= 8+namelen; memset(name, 0, sizeof(name)); strncpy(name, pnt, namelen); pnt += namelen; if(j & 1) { j--; pnt++;}; printf("%4.4d %4.4d %8.8x %s\n",count++, index, extent, name); }; j = path_table_size; pnt = typem; count = 1; while(j){ int namelen, extent, index; char name[32]; namelen = *pnt++; pnt++; extent = isonum_732(pnt); pnt += 4; index = isonum_722(pnt); pnt+= 2; j -= 8+namelen; memset(name, 0, sizeof(name)); strncpy(name, pnt, namelen); pnt += namelen; if(j & 1) { j--; pnt++;}; printf("%4.4d %4.4d %8.8x %s\n", count++, index, extent, name); }; } main(int argc, char * argv[]){ int file_addr, file_size; char c; int nbyte; struct iso_primary_descriptor ipd; struct iso_directory_record * idr; int typel_extent, typem_extent; int path_table_size; int i,j; if(argc < 2) return 0; infile = fopen(argv[1],"rb"); file_addr = 16 << 11; lseek(fileno(infile), file_addr, 0); read(fileno(infile), &ipd, sizeof(ipd)); idr = (struct iso_directory_record *) &ipd.root_directory_record; file_addr = isonum_733(idr->extent); file_size = isonum_733(idr->size); printf("Root at extent %x, %d bytes\n", file_addr, file_size); file_addr = file_addr << 11; check_tree(file_addr, file_size, file_addr); typel_extent = isonum_731(ipd.type_l_path_table); typem_extent = isonum_732(ipd.type_m_path_table); path_table_size = isonum_733(ipd.path_table_size); /* Enable this to get the dump of the path tables */ #if 0 check_path_tables(typel_extent, typem_extent, path_table_size); #endif fclose(infile); if(!ngoof) printf("No errors found\n"); } *[MKISOFS.SRC.DIAG]MAKEFILE.;1+,B. / 4 -=0123KPWO 56]p+b7E 89*̞OGHJ#CC = gcc CC = cc -traditional all: dump isodump isovfy isoinfo:isoinfo.c ${CC} -g -o isoinfo isoinfo.c dump:dump.c ${CC} -o dump dump.c isodump:isodump.c ${CC} -o isodump isodump.c isovfy:isovfy.c ${CC} -o isovfy isovfy.c clean: rm -f dump isodump isovfy isoinfo *[MKISOFS.SRC.DIAG]README.;1+,C. / 4 R-=0123KPWO 56'㏗7Y 89*̞OGHJ I am enclosing 3 test programs that I use to verify the integrity of an iso9660 disc. The first one (isodump) is pretty simple - it dumps to the screen the contents of the various directories. The second one (isovfy) goes through and looks for problems of one kind or another. To use, type something like "./isodump /dev/ramdisk" or "./isodump /dev/scd0", depending upon where the iso9660 disc is. It starts by displaying the files in the first sector of the root directory. It has some pretty simple one letter commands that you can use to traverse the directory tree. a - move back one sector. b - move forward one sector. g - go to new logical sector. q - quit The a and b commands do not try and stop you from going past the beginning or end of a sector, and the g command does not have any way of knowing whether the sector you request is actually a directory or not. The output is displayed in several columns. The first column is the total length of the directory record for the file. The second column (in [] brackets) is the volume number. Next comes the starting extent number (in hex), and then comes the file size in bytes. Then cones the filename (not the Rock Ridge version), and this is preceeded by an "*" if the file is a directory. After this is a summary of the Rock Ridge fields present along with a display of the translation of the symbolic link name if the SL Rock Ridge record is present. I tailored this program for debugging some of the problems that I was having earlier. The idea is that you can tailor it to test for problems that you might be having, so it is not intended as a be-all and end-all dump program. If you move to a sector that does not contain directory information, the results are unpredictable. The second program, isovfy, is run in the same way as isodump, except that you do not have to do much except let it run. I have it written to verify all kinds of different things, and as people find other sorts of problems other tests could be added. The third program, dump.c, basically does a hexdump of the cd. This is screen oriented, and there are some simple commands: a - move back one sector. b - move forward one sector. f - enter new search string. + - search forward for search string. g - go to new logical sector. q - quit Note that with the 'g' command, sectors are always given in hex, and represent 2048 byte sectors (as on the cdrom). If you know how to decode a raw iso9660 directory, you can pick out the starting extent number from the hexdump and know where to go from there. The starting extent appears something like 30 bytes prior to the start of the iso9660 (not Rock Ridge) filename, and it appears in a 7.3.3 format (meaning that it occupies 8 bytes, 4 in little endian format, and 4 in big endian format). Thus you should see a mirror image of the bytes when looking at the extent number. The isovfy program can also dump the contents of the path tables, but this capability is commented out right now. Feel free to enable this to see what is in the tables. Ultimately I may fix it so that this checks the integrity of the tables as well. The isovfy program gives warnings about things like files that have a size of 0 but have an extent number assigned. The mkisofs program should never do this, but the YM software does leave these around. I think it is probably harmless in the YM case.~ *[MKISOFS.SRC]EXCLUDE.C;2+,.. / 4L -)0123KPWO 56{֡17 89*̞OGHJ~ MKISOFS.BCK.)[MKISOFS.SRC]EXCLUDE.C;2L /* * 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 #include #include /* this allows for 1000 entries to be excluded ... */ #define MAXEXCL 1000 static char *excl[MAXEXCL]; void exclude(char *fn) { register int i; for(i = 0; excl[i] != NULL && 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) { fprintf(stderr, "Can't allocate memory for excluded filename\n"); return; } strcpy(excl[i], fn); } int is_excluded(char *fn) /* very dumb search method ... */ { register int i; for(i = 0; excl[i] != NULL && i < MAXEXCL; i++) { if(strcmp(excl[i], fn) == 0) return 1; /* found -> excluded filename */ } return 0; /* not found -> not excluded */ } *[MKISOFS.SRC]EXCLUDE.H;2+,/. / 4J -)0123KPWO 56M-78 89*̞OGHJ/* * 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 *); int is_excluded(char *); *[MKISOFS.SRC]HASH.C;2+,0./ 4L -)0123KPWO56537u 89*̞OGHJ/* * File hash.c - generate hash tables for iso9660 filesystem. Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "mkisofs.h" #define NR_HASH 1024 #define HASH_FN(DEV, INO) ((DEV + INO + (INO >> 2) + (INO << 8)) % NR_HASH) static struct file_hash *hash_table[NR_HASH] = {NULL, }; 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) { fprintf(stderr, "Non zero-length file assigned zero extent.\n"); exit(1); } if(spnt->dev == (dev_t)UNCACHED_DEVICE || spnt->inode == UNCACHED_INODE) return; hash_number = HASH_FN((unsigned int)spnt->dev, (unsigned int)spnt->inode); #if 0 if(verbose) fprintf(stderr, "%s ", spnt->name); #endif s_hash = (struct file_hash *)e_malloc(sizeof(struct file_hash)); s_hash->next = hash_table[hash_number]; s_hash->inode = spnt->inode; s_hash->dev = spnt->dev; s_hash->starting_block = spnt->starting_block; s_hash->size = spnt->size; hash_table[hash_number] = s_hash; } struct file_hash *find_hash(dev_t dev, ino_t inode) { struct file_hash *spnt; unsigned int hash_number; hash_number = HASH_FN((unsigned int)dev, (unsigned int)inode); if(dev == (dev_t)UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL; spnt = hash_table[hash_number]; while(spnt) { if(spnt->inode == inode && spnt->dev == dev) return spnt; spnt = spnt->next; } return NULL; } static struct file_hash *directory_hash_table[NR_HASH] = {NULL, }; void add_directory_hash(dev_t dev, ino_t inode) { struct file_hash *s_hash; unsigned int hash_number; if(dev == (dev_t)UNCACHED_DEVICE || inode == UNCACHED_INODE) return; hash_number = HASH_FN((unsigned int)dev, (unsigned int)inode); s_hash = (struct file_hash *)e_malloc(sizeof(struct file_hash)); s_hash->next = directory_hash_table[hash_number]; s_hash->inode = inode; s_hash->dev = dev; directory_hash_table[hash_number] = s_hash; } struct file_hash *find_directory_hash(dev_t dev, ino_t inode) { struct file_hash *spnt; unsigned int hash_number; hash_number = HASH_FN((unsigned int)dev, (unsigned int)inode); if(dev == (dev_t)UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL; spnt = directory_hash_table[hash_number]; while(spnt) { if(spnt->inode == inode && spnt->dev == dev) return spnt; spnt = spnt->next; } return NULL; } struct name_hash { struct name_hash *next; struct directory_entry *de; }; #define NR_NAME_HASH 128 static struct name_hash *name_hash_table[NR_NAME_HASH] = {NULL, }; static unsigned int name_hash(const char *name) { const char *p; unsigned int hash = 0; p = name; while(*p) hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++; return hash % NR_NAME_HASH; } void add_file_hash(struct directory_entry *de) { struct name_hash *new; int hash; new = (struct name_hash *)e_malloc(sizeof(struct name_hash)); new->de = de; new->next = NULL; hash = name_hash(de->isorec.name); /* Now insert into the hash table */ new->next = name_hash_table[hash]; name_hash_table[hash] = new; } struct directory_entry *find_file_hash(char * name) { struct name_hash *nh; for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next) if(strcmp(nh->de->isorec.name, name) == 0) return nh->de; return NULL; } int delete_file_hash(struct directory_entry * de) { struct name_hash *nh, *prev; int hash; prev = NULL; hash = name_hash(de->isorec.name); for(nh = name_hash_table[hash]; nh; nh = nh->next) { if(nh->de == de) break; prev = nh; } if(!nh) return 1; if(!prev) name_hash_table[hash] = nh->next; else prev->next = nh->next; free(nh); return 0; } void flush_file_hash(void) { struct name_hash *nh, *nh1; int i; for(i = 0; i < NR_NAME_HASH; i++) { nh = name_hash_table[i]; while(nh) { nh1 = nh->next; free(nh); nh = nh1; } name_hash_table[i] = NULL; } } *[MKISOFS.SRC]ISO9660.H;2+,. / 4H -)0123KPWO 56B'C7CC89*̞OGHJ/* * Header file iso9660.h - assorted structure definitions and typecasts. * specific to iso9660 filesystem. Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* 14-May-1997 George Watson (watson_g@eisner.decus.org): added ISO_PATH_TABLE_LEN and ISO_DIRECTORY_RECORD_LEN defines. */ #ifndef _ISOFS_FS_H #define _ISOFS_FS_H #pragma __member_alignment __save #pragma __nomember_alignment /* * The isofs filesystem constants/structures */ /* This part borrowed from the bsd386 isofs */ #define ISODCL(from, to) (to - from + 1) struct iso_volume_descriptor { char type[ISODCL(1,1)]; /* 711 */ char id[ISODCL(2,6)]; char version[ISODCL(7,7)]; char data[ISODCL(8,2048)]; }; /* volume descriptor types */ #define ISO_VD_PRIMARY 1 #define ISO_VD_END 255 #define ISO_STANDARD_ID "CD001" struct iso_primary_descriptor { char type [ISODCL ( 1, 1)]; /* 711 */ char id [ISODCL ( 2, 6)]; char version [ISODCL ( 7, 7)]; /* 711 */ char unused1 [ISODCL ( 8, 8)]; char system_id [ISODCL ( 9, 40)]; /* achars */ char volume_id [ISODCL ( 41, 72)]; /* dchars */ char unused2 [ISODCL ( 73, 80)]; char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ char unused3 [ISODCL ( 89, 120)]; char volume_set_size [ISODCL (121, 124)]; /* 723 */ char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ char logical_block_size [ISODCL (129, 132)]; /* 723 */ char path_table_size [ISODCL (133, 140)]; /* 733 */ char type_l_path_table [ISODCL (141, 144)]; /* 731 */ char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ char type_m_path_table [ISODCL (149, 152)]; /* 732 */ char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ char volume_set_id [ISODCL (191, 318)]; /* dchars */ char publisher_id [ISODCL (319, 446)]; /* achars */ char preparer_id [ISODCL (447, 574)]; /* achars */ char application_id [ISODCL (575, 702)]; /* achars */ char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ char file_structure_version [ISODCL (882, 882)]; /* 711 */ char unused4 [ISODCL (883, 883)]; char application_data [ISODCL (884, 1395)]; char unused5 [ISODCL (1396, 2048)]; }; /* We use this to help us look up the parent inode numbers. */ struct iso_path_table{ unsigned char name_len[1]; /* 711 */ unsigned char XAR_len[1]; /* 711 */ char extent[4]; /* 73x */ char parent[2]; /* 72x */ char name[1]; }; #define ISO_PATH_TABLE_LEN 8 struct iso_directory_record { unsigned char length [ISODCL (1, 1)]; /* 711 */ char ext_attr_length [ISODCL (2, 2)]; /* 711 */ char extent [ISODCL (3, 10)]; /* 733 */ char size [ISODCL (11, 18)]; /* 733 */ char date [ISODCL (19, 25)]; /* 7 by 711 */ char flags [ISODCL (26, 26)]; char file_unit_size [ISODCL (27, 27)]; /* 711 */ char interleave [ISODCL (28, 28)]; /* 711 */ char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ unsigned char name_len [ISODCL (33, 33)]; /* 711 */ char name[34]; /* Not really, but we need something here */ }; #define ISO_DIRECTORY_RECORD_LEN 33 #pragma __member_alignment __restore #endif *[MKISOFS.SRC]MKISOFS.C;2+,H.$/ 4$#-)0123KPWO%56C7GC89*̞OGHJF/* * Program mkisofs.c - generate iso9660 filesystem based upon directory * tree on hard disk. Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ /* 14-May-1997 George Watson (watson_g@eisner.decus.org): changed version to 1.05.vms7, made changes to OpenVMS support. */ #include #include "mkisofs.h" #ifdef linux #include #endif #include "iso9660.h" #include #include #include "vms.h" #include #include #include #include "exclude.h" #ifdef __NetBSD__ #include #include #endif struct directory *root = NULL; static char version_string[] = "mkisofs v1.05.vms7"; FILE *discimage; unsigned int next_extent = 0; unsigned int last_extent = 0; unsigned int path_table_size = 0; unsigned int path_table[4] = {0,}; unsigned int path_blocks = 0; struct iso_directory_record root_record; static int timezone_offset; char *extension_record = NULL; int extension_record_extent = 0; static int extension_record_size = 0; /* These variables are associated with command line options */ int use_RockRidge = 0; int verbose = 0; int all_files = 0; int follow_links = 0; int rationalize = 0; int generate_tables = 0; char *preparer = PREPARER_DEFAULT; char *publisher = PUBLISHER_DEFAULT; char *appid = APPID_DEFAULT; char *copyright = COPYRIGHT_DEFAULT; char *biblio = BIBLIO_DEFAULT; char *abstract = ABSTRACT_DEFAULT; char *volset_id = VOLSET_ID_DEFAULT; char *volume_id = VOLUME_ID_DEFAULT; char *system_id = SYSTEM_ID_DEFAULT; int omit_period = 0; /* Violates iso9660, but these are a pain */ int transparent_compression = 0; /* So far only works with linux */ int omit_version_number = 0; /* May violate iso9660, but noone uses vers*/ int RR_relocation_depth = 6; /* Violates iso9660, but most systems work */ int full_iso9660_filenames = 0; /* Used with Amiga. Disc will not work with DOS */ int allow_leading_dots = 0; /* DOS cannot read names with leading dots */ struct rcopts{ char *tag; char **variable; }; struct rcopts rcopt[] = { {"PREP", &preparer}, {"PUBL", &publisher}, {"APPI", &appid}, {"COPY", ©right}, {"BIBL", &biblio}, {"ABST", &abstract}, {"VOLS", &volset_id}, {"VOLI", &volume_id}, {"SYSI", &system_id}, {NULL, NULL} }; #ifdef ultrix char *strdup(s) char *s;{char *c;if(c=(char *)malloc(strlen(s)+1))strcpy(c,s);return c;} #endif void read_rcfile(char *appname) { FILE *rcfile; struct rcopts *rco; char *pnt, *pnt1; char linebuffer[256]; static char rcfn[] = ".mkisofsrc"; char filename[1000]; int linum; strcpy(filename, rcfn); rcfile = fopen(filename, "r"); if(!rcfile && errno != ENOENT) perror(filename); if (!rcfile) { pnt = getenv("HOME"); if(pnt && strlen(pnt) + strlen(rcfn) + 2 <= sizeof(filename)) { strcpy(filename, pnt); #ifndef __VMS strcat(filename, "/"); #endif strcat(filename, rcfn); rcfile = fopen(filename, "r"); if(!rcfile && errno != ENOENT) perror(filename); } } if(!rcfile && strlen(appname)+sizeof(rcfn)+2 <= sizeof(filename)) { strcpy(filename, appname); pnt = strrchr(filename, PATH_SEPARATOR); if(pnt) { strcpy(pnt + 1, rcfn); rcfile = fopen(filename, "r"); if(!rcfile && errno != ENOENT) perror(filename); } } if(!rcfile) return; fprintf(stderr, "Using \"%s\"\n", filename); /* OK, we got it. Now read in the lines and parse them */ linum = 0; while(fgets(linebuffer, sizeof(linebuffer), rcfile)) { char *name, *name_end; ++linum; /* skip any leading white space */ pnt = linebuffer; while(*pnt == ' ' || *pnt == '\t') ++pnt; /* If we are looking at a # character, this line is a comment. */ if(*pnt == '#') continue; /* The name should begin in the left margin. Make sure it is in upper case. Stop when we see white space or a comment. */ name = pnt; while(*pnt && isalpha(*pnt)) { if(islower(*pnt)) *pnt = toupper(*pnt); pnt++; } if(name == pnt) { fprintf(stderr, "%s:%d: name required\n", filename, linum); continue; } name_end = pnt; /* Skip past white space after the name */ while(*pnt == ' ' || *pnt == '\t') pnt++; /* silently ignore errors in the rc file. */ if(*pnt != '=') { fprintf(stderr, "%s:%d: equals sign required\n", filename, linum); continue; } /* Skip past the = sign, and any white space following it */ pnt++; while(*pnt == ' ' || *pnt == '\t') pnt++; /* now it is safe to NUL terminate the name */ *name_end = 0; /* Now get rid of trailing newline */ pnt1 = pnt; while(*pnt1) { if(*pnt1 == '\n') { *pnt1 = 0; break; } pnt1++; } /* OK, now figure out which option we have */ for(rco = rcopt; rco->tag; rco++) { if(strcmp(rco->tag, name) == 0) { *rco->variable = strdup(pnt); break; } } if(rco->tag == NULL) { fprintf(stderr, "%s:%d: field name \"%s\" unknown\n", filename, linum, name); } } if(ferror(rcfile)) perror(filename); fclose(rcfile); } char *path_table_l = NULL; char *path_table_m = NULL; int goof = 0; void usage(void) { fprintf(stderr,"Usage:\n"); fprintf(stderr, "mkisofs [-o outfile] [-R] [-V volid] [-v] [-a] \ [-T]\n [-l] [-d] [-V] [-D] [-L] [-p preparer] \ [-P publisher] [ -A app_id ] [-z] [-x path -x path ...] path\n"); exit(1); } int get_iso9660_timezone_offset(void) { struct tm gm; struct tm *pt; time_t ctime; int local_min, gmt_min; time(&ctime); pt = gmtime(&ctime); gm = *pt; pt = localtime(&ctime); if(gm.tm_year < pt->tm_year) gm.tm_yday = -1; if(gm.tm_year > pt->tm_year) pt->tm_yday = -1; gmt_min = gm.tm_min + 60*(gm.tm_hour + 24*gm.tm_yday); local_min = pt->tm_min + 60*(pt->tm_hour + 24*pt->tm_yday); return (gmt_min - local_min)/15; } /* Fill in date in the iso9660 format */ int iso9660_date(char *result, time_t ctime) { struct tm *local; local = localtime(&ctime); result[0] = local->tm_year; result[1] = local->tm_mon + 1; result[2] = local->tm_mday; result[3] = local->tm_hour; result[4] = local->tm_min; result[5] = local->tm_sec; result[6] = timezone_offset; return 0; } int iso9660_file_length(const char *name, struct directory_entry *sresult, int dirflag) { int seen_dot = 0; int seen_semic = 0; char *result; int priority = 32767; int tildes = 0; int ignore = 0; int extra = 0; int current_length = 0; int chars_after_dot = 0; int chars_before_dot = 0; const char *pnt; result = sresult->isorec.name; if(strcmp(name,".") == 0) { if(result) *result = 0; return 1; } if(strcmp(name,"..") == 0) { if(result) { *result++ = 1; *result++ = 0; } return 1; } pnt = name; while(*pnt) { #ifdef __VMS if(strcmp(pnt,".DIR;1") == 0) break; #endif if(*pnt == '#') { priority = 1; pnt++; continue; } if(*pnt == '~') { priority = 1; tildes++; pnt++; continue; } if(*pnt == ';') { seen_semic = 1; *result++ = *pnt++; continue; } if(ignore) { pnt++; continue; } if(seen_semic) { if(*pnt >= '0' && *pnt <= '9') *result++ = *pnt; extra++; pnt++; continue; } if(full_iso9660_filenames) { /* Here we allow a more relaxed syntax. */ if(*pnt == '.') { if(seen_dot) { ignore++; continue; } seen_dot++; } if(current_length < 30) *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt); } else { /* Dos style filenames */ if(*pnt == '.') { if(!chars_before_dot && !allow_leading_dots) { /* DOS can't read files with dot first */ chars_before_dot++; if(result) *result++ = '_'; /* Substitute underscore */ } else { if(seen_dot) { ignore++; continue; } if(result) *result++ = '.'; seen_dot++; } } else if(seen_dot) { if(chars_after_dot < 3) { chars_after_dot++; if(result) *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt); } } else { if(chars_before_dot < 8) { chars_before_dot++; if(result) *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt); } } } current_length++; pnt++; } if(tildes == 2) { int prio1 = 0; pnt = name; while(*pnt && *pnt != '~') pnt++; if(*pnt) pnt++; while(*pnt && *pnt != '~') { prio1 = 10*prio1 + *pnt - '0'; pnt++; } priority = prio1; } if(!dirflag) { if(!seen_dot && !omit_period) { if(result) *result++ = '.'; extra++; } if(!omit_version_number && !seen_semic) { if(result) { *result++ = ';'; *result++ = '1'; } extra += 2; } } if(result) *result++ = 0; sresult->priority = priority; return chars_before_dot + chars_after_dot + seen_dot + extra; } #ifdef ADD_FILES 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 = rindex(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); } void add_file_list(int argc, char **argv, int ind) { char *ptr; char *dup_arg; while(ind < argc) { dup_arg = strdup(argv[ind]); ptr = index(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[1024]; FILE *f; char *ptr; char *p2; int count = 0; if(strcmp(filename, "-") == 0) f = stdin; else { f = fopen(filename, "r"); if(f == NULL) { perror("fopen"); exit(1); } } while(fgets(buff, 1024, f)) { count++; ptr = buff; while(isspace(*ptr)) ptr++; if(*ptr==0) continue; if(*ptr=='#') continue; if(ptr[strlen(ptr)-1] == '\n') ptr[strlen(ptr)-1] = 0; p2 = index(ptr, '='); if(p2 == NULL) { fprintf(stderr, "Error in line %d: %s\n", count, buff); exit (1); } *p2 = 0; p2++; add_one_file(ptr, p2); } if(f != stdin) fclose(f); } #endif int main(int argc, char **argv) { char *outfile; struct directory_entry de; unsigned int mem_start; struct stat statbuf; char *scan_tree; int c; #ifdef ADD_FILES char *add_file_file = NULL; #endif if(argc < 2) usage(); /* Get the defaults from the .mkisofsrc file */ read_rcfile(argv[0]); outfile = NULL; while((c = getopt(argc, argv, "i:o:V:RrfvaTp:P:x:dDlLNzA:")) != EOF) switch(c) { case 'p': preparer = optarg; if(strlen(preparer) > 128) { fprintf(stderr,"Preparer string too long\n"); exit(1); } break; case 'P': publisher = optarg; if(strlen(publisher) > 128) { fprintf(stderr,"Publisher string too long\n"); exit(1); } break; case 'A': appid = optarg; if(strlen(appid) > 128) { fprintf(stderr,"Application-id string too long\n"); exit(1); } break; case 'd': omit_period++; break; case 'D': RR_relocation_depth = 32767; break; case 'l': full_iso9660_filenames++; break; case 'L': allow_leading_dots++; break; case 'N': omit_version_number++; break; case 'o': outfile = optarg; break; case 'f': follow_links++; break; case 'R': use_RockRidge++; break; case 'r': rationalize++; use_RockRidge++; break; case 'V': volume_id = optarg; break; case 'v': verbose++; break; case 'a': all_files++; break; case 'T': generate_tables++; break; case 'z': #ifdef __VMS fprintf(stderr,"Transparent compression not supported with VMS\n"); exit(1); #else transparent_compression++; #endif break; case 'x': exclude(optarg); break; case 'i': #ifdef ADD_FILES add_file_file = optarg; break; #endif default: usage(); exit(1); } #ifdef __NetBSD__ { int resource; struct rlimit rlp; if(getrlimit(RLIMIT_DATA,&rlp) == -1) perror("Warning: getrlimit"); else { rlp.rlim_cur = 33554432; if(setrlimit(RLIMIT_DATA,&rlp) == -1) perror("Warning: setrlimit"); } } #endif mem_start = (unsigned int)sbrk(0); if(verbose) fprintf(stderr, "%s\n", version_string); /* Now find the timezone offset */ timezone_offset = get_iso9660_timezone_offset(); /* The first step is to scan the directory tree, and take some notes */ scan_tree = argv[optind]; #ifdef ADD_FILES if(add_file_file) add_file(add_file_file); add_file_list(argc, argv, optind+1); #endif if(!scan_tree) { usage(); exit(1); } #ifndef __VMS if(scan_tree[strlen(scan_tree)-1] != '/') { scan_tree = (char *)e_malloc(strlen(argv[optind])+2); strcpy(scan_tree, argv[optind]); strcat(scan_tree, "/"); } #else scan_tree = VMS_parse(scan_tree); if(!scan_tree) { usage(); exit(1); } #endif if(use_RockRidge) { #if 1 extension_record = generate_rr_extension_record("RRIP_1991A", "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS", "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.", &extension_record_size); #else extension_record = generate_rr_extension_record("IEEE_P1282", "THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS", "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION.", &extension_record_size); #endif } stat_filter(scan_tree, &statbuf); add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); de.filedir = root; /* We need this to bootstrap */ #ifdef __VMS c = strlen(scan_tree); scan_tree[c-1] = '\0'; #endif scan_directory_tree(scan_tree, &de); /* Fix this up so that the path tables get done right */ root->self = root->contents; if(reloc_dir) sort_n_finish(reloc_dir); if(goof) exit(1); if(outfile){ discimage = fopen(outfile, "w" #ifdef __VMS , "ctx=bin", "fop=ctg", "rfm=fix", "mrs=2048" #endif ); if(!discimage) { fprintf(stderr, "Unable to open disc image file\n"); exit(1); } } else discimage = stdout; /* Now assign addresses on the disc for the path table. */ path_blocks = (path_table_size + (SECTOR_SIZE - 1)) >> 11; if(path_blocks & 1) path_blocks++; path_table[0] = 0x12; path_table[1] = 0; path_table[2] = path_table[0] + path_blocks; path_table[3] = 0; last_extent = path_table[2] + path_blocks; /* The next free block */ /* The next step is to go through the directory tree and assign extent numbers for all of the directories */ assign_directory_addresses(root); if(extension_record) { struct directory_entry *s_entry; extension_record_extent = last_extent++; s_entry = root->contents; set_733(s_entry->rr_attributes + s_entry->rr_attr_size - 24, extension_record_extent); set_733(s_entry->rr_attributes + s_entry->rr_attr_size - 8, extension_record_size); } if(use_RockRidge && reloc_dir) finish_cl_pl_entries(); /* Now we generate the path tables that are used by DOS to improve directory access times. */ generate_path_tables(); /* Generate root record for volume descriptor. */ generate_root_record(); if(verbose) dump_tree(root); iso_write(discimage); fprintf(stderr, "Max brk space used %x\n", ((unsigned int)sbrk(0)) - mem_start); fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9); #ifdef __VMS return 1; #else return 0; #endif } void *e_malloc(size_t size) { void* pt; if((pt = malloc(size)) == NULL) { printf("Not enougth memory\n"); exit(1); } return pt; } *[MKISOFS.SRC]MKISOFS.H;2+,5./ 4O P-)0123KPWO56z$7O 89*̞OGHJ/* * Header file mkisofs.h - assorted structure definitions and typecasts. Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ #include /* This symbol is used to indicate that we do not have things like symlinks, dev~ MKISOFS.BCK5)[MKISOFS.SRC]MKISOFS.H;2O ices, and so forth available. Just files and dirs */ #ifdef __VMS #define NON_UNIXFS #endif #ifdef DJGPP #define NON_UNIXFS #endif #include #include #include #include #ifdef linux #include #endif #ifdef ultrix extern char *strdup(); #endif #include #include "iso9660.h" #include "defaults.h" struct directory_entry{ struct directory_entry *next; struct iso_directory_record isorec; unsigned int starting_block; unsigned int size; unsigned int priority; char *name; char *table; char *whole_name; struct directory *filedir; struct directory_entry *parent_rec; unsigned int flags; ino_t inode; /* Used in the hash table */ dev_t dev; /* Used in the hash table */ unsigned char *rr_attributes; unsigned int rr_attr_size; unsigned int total_rr_attr_size; }; struct file_hash{ struct file_hash *next; ino_t inode; /* Used in the hash table */ dev_t dev; /* Used in the hash table */ unsigned int starting_block; unsigned int size; }; struct directory{ struct directory *next; /* Next directory at same level as this one */ struct directory *subdir; /* First subdirectory in this directory */ struct directory *parent; struct directory_entry *contents; struct directory_entry *self; char *whole_name; /* Entire path */ char *de_name; /* Entire path */ unsigned int ce_bytes; /* Number of bytes of CE entries reqd for this dir */ unsigned int depth; unsigned int size; unsigned int extent; unsigned short int path_index; }; struct deferred{ struct deferred *next; unsigned int starting_block; char *name; struct directory *filedir; unsigned int flags; }; #ifdef ADD_FILES struct file_adds { char *name; struct file_adds *child; struct file_adds *next; int add_count; int used; struct dirent de; struct { char *path; char *name; } *adds; }; extern struct file_adds *root_file_adds; #endif void sort_n_finish(struct directory *); extern int goof; extern struct directory *root; extern struct directory *reloc_dir; extern unsigned int next_extent; extern unsigned int last_extent; extern unsigned int path_table_size; extern unsigned int path_table[4]; extern unsigned int path_blocks; extern char *path_table_l; extern char *path_table_m; extern struct iso_directory_record root_record; extern int use_RockRidge; extern int rationalize; extern int follow_links; extern int verbose; extern int all_files; extern int generate_tables; extern int omit_period; extern int omit_version_number; extern int transparent_compression; extern int RR_relocation_depth; extern int full_iso9660_filenames; int scan_directory_tree(char *, struct directory_entry *); void dump_tree(struct directory *); void assign_directory_addresses(struct directory *); int stat_filter(char *, struct stat *); int iso9660_file_length(const char *, struct directory_entry *, int); int iso_write(FILE *); void generate_path_tables(void); void generate_iso9660_directories(struct directory *, FILE *); void generate_one_directory(struct directory *, FILE *); void generate_root_record(void); int iso9660_date(char *, time_t); void add_hash(struct directory_entry *); struct file_hash *find_hash(dev_t, ino_t); void add_directory_hash(dev_t, ino_t); struct file_hash *find_directory_hash(dev_t, ino_t); void flush_file_hash(void); int delete_file_hash(struct directory_entry *); struct directory_entry *find_file_hash(char *); void add_file_hash(struct directory_entry *); void finish_cl_pl_entries(void); int get_733(void *); void set_723(void *, unsigned int); void set_733(void *, unsigned int); void sort_directory(struct directory_entry **); int generate_rock_ridge_attributes(char *, char *, struct directory_entry *, struct stat *, struct stat *, int); char *generate_rr_extension_record(char *, char *, char *, int *); 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; void *e_malloc(size_t); #define SECTOR_SIZE (2048) #define ROUND_UP(X) ((X + (SECTOR_SIZE - 1)) & -SECTOR_SIZE) #define NEED_RE 1 #define NEED_PL 2 #define NEED_CL 4 #define NEED_CE 8 #define NEED_SP 16 #define TABLE_INODE (sizeof(ino_t) >= 4 ? 0x7ffffffe : 0x7ffe) #define UNCACHED_INODE (sizeof(ino_t) >= 4 ? 0x7fffffff : 0x7fff) #define UNCACHED_DEVICE (sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff) #ifdef __VMS #define STAT_INODE(X) (X.st_ino[0]) #define PATH_SEPARATOR ']' /* '[' ? */ #define SPATH_SEPARATOR "" /* ".]" ? */ #else #define STAT_INODE(X) (X.st_ino) #define PATH_SEPARATOR '/' #define SPATH_SEPARATOR "/" #endif *[MKISOFS.SRC]ROCK.C;2+,7./ 4P-)0123KPWO56I$7O_ 89*̞OGHJ4/* * File rock.c - generate RRIP records for iso9660 filesystems. Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #if defined(HASSYSMACROS) && !defined(HASMKDEV) #include #endif #include #ifdef HASMKDEV #include #include #endif #include "mkisofs.h" #include "iso9660.h" #include #include "vms.h" #ifndef S_ISLNK #ifdef NON_UNIXFS #define S_ISLNK(m) (0) #else #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #endif #endif #define SU_VERSION 1 #define SL_ROOT 8 #define SL_PARENT 4 #define SL_CURRENT 2 #define SL_CONTINUE 1 #define CE_SIZE 28 #define CL_SIZE 12 #define ER_SIZE 8 #define NM_SIZE 5 #define PL_SIZE 12 #define PN_SIZE 20 #define PX_SIZE 36 #define RE_SIZE 4 #define SL_SIZE 20 #define ZZ_SIZE 15 #ifdef __QNX__ #define TF_SIZE (5 + 4 * 7) #else #define TF_SIZE (5 + 3 * 7) #endif /* If we need to store this number of bytes, make sure we do not box ourselves in so that we do not have room for a CE entry for the continuation record */ #define MAYBE_ADD_CE_ENTRY(BYTES) \ (BYTES + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0) /* * Buffer to build RR attributes */ static unsigned char Rock[16384]; static unsigned char symlink_buff[256]; static int ipnt = 0; static int recstart = 0; static int currlen = 0; static int mainrec = 0; static int reclimit; static void add_CE_entry(void) { if(recstart) set_733(Rock + recstart - 8, ipnt + 28 - recstart); Rock[ipnt++] ='C'; Rock[ipnt++] ='E'; Rock[ipnt++] = CE_SIZE; Rock[ipnt++] = SU_VERSION; set_733(Rock + ipnt, 0); ipnt += 8; set_733(Rock + ipnt, 0); ipnt += 8; set_733(Rock + ipnt, 0); ipnt += 8; recstart = ipnt; currlen = 0; if(!mainrec) mainrec = ipnt; reclimit = SECTOR_SIZE - 8; /* Limit to one sector */ } int generate_rock_ridge_attributes(char *whole_name, char *name, struct directory_entry *s_entry, struct stat *statbuf, struct stat *lstatbuf, int deep_opt) { int flagpos, flagval; int need_ce; statbuf = statbuf; /* this shuts up unreferenced compiler warnings */ mainrec = recstart = ipnt = 0; reclimit = 0xf8; /* Obtain the amount of space that is currently used for the directory record. Assume max for name, since name conflicts may cause us to rename the file later on */ currlen = sizeof(s_entry->isorec); /* Identify that we are using the SUSP protocol */ if(deep_opt & NEED_SP) { Rock[ipnt++] ='S'; Rock[ipnt++] ='P'; Rock[ipnt++] = 7; Rock[ipnt++] = SU_VERSION; Rock[ipnt++] = 0xbe; Rock[ipnt++] = 0xef; Rock[ipnt++] = 0; } /* First build the posix name field */ Rock[ipnt++] ='R'; Rock[ipnt++] ='R'; Rock[ipnt++] = 5; Rock[ipnt++] = SU_VERSION; flagpos = ipnt; flagval = 0; Rock[ipnt++] = 0; /* We go back and fix this later */ if(strcmp(name,".") && strcmp(name,"..")) { char * npnt; int remain, use; remain = strlen(name); npnt = name; while(remain) { use = remain; need_ce = 0; /* Can we fit this SUSP and a CE entry? */ if(use + currlen + CE_SIZE + (ipnt - recstart) > reclimit) { use = reclimit - currlen - CE_SIZE - (ipnt - recstart); need_ce++; } /* Only room for 256 per SUSP field */ if(use > 0xf8) use = 0xf8; /* First build the posix name field */ Rock[ipnt++] ='N'; Rock[ipnt++] ='M'; Rock[ipnt++] = NM_SIZE + use; Rock[ipnt++] = SU_VERSION; Rock[ipnt++] = (remain != use ? 1 : 0); flagval |= (1<<3); strncpy((char *)&Rock[ipnt], npnt, use); npnt += use; ipnt += use; remain -= use; if(remain && need_ce) add_CE_entry(); } } /* * Add the posix modes */ if(MAYBE_ADD_CE_ENTRY(PX_SIZE)) add_CE_entry(); Rock[ipnt++] ='P'; Rock[ipnt++] ='X'; Rock[ipnt++] = PX_SIZE; Rock[ipnt++] = SU_VERSION; flagval |= (1<<0); set_733(Rock + ipnt, lstatbuf->st_mode); ipnt += 8; set_733(Rock + ipnt, lstatbuf->st_nlink); ipnt += 8; set_733(Rock + ipnt, lstatbuf->st_uid); ipnt += 8; set_733(Rock + ipnt, lstatbuf->st_gid); ipnt += 8; /* * Check for special devices */ #ifndef NON_UNIXFS if(S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) { if(MAYBE_ADD_CE_ENTRY(PN_SIZE)) add_CE_entry(); Rock[ipnt++] ='P'; Rock[ipnt++] ='N'; Rock[ipnt++] = PN_SIZE; Rock[ipnt++] = SU_VERSION; flagval |= (1<<1); if(sizeof(dev_t) <= 4) { set_733(Rock + ipnt, 0); ipnt += 8; set_733(Rock + ipnt, lstatbuf->st_rdev); ipnt += 8; } else { set_733(Rock + ipnt, (lstatbuf->st_rdev >> 16) >> 16); ipnt += 8; set_733(Rock + ipnt, lstatbuf->st_rdev); ipnt += 8; } } #endif /* * Check for and symbolic links. VMS does not have these. */ if(S_ISLNK(lstatbuf->st_mode)) { int lenpos, lenval, j0, j1; int cflag, nchar; unsigned char *cpnt, *cpnt1; nchar = readlink(whole_name, (char *)symlink_buff, sizeof(symlink_buff)); symlink_buff[nchar] = 0; set_733(s_entry->isorec.size, 0); cpnt = &symlink_buff[0]; flagval |= (1<<2); while(nchar) { if(MAYBE_ADD_CE_ENTRY(SL_SIZE)) add_CE_entry(); Rock[ipnt++] ='S'; Rock[ipnt++] ='L'; lenpos = ipnt; Rock[ipnt++] = SL_SIZE; Rock[ipnt++] = SU_VERSION; Rock[ipnt++] = 0; /* Flags */ lenval = 5; while(*cpnt) { cpnt1 = (unsigned char *)strchr((char *)cpnt, '/'); if(cpnt1) { nchar--; *cpnt1 = 0; } /* We treat certain components in a special way. */ if(cpnt[0] == '.' && cpnt[1] == '.' && cpnt[2] == 0) { if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry(); Rock[ipnt++] = SL_PARENT; Rock[ipnt++] = 0; /* length is zero */ lenval += 2; nchar -= 2; } else if(cpnt[0] == '.' && cpnt[1] == 0) { if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry(); Rock[ipnt++] = SL_CURRENT; Rock[ipnt++] = 0; /* length is zero */ lenval += 2; nchar -= 1; } else if(cpnt[0] == 0) { if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry(); Rock[ipnt++] = SL_ROOT; Rock[ipnt++] = 0; /* length is zero */ lenval += 2; } else { /* If we do not have enough room for a component, start a new continuations segment now */ if(MAYBE_ADD_CE_ENTRY(6)) { add_CE_entry(); if(cpnt1) { *cpnt1 = '/'; nchar++; cpnt1 = NULL; /* A kluge so that we can restart properly */ } break; } j0 = strlen((char *)cpnt); while(j0) { j1 = j0; if(j1 > 0xf8) j1 = 0xf8; need_ce = 0; if(j1 + currlen + CE_SIZE + (ipnt - recstart) > reclimit) { j1 = reclimit - currlen - CE_SIZE - (ipnt - recstart); need_ce++; } Rock[ipnt++] = (j1 != j0 ? SL_CONTINUE : 0); Rock[ipnt++] = j1; strncpy((char *)Rock + ipnt, (char *)cpnt, j1); ipnt += j1; lenval += j1 + 2; cpnt += j1; nchar -= j1; /* Number we processed this time */ j0 -= j1; if(need_ce) { add_CE_entry(); if(cpnt1) { *cpnt1 = '/'; nchar++; cpnt1 = NULL; /* A kluge so that we can restart properly */ } break; } } } if(cpnt1) cpnt = cpnt1 + 1; else break; } Rock[lenpos] = lenval; if(nchar) Rock[lenpos + 2] = SL_CONTINUE; /* We need another SL entry */ } /* while nchar */ } /* Is a symbolic link */ /* * Add in the Rock Ridge TF time field */ if(MAYBE_ADD_CE_ENTRY(TF_SIZE)) add_CE_entry(); Rock[ipnt++] ='T'; Rock[ipnt++] ='F'; Rock[ipnt++] = TF_SIZE; Rock[ipnt++] = SU_VERSION; #ifdef __QNX__ Rock[ipnt++] = 0x0f; #else Rock[ipnt++] = 0x0e; #endif flagval |= (1<<7); #ifdef __QNX__ iso9660_date((char *)&Rock[ipnt], lstatbuf->st_ftime); ipnt += 7; #endif iso9660_date((char *)&Rock[ipnt], lstatbuf->st_mtime); ipnt += 7; iso9660_date((char *)&Rock[ipnt], lstatbuf->st_atime); ipnt += 7; iso9660_date((char *)&Rock[ipnt], lstatbuf->st_ctime); ipnt += 7; /* * Add in the Rock Ridge RE time field */ if(deep_opt & NEED_RE) { if(MAYBE_ADD_CE_ENTRY(RE_SIZE)) add_CE_entry(); Rock[ipnt++] ='R'; Rock[ipnt++] ='E'; Rock[ipnt++] = RE_SIZE; Rock[ipnt++] = SU_VERSION; flagval |= (1<<6); } /* * Add in the Rock Ridge PL record, if required. */ if(deep_opt & NEED_PL) { if(MAYBE_ADD_CE_ENTRY(PL_SIZE)) add_CE_entry(); Rock[ipnt++] ='P'; Rock[ipnt++] ='L'; Rock[ipnt++] = PL_SIZE; Rock[ipnt++] = SU_VERSION; set_733(Rock + ipnt, 0); ipnt += 8; flagval |= (1<<5); } /* * Add in the Rock Ridge CL field, if required. */ if(deep_opt & NEED_CL) { if(MAYBE_ADD_CE_ENTRY(CL_SIZE)) add_CE_entry(); Rock[ipnt++] ='C'; Rock[ipnt++] ='L'; Rock[ipnt++] = CL_SIZE; Rock[ipnt++] = SU_VERSION; set_733(Rock + ipnt, 0); ipnt += 8; flagval |= (1<<4); } #ifndef __VMS /* If transparent compression was requested, fill in the correct field for this file */ if(transparent_compression && S_ISREG(lstatbuf->st_mode) && strlen(name) > 3 && strcmp(name + strlen(name) - 3,".gZ") == 0) { FILE *zipfile; char *checkname; unsigned int file_size; unsigned char header[8]; int OK_flag; /* First open file and verify that the correct algorithm was used */ file_size = 0; OK_flag = 1; zipfile = fopen(whole_name, "r"); fread(header, 1, sizeof(header), zipfile); /* Check some magic numbers from gzip. */ if(header[0] != 0x1f || header[1] != 0x8b || header[2] != 8) OK_flag = 0; /* Make sure file was blocksized. */ if((header[3] & 0x40 == 0)) OK_flag = 0; /* OK, now go to the end of the file and get some more info */ if(OK_flag){ int status; status = (long)lseek(fileno(zipfile), (off_t)(-8), SEEK_END); if(status == -1) OK_flag = 0; } if(OK_flag){ if(read(fileno(zipfile), (char*)header, sizeof(header)) != sizeof(header)) OK_flag = 0; else { int blocksize; blocksize = (header[3] << 8) | header[2]; file_size = ((unsigned int)header[7] << 24) | ((unsigned int)header[6] << 16) | ((unsigned int)header[5] << 8) | header[4]; #if 0 fprintf(stderr, "Blocksize = %d %d\n", blocksize, file_size); #endif if(blocksize != SECTOR_SIZE) OK_flag = 0; } } fclose(zipfile); checkname = strdup(whole_name); checkname[strlen(whole_name)-3] = 0; zipfile = fopen(checkname, "r"); if(zipfile) { OK_flag = 0; fprintf(stderr, "Unable to insert transparent compressed file - name conflict\n"); fclose(zipfile); } free(checkname); if(OK_flag){ if(MAYBE_ADD_CE_ENTRY(ZZ_SIZE)) add_CE_entry(); Rock[ipnt++] ='Z'; Rock[ipnt++] ='Z'; Rock[ipnt++] = ZZ_SIZE; Rock[ipnt++] = SU_VERSION; Rock[ipnt++] = 'g'; Rock[ipnt++] = 'z'; /* Identify compression used */ Rock[ipnt++] = 3; set_733(Rock + ipnt, file_size); /* Real file size */ ipnt += 8; } } #endif /* * Add in the Rock Ridge CE field, if required. We use this for the * extension record that is stored in the root directory. */ if(deep_opt & NEED_CE) add_CE_entry(); /* * Done filling in all of the fields. Now copy it back to a buffer for the * file in question. */ Rock[flagpos] = flagval; /* If there was a CE, fill in the size field */ if(recstart) set_733(Rock + recstart - 8, ipnt - recstart); s_entry->rr_attributes = (unsigned char *)e_malloc(ipnt); s_entry->total_rr_attr_size = ipnt; s_entry->rr_attr_size = (mainrec ? mainrec : ipnt); memcpy(s_entry->rr_attributes, Rock, ipnt); return ipnt; } /* Guaranteed to return a single sector with the relevant info */ char *generate_rr_extension_record(char *id, char *descriptor, char *source, int *size) { int ipnt = 0; char *pnt; int len_id, len_des, len_src; len_id = strlen(id); len_des = strlen(descriptor); len_src = strlen(source); Rock[ipnt++] ='E'; Rock[ipnt++] ='R'; Rock[ipnt++] = ER_SIZE + len_id + len_des + len_src; Rock[ipnt++] = 1; Rock[ipnt++] = len_id; Rock[ipnt++] = len_des; Rock[ipnt++] = len_src; Rock[ipnt++] = 1; memcpy(Rock + ipnt, id, len_id); ipnt += len_id; memcpy(Rock + ipnt, descriptor, len_des); ipnt += len_des; memcpy(Rock + ipnt, source, len_src); ipnt += len_src; if(ipnt > SECTOR_SIZE) { fprintf(stderr,"Extension record too long\n"); exit(1); } pnt = (char *)e_malloc(SECTOR_SIZE); memset(pnt, 0, SECTOR_SIZE); memcpy(pnt, Rock, ipnt); *size = ipnt; return pnt; } *[MKISOFS.SRC]TREE.C;2+,< .?/ 4P?;4-)0123KPWO@562D7DD89*̞OGHJ2/* * File tree.c - scan directory tree and build memory structures for iso9660 * filesystem Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ /* 14-May-1997 George Watson (watson_g@eisner.decus.org): modified OpenVMS support. Parsing of VMS directory path format, plus the pseudo- directories "." and "..", is fully supported. */ #include #include #include #include #include #include "mkisofs.h" #include "iso9660.h" #include #include "exclude.h" #ifndef __VMS #if defined(HASSYSMACROS) && !defined(HASMKDEV) #include #endif #ifdef HASMKDEV #include #include #endif #else #include #include #include "vms.h" #endif #ifndef S_ISLNK #ifdef NON_UNIXFS #define S_ISLNK(m) (0) #else #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #endif #endif #ifndef S_ISSOCK #ifdef NON_UNIXFS #define S_ISSOCK(m) (0) #else #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) #endif #endif #ifndef S_ISFIFO #ifdef NON_UNIXFS #define S_ISFIFO(m) (0) #else #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) #endif #endif #ifdef __svr4__ extern char *strdup(const char *); #endif static unsigned char symlink_buff[256]; extern int verbose; /* We use this for the artificial entries we create */ struct stat fstatbuf = {0,}; struct stat root_statbuf = {0, }; /* Stat buffer for root directory */ struct directory *reloc_dir = NULL; void stat_fix(struct stat *st) { /* Remove the uid and gid, they will only be useful on the author's system. */ st->st_uid = st->st_gid = 0; /* Make sure the file modes make sense. Turn on all read bits. Turn on all exec/search bits if any exec/search bit is set. Turn off all write bits, and all special mode bits (on a r/o fs lock bits are useless, and with uid+gid 0 don't want set-id bits, either). */ st->st_mode |= 0444; if (st->st_mode & 0111) st->st_mode |= 0111; st->st_mode &= ~07222; } int stat_filter(char *path, struct stat *st) { #ifdef __VMS int result = VMS_stat(path, st); #else int result = stat(path, st); #endif if(result >= 0 && rationalize) stat_fix(st); return result; } int lstat_filter(char *path, struct stat *st) { #ifdef __VMS int result = VMS_stat(path, st); #else int result = lstat(path, st); #endif if(result >= 0 && rationalize) stat_fix(st); return result; } void sort_n_finish(struct directory *this_dir) { struct directory_entry *s_entry, *s_entry1; time_t current_time; struct directory_entry *table; int count; int new_reclen; char *c; int tablesize = 0; char newname[34], rootname[34]; /* Here we can take the opportunity to toss duplicate entries from the directory. */ table = NULL; if(fstatbuf.st_ctime == 0) { time(¤t_time); fstatbuf.st_uid = 0; fstatbuf.st_gid = 0; fstatbuf.st_ctime = current_time; fstatbuf.st_mtime = current_time; fstatbuf.st_atime = current_time; } flush_file_hash(); s_entry = this_dir->contents; while(s_entry) { /* First assume no conflict, and handle this case */ if(!(s_entry1 = find_file_hash(s_entry->isorec.name))) { add_file_hash(s_entry); s_entry = s_entry->next; continue; } if(s_entry1 == s_entry) { fprintf(stderr, "Fatal goof\n"); exit(1); } /* OK, handle the conflicts. Try substitute names until we come up with a winner */ strcpy(rootname, s_entry->isorec.name); if(full_iso9660_filenames) { if(strlen(rootname) > 27) rootname[27] = 0; } c = strchr(rootname, '.'); if(c) *c = 0; count = 0; while(count < 1000) { sprintf(newname, "%s.%3.3d%s", rootname, count, (s_entry->isorec.flags[0] == 2 || omit_version_number ? "" : ";1")); #ifdef __VAXC /* Sigh. VAXCRTL seems to be broken here */ { int ijk = 0; while(newname[ijk]) { if(newname[ijk] == ' ') newname[ijk] = '0'; ijk++; } } #endif if(!find_file_hash(newname)) break; count++; } if(count >= 1000) { fprintf(stderr,"Unable to generate unique name for file %s\n", s_entry->name); exit(1); } /* OK, now we have a good replacement name. Now decide which one of these two beasts should get the name changed */ if(s_entry->priority < s_entry1->priority) { fprintf(stderr, "Using %s for %s%s%s (%s)\n", newname, this_dir->whole_name, SPATH_SEPARATOR, s_entry->name, s_entry1->name); s_entry->isorec.name_len[0] = strlen(newname); new_reclen = ISO_DIRECTORY_RECORD_LEN + strlen(newname); if(use_RockRidge) { if(new_reclen & 1) new_reclen++; /* Pad to an even byte */ new_reclen += s_entry->rr_attr_size; } if(new_reclen & 1) new_reclen++; /* Pad to an even byte */ s_entry->isorec.length[0] = new_reclen; strcpy(s_entry->isorec.name, newname); } else { delete_file_hash(s_entry1); fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, this_dir->whole_name, SPATH_SEPARATOR, s_entry1->name, s_entry->name); s_entry1->isorec.name_len[0] = strlen(newname); new_reclen = ISO_DIRECTORY_RECORD_LEN + strlen(newname); if(use_RockRidge) { if(new_reclen & 1) new_reclen++; /* Pad to an even byte */ new_reclen += s_entry1->rr_attr_size; } if(new_reclen & 1) new_reclen++; /* Pad to an even byte */ s_entry1->isorec.length[0] = new_reclen; strcpy(s_entry1->isorec.name, newname); add_file_hash(s_entry1); } add_file_hash(s_entry); s_entry = s_entry->next; } if(generate_tables && !find_file_hash("TRANS.TBL") && (reloc_dir != this_dir)) { /* First we need to figure out how big this table is */ for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { if(strcmp(s_entry->name, ".") == 0 || strcmp(s_entry->name, "..") == 0) continue; if(s_entry->table) tablesize += 35 + strlen(s_entry->table); } table = (struct directory_entry *)e_malloc(sizeof(struct directory_entry)); memset(table, 0, sizeof(struct directory_entry)); table->table = NULL; table->next = this_dir->contents; this_dir->contents = table; table->filedir = root; table->isorec.flags[0] = 0; table->priority = 32768; iso9660_date(table->isorec.date, fstatbuf.st_ctime); table->inode = TABLE_INODE; table->dev = (dev_t)UNCACHED_DEVICE; set_723(table->isorec.volume_sequence_number, 1); set_733(table->isorec.size, tablesize); table->size = tablesize; table->filedir = this_dir; table->name = strdup(""); table->table = (char *)e_malloc(ROUND_UP(tablesize)); memset(table->table, 0, ROUND_UP(tablesize)); iso9660_file_length ("TRANS.TBL", table, 1); if(use_RockRidge) { fstatbuf.st_mode = 0444 | S_IFREG; fstatbuf.st_nlink = 1; generate_rock_ridge_attributes("", "TRANS.TBL", table, &fstatbuf, &fstatbuf, 0); } } for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { new_reclen = strlen(s_entry->isorec.name); if(s_entry->isorec.flags[0] == 2) { if(strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) { path_table_size += ISO_PATH_TABLE_LEN + new_reclen; if(new_reclen & 1) path_table_size++; } else { new_reclen = 1; if(this_dir == root && strlen(s_entry->name) == 1) path_table_size += ISO_PATH_TABLE_LEN + 1; } } if(path_table_size & 1) path_table_size++; /* For odd lengths we pad */ s_entry->isorec.name_len[0] = new_reclen; new_reclen += ISO_DIRECTORY_RECORD_LEN; if(new_reclen & 1) new_reclen++; if(use_RockRidge) { new_reclen += s_entry->rr_attr_size; if(new_reclen & 1) new_reclen++; } if(new_reclen > 0xff) { fprintf(stderr,"Fatal error - RR overflow for file %s\n", s_entry->name); exit(1); } s_entry->isorec.length[0] = new_reclen; } sort_directory(&this_dir->contents); if(table) { char buffer[1024]; count = 0; for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { if(s_entry == table) continue; if(!s_entry->table) continue; if(strcmp(s_entry->name, ".") == 0 || strcmp(s_entry->name, "..") == 0) continue; sprintf(buffer, "%c %-34s%s", s_entry->table[0], s_entry->isorec.name, s_entry->table+1); memcpy(table->table + count, buffer, strlen(buffer)); count += strlen(buffer); free(s_entry->table); s_entry->table = NULL; } if(count != tablesize) { fprintf(stderr, "Translation table size mismatch %d %d\n", count, tablesize); exit(1); } } /* Now go through the directory and figure out how large this one will be. Do not split a directory entry across a sector boundary */ s_entry = this_dir->contents; this_dir->ce_bytes = 0; while(s_entry) { new_reclen = s_entry->isorec.length[0]; if((this_dir->size & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE) this_dir->size = (this_dir->size + (SECTOR_SIZE - 1)) & -SECTOR_SIZE; this_dir->size += new_reclen; /* See if continuation entries were used on disc */ if(use_RockRidge && s_entry->rr_attr_size != s_entry->total_rr_attr_size) { unsigned char *pnt; int len; int nbytes; pnt = s_entry->rr_attributes; len = s_entry->total_rr_attr_size; /* We make sure that each continuation entry record is not split across sectors, but each file could in theory have more than one CE, so we scan through and figure out what we need. */ while(len > 3) { if(pnt[0] == 'C' && pnt[1] == 'E') { nbytes = get_733(pnt+20); if((this_dir->ce_bytes & (SECTOR_SIZE - 1)) + nbytes >= SECTOR_SIZE) this_dir->ce_bytes = ROUND_UP(this_dir->ce_bytes); /* Now store the block in the ce buffer */ this_dir->ce_bytes += nbytes; if(this_dir->ce_bytes & 1) this_dir->ce_bytes++; } len -= pnt[2]; pnt += pnt[2]; } } s_entry = s_entry->next; } } static void generate_reloc_directory(void) { int new_reclen; time_t current_time; struct directory_entry *s_entry; /* Create an entry for our internal tree */ time(¤t_time); reloc_dir = (struct directory *)e_malloc(sizeof(struct directory)); memset(reloc_dir, 0, sizeof(struct directory)); reloc_dir->parent = root; reloc_dir->next = root->subdir; root->subdir = reloc_dir; reloc_dir->depth = 1; reloc_dir->whole_name = strdup("./rr_moved"); reloc_dir->de_name = strdup("rr_moved"); reloc_dir->extent = 0; new_reclen = strlen(reloc_dir->de_name); /* Now create an actual directory entry */ s_entry = (struct directory_entry *)e_malloc(sizeof(struct directory_entry)); memset(s_entry, 0, sizeof(struct directory_entry)); s_entry->next = root->contents; reloc_dir->self = s_entry; root->contents = s_entry; root->contents->name = strdup(reloc_dir->de_name); root->contents->filedir = root; root->contents->isorec.flags[0] = 2; root->contents->priority = 32768; iso9660_date(root->contents->isorec.date, current_time); root->contents->inode = UNCACHED_INODE; root->contents->dev = (dev_t)UNCACHED_DEVICE; set_723(root->contents->isorec.volume_sequence_number, 1); iso9660_file_length(reloc_dir->de_name, root->contents, 1); if(use_RockRidge) { fstatbuf.st_mode = 0555 | S_IFDIR; fstatbuf.st_nlink = 2; generate_rock_ridge_attributes("", "rr_moved", s_entry, &fstatbuf, &fstatbuf, 0); } /* Now create the . and .. entries in rr_moved */ s_entry = (struct directory_entry *)e_malloc(sizeof(struct directory_entry)); memcpy(s_entry, root->contents, sizeof(struct directory_entry)); s_entry->name = strdup("."); iso9660_file_length (".", s_entry, 1); s_entry->filedir = reloc_dir; reloc_dir->contents = s_entry; if(use_RockRidge) { fstatbuf.st_mode = 0555 | S_IFDIR; fstatbuf.st_nlink = 2; generate_rock_ridge_attributes("", ".", s_entry, &fstatbuf, &fstatbuf, 0); } s_entry = (struct directory_entry *)e~ MKISOFS.BCK< )[MKISOFS.SRC]TREE.C;2P?,:_malloc(sizeof(struct directory_entry)); memcpy(s_entry, root->contents, sizeof(struct directory_entry)); s_entry->name = strdup(".."); iso9660_file_length ("..", s_entry, 1); s_entry->filedir = root; reloc_dir->contents->next = s_entry; reloc_dir->contents->next->next = NULL; if(use_RockRidge) { fstatbuf.st_mode = 0555 | S_IFDIR; fstatbuf.st_nlink = 2; generate_rock_ridge_attributes("", "..", s_entry, &root_statbuf, &root_statbuf, 0); } } static void increment_nlink(struct directory_entry *s_entry) { unsigned char *pnt; int len, nlink; pnt = s_entry->rr_attributes; len = s_entry->total_rr_attr_size; while(len) { if(pnt[0] == 'P' && pnt[1] == 'X') { nlink = get_733(pnt+12); set_733(pnt+12, nlink+1); break; } len -= pnt[2]; pnt += pnt[2]; } } void finish_cl_pl_entries(void) { struct directory_entry *s_entry, *s_entry1; struct directory *d_entry; s_entry = reloc_dir->contents; s_entry = s_entry->next->next; /* Skip past . and .. */ for( ; s_entry; s_entry = s_entry->next) { d_entry = reloc_dir->subdir; while(d_entry) { if(d_entry->self == s_entry) break; d_entry = d_entry->next; } if(!d_entry) { fprintf(stderr, "Unable to locate directory parent\n"); exit(1); } /* First fix the PL pointer in the directory in the rr_reloc dir */ s_entry1 = d_entry->contents->next; set_733(s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8, s_entry->filedir->extent); /* Now fix the CL pointer */ s_entry1 = s_entry->parent_rec; set_733(s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8, d_entry->extent); s_entry->filedir = reloc_dir; /* Now we can fix this */ } /* Next we need to modify the NLINK terms in the assorted root directory records to account for the presence of the RR_MOVED directory */ increment_nlink(root->self); increment_nlink(root->self->next); d_entry = root->subdir; while(d_entry) { increment_nlink(d_entry->contents->next); d_entry = d_entry->next; } } #ifdef ADD_FILES /* 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; f=root_file_adds; if(!f) return NULL; dup_path = strdup(path); /* I don't trust strtok */ 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); /* looks like we found something. */ if(tmp->used >= tmp->add_count) return(NULL); *newpath = tmp->adds[tmp->used].path; tmp->used++; *de = &(tmp->de); return (tmp->adds[tmp->used-1].name); } /* 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; #ifdef __VMS de = VMS_readdir(dir); #else de = readdir(dir); #endif if(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; return(de); } #else struct dirent *readdir_add_files(char **pathp, char *path, DIR *dir) { #ifdef __VMS return(VMS_readdir(dir)); #else return(readdir(dir)); #endif } #endif /* * 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 scan_directory_tree(char *path, struct directory_entry *de) { DIR *current_dir; char whole_path[1024]; struct dirent *d_entry; struct directory_entry *s_entry, *s_entry1; struct directory *this_dir, *next_brother, *parent; struct stat statbuf, lstatbuf; int status, dflag; char *cpnt; int new_reclen; int deep_flag; char *old_path; #ifdef __VMS cpnt = vms_path_fixup(path); #endif current_dir = opendir(path); d_entry = NULL; /* Apparently NFS sometimes allows you to open the directory, but then refuses to allow you to read the contents. Allow for this */ old_path = path; if(current_dir) d_entry = readdir_add_files(&path, old_path, current_dir); if(!current_dir || !d_entry) { fprintf(stderr, "Unable to open directory %s\n", path); de->isorec.flags[0] &= ~2; /* Mark as not a directory */ #ifdef __VMS if(current_dir) VMS_closedir(current_dir); #else if(current_dir) closedir(current_dir); #endif return 0; } parent = de->filedir; /* Set up the struct for the current directory, and insert it into the tree */ this_dir = (struct directory *) e_malloc(sizeof(struct directory)); this_dir->next = NULL; new_reclen = 0; this_dir->subdir = NULL; this_dir->self = de; this_dir->contents = NULL; this_dir->whole_name = strdup(path); #ifdef __VMS this_dir->de_name = cpnt; #else cpnt = strrchr(path, PATH_SEPARATOR); if(cpnt) cpnt++; else cpnt = path; this_dir->de_name = strdup(cpnt); #endif this_dir->size = 0; this_dir->extent = 0; if(!parent || parent == root) { if (!root) { root = this_dir; /* First time through for root directory only */ root->depth = 0; root->parent = root; } else { this_dir->depth = 1; if(!root->subdir) root->subdir = this_dir; else { next_brother = root->subdir; while(next_brother->next) next_brother = next_brother->next; next_brother->next = this_dir; } this_dir->parent = parent; } } else { /* Come through here for normal traversal of tree */ #ifdef DEBUG fprintf(stderr, "%s(%d) ", path, this_dir->depth); #endif if(parent->depth > RR_relocation_depth) { fprintf(stderr, "Directories too deep %s\n", path); exit(1); } this_dir->parent = parent; this_dir->depth = parent->depth + 1; if(!parent->subdir) parent->subdir = this_dir; else { next_brother = parent->subdir; while(next_brother->next) next_brother = next_brother->next; next_brother->next = this_dir; } } /* Now we scan the directory itself, and look at what is inside of it. */ dflag = 0; while(1) { /* The first time through, skip this, since we already asked for the first entry when we opened the directory. */ if(dflag) d_entry = readdir_add_files(&path, old_path, current_dir); dflag++; if(!d_entry) break; /* OK, got a valid entry */ /* If we do not want all files, then pitch the backups. */ if(!all_files) { if(strchr(d_entry->d_name,'~')) continue; if(strchr(d_entry->d_name,'#')) continue; } if(strlen(path) + strlen(d_entry->d_name) + 2 > sizeof(whole_path)) { fprintf(stderr, "Overflow of stat buffer\n"); exit(1); } /* Generate the complete ASCII path for this file */ strcpy(whole_path, path); #ifndef __VMS if(whole_path[strlen(whole_path)-1] != '/') strcat(whole_path, "/"); #endif strcat(whole_path, d_entry->d_name); /* Should we exclude this file? */ if(is_excluded(whole_path)) { if(verbose) fprintf(stderr, "Excluded: %s\n", whole_path); continue; } #if 0 if(verbose) fprintf(stderr, "%s\n", whole_path); #endif status = stat_filter(whole_path, &statbuf); lstat_filter(whole_path, &lstatbuf); if(this_dir == root && strcmp(d_entry->d_name, ".") == 0) root_statbuf = statbuf; /* Save this for later on */ /* We do this to make sure that the root entries are consistent */ if(this_dir == root && strcmp(d_entry->d_name, "..") == 0) { statbuf = root_statbuf; lstatbuf = root_statbuf; } if(S_ISLNK(lstatbuf.st_mode)) { /* Here we decide how to handle the symbolic links. Here we handle the general case - if we are not following links or there is an error, then we must change something. If RR is in use, it is easy, we let RR describe the file. If not, then we punt the file. */ if((status || !follow_links)) { if(use_RockRidge) { status = 0; statbuf.st_size = 0; STAT_INODE(statbuf) = UNCACHED_INODE; statbuf.st_dev = (dev_t)UNCACHED_DEVICE; statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG; } else { if(follow_links) fprintf(stderr, "Unable to stat file %s - ignoring and continuing.\n", whole_path); else fprintf(stderr, "Symlink %s ignored - continuing.\n", whole_path); continue; /* Non Rock Ridge discs - ignore all symlinks */ } } /* Here we handle a different kind of case. Here we have a symlink, but we want to follow symlinks. If we run across a directory loop, then we need to pretend that we are not following symlinks for this file. If this is the first time we have seen this, then make this seem as if there was no symlink there in the first place. */ if(follow_links && S_ISDIR(statbuf.st_mode)) { if(strcmp(d_entry->d_name, ".") && strcmp(d_entry->d_name, "..")) { if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) { if(!use_RockRidge) { fprintf(stderr, "Already cached directory seen (%s)\n", whole_path); continue; } statbuf.st_size = 0; STAT_INODE(statbuf) = UNCACHED_INODE; statbuf.st_dev = (dev_t)UNCACHED_DEVICE; statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG; } else { lstatbuf = statbuf; add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); } } } } /* * Add directories to the cache so that we don't waste space even * if we are supposed to be following symlinks. */ if(follow_links && strcmp(d_entry->d_name, ".") && strcmp(d_entry->d_name, "..") && S_ISDIR(statbuf.st_mode)) { add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); } #ifdef __VMS if(!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX && statbuf.st_fab_rfm != FAB$C_STMLF)) { fprintf(stderr, "Warning - file %s has an unsupported VMS record format (%d)\n", whole_path, statbuf.st_fab_rfm); } #endif if(S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK))) { fprintf(stderr, "File %s is not readable (errno = %d) - ignoring\n", whole_path, errno); continue; } /* Add this so that we can detect directory loops with hard links. If we are set up to follow symlinks, then we skip this checking. */ if(!follow_links && S_ISDIR(lstatbuf.st_mode) && strcmp(d_entry->d_name, ".") && strcmp(d_entry->d_name, "..")) { if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) { fprintf(stderr,"Directory loop - fatal goof (%s %lx %lu).\n", whole_path, (unsigned long)statbuf.st_dev, (unsigned long)STAT_INODE(statbuf)); exit(1); } add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); } if(!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) && !S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode) && !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) && !S_ISDIR(lstatbuf.st_mode)) { fprintf(stderr,"Unknown file type %s - ignoring and continuing.\n", whole_path); continue; } /* Who knows what trash this is - ignore and continue */ if(status) { fprintf(stderr, "Unable to stat file %s - ignoring and continuing.\n", whole_path); continue; } s_entry = (struct directory_entry *)e_malloc(sizeof(struct directory_entry)); s_entry->next = this_dir->contents; this_dir->contents = s_entry; deep_flag = 0; s_entry->table = NULL; s_entry->name = strdup(d_entry->d_name); s_entry->whole_name = strdup (whole_path); s_entry->filedir = this_dir; s_entry->isorec.flags[0] = 0; s_entry->isorec.ext_attr_length[0] = 0; iso9660_date(s_entry->isorec.date, statbuf.st_ctime); s_entry->isorec.file_unit_size[0] = 0; s_entry->isorec.interleave[0] = 0; if(parent && parent == reloc_dir && strcmp(d_entry->d_name, "..") == 0) { s_entry->inode = UNCACHED_INODE; s_entry->dev = (dev_t)UNCACHED_DEVICE; deep_flag = NEED_PL; } else { s_entry->inode = STAT_INODE(statbuf); s_entry->dev = statbuf.st_dev; } set_723(s_entry->isorec.volume_sequence_number, 1); iso9660_file_length(d_entry->d_name, s_entry, S_ISDIR(statbuf.st_mode)); s_entry->rr_attr_size = 0; s_entry->total_rr_attr_size = 0; s_entry->rr_attributes = NULL; /* Directories are assigned sizes later on */ if(!S_ISDIR(statbuf.st_mode)) { set_733(s_entry->isorec.size, statbuf.st_size); if(S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) || S_ISFIFO(lstatbuf.st_mode) || S_ISSOCK(lstatbuf.st_mode) || S_ISLNK(lstatbuf.st_mode)) s_entry->size = 0; else s_entry->size = statbuf.st_size; } else s_entry->isorec.flags[0] = 2; if(strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..") && S_ISDIR(statbuf.st_mode) && this_dir->depth > RR_relocation_depth) { if(!reloc_dir) generate_reloc_directory(); s_entry1 = (struct directory_entry *)e_malloc(sizeof(struct directory_entry)); memcpy(s_entry1, this_dir->contents, sizeof(struct directory_entry)); s_entry1->table = NULL; s_entry1->name = strdup(this_dir->contents->name); s_entry1->next = reloc_dir->contents; reloc_dir->contents = s_entry1; s_entry1->priority = 32768; s_entry1->parent_rec = this_dir->contents; deep_flag = NEED_RE; if(use_RockRidge) { generate_rock_ridge_attributes(whole_path, d_entry->d_name, s_entry1, &statbuf, &lstatbuf, deep_flag); } deep_flag = 0; /* We need to set this temporarily so that the parent to this is correctly determined. */ s_entry1->filedir = reloc_dir; scan_directory_tree(whole_path, s_entry1); s_entry1->filedir = this_dir; statbuf.st_size = 0; statbuf.st_mode &= 0777; set_733(s_entry->isorec.size, 0); s_entry->size = 0; s_entry->isorec.flags[0] = 0; s_entry->inode = UNCACHED_INODE; deep_flag = NEED_CL; } if(generate_tables && strcmp(s_entry->name, ".") && strcmp(s_entry->name, "..")) { char buffer[2048]; switch(lstatbuf.st_mode & S_IFMT) { case S_IFDIR: sprintf(buffer, "D\t%s\n", s_entry->name); break; #ifndef NON_UNIXFS case S_IFBLK: sprintf(buffer, "B\t%s\t%lu 7%lu\n", s_entry->name, (unsigned long int)major(statbuf.st_rdev), (unsigned long int)minor(statbuf.st_rdev)); break; case S_IFIFO: sprintf(buffer, "P\t%s\n", s_entry->name); break; case S_IFCHR: sprintf(buffer, "C\t%s\t%lu %lu\n", s_entry->name, (unsigned long int)major(statbuf.st_rdev), (unsigned long int)minor(statbuf.st_rdev)); break; case S_IFLNK: readlink(whole_path, symlink_buff, sizeof(symlink_buff)); sprintf(buffer, "L\t%s\t%s\n", s_entry->name, symlink_buff); break; case S_IFSOCK: sprintf(buffer, "S\t%s\n", s_entry->name); break; #endif /* NON_UNIXFS */ case S_IFREG: default: sprintf(buffer, "F\t%s\n", s_entry->name); break; } s_entry->table = strdup(buffer); } if(S_ISDIR(statbuf.st_mode)) { int dflag; if(strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..")) { dflag = scan_directory_tree(whole_path, s_entry); /* If unable to scan directory, mark this as a non-directory */ if(!dflag) lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG; } } if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".") == 0) deep_flag |= NEED_CE | NEED_SP; /* For extension record */ /* Now figure out how much room this file will take in the directory */ if(use_RockRidge) { generate_rock_ridge_attributes(whole_path, d_entry->d_name, s_entry, &statbuf, &lstatbuf, deep_flag); } } #ifdef __VMS VMS_closedir(current_dir); #else closedir(current_dir); #endif sort_n_finish(this_dir); return 1; } void generate_iso9660_directories(struct directory *node, FILE *outfile) { struct directory *dpnt; dpnt = node; while(dpnt) { generate_one_directory(dpnt, outfile); if(dpnt->subdir) generate_iso9660_directories(dpnt->subdir, outfile); dpnt = dpnt->next; } } void 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; } } *[MKISOFS.SRC]VMS.C;2+,./ 4P /-)0123KPWO56@C7C89*̞OGHJ/* * File vms.c - assorted bletcherous hacks for VMS. Written by Eric Youngdale (1993). */ /* 14-May-1997 George Watson (watson_g@eisner.decus.org): less bletcherous (I hope) hacks for VMS. Support for VMS directory path format is cleaned up. The opendir/readdir/closedir/stat routines now in the VMS DECC runtime are used, with extensions for "." and "..". */ #ifdef __VMS #include #include #include #include #include #include "mkisofs.h" #include static struct RAB *rab; /* used for external mailfiles */ static int rms_status; static void error_exit(char * text) { fprintf(stderr, "%s\n", text); exit(33); } static char root_result[256]; char *VMS_parse(char *root) { struct NAM pnam = cc$rms_nam; struct FAB pfab = cc$rms_fab; char *cp; long int sts; pnam.nam$l_esa = root_result; pnam.nam$b_ess = 255; pfab.fab$l_fna = root; pfab.fab$b_fns = strlen(root); pfab.fab$l_dna = "."; pfab.fab$b_dns = 1; pfab.fab$l_nam = &pnam; sts = sys$parse(&pfab); if(!(sts & 1)) { fprintf(stderr, "$PARSE of root directory failed\n"); exit(sts); } cp = (char *)(pnam.nam$l_ver); cp[0] = '\0'; return(root_result); } static DIR *dircontext[32] = {NULL,}; static int dirstate[32] = {0,}; static struct dirent vms_current; static struct dirent vms_parent; char *vms_path_fixup(char * name) { char *pnt0, *pnt1; /* First strip the .DIR;1 */ pnt1 = name + strlen(name) - 6; if(strcmp(pnt1, ".DIR;1") == 0) *pnt1 = 0; pnt1 = (char *)strrchr(name, ']'); if(pnt1) { if(pnt1[1] == 0) { pnt0 = (char *)strrchr(name, '.'); if(!pnt0) pnt0 = (char *)strrchr(name, '['); *pnt1 = '\0'; pnt0 = strdup(pnt0+1); *pnt1 = ']'; return(pnt0); } *pnt1 = '.'; pnt0 = strdup(pnt1+1); strcat(name,"]"); return(pnt0); } return(NULL); } __struct_dirent_ptr32 VMS_readdir(DIR *dirp) { int i, j; vms_current.d_name[0] = vms_parent.d_name[0] = vms_parent.d_name[1] = '.'; j = 32; for(i = 0; i < 32; i++) { if(dircontext[i] == dirp) break; if(j == 32 && dircontext[i] == NULL) j = i; } if(i == 32) { if((i = j) == 32) { fprintf(stderr, "Ran out of VMS directory contexts\n"); exit(EXIT_FAILURE); } dircontext[i] = dirp; dirstate[i] = 0; } if(dirstate[i] == 0) { dirstate[i] = 1; return(&vms_current); } if(dirstate[i] == 1) { dirstate[i] = 2; return(&vms_parent); } return(readdir(dirp)); } int VMS_closedir(DIR *dirp) { int i; for(i = 0; i < 32; i++) if(dircontext[i] == dirp) break; if(i < 32) dircontext[i] = NULL; return(closedir(dirp)); } int VMS_stat(const char *__path, struct stat *__buf) { char pbuf[256]; int i, j, k; k = strlen(__path); for(i = k; i > 0; i--) if(__path[i-1] == ']') break; if(strcmp(__path+i, ".") == 0) { /* Want info about the current directory. */ for(j = i-1; j > 0; j--) if(__path[j-1] == '.' || __path[j-1] == '[') break; if(__path[j-1] == '[') sprintf(pbuf, "%.*s[000000]%.*s.DIR;1", j-1, __path, i-j-1, __path+j); else sprintf(pbuf, "%.*s]%.*s.DIR;1", j-1, __path, i-j-1, __path+j); return(stat(pbuf, __buf)); } if(strcmp(__path+i, "..") == 0) { /* Want info about the parent directory. */ for(i--; i > 0; i--) if(__path[i-1] == '.' || __path[i-1] == '[') break; if(__path[i-1] == '[') j = i; else for(j = i-1; j > 0; j--) if(__path[j-1] == '.' || __path[j-1] == '[') break; if(i == j) sprintf(pbuf, "%.*s[000000]000000.DIR;1", i-1, __path); else if(__path[j-1] == '[') sprintf(pbuf, "%.*s[000000]%.*s.DIR;1", j-1, __path, i-j-1, __path+j); else sprintf(pbuf, "%.*s]%.*s.DIR;1", j-1, __path, i-j-1, __path+j); return(stat(pbuf, __buf)); } return(stat(__path, __buf)); } static int 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; rab->rab$l_fab = fab; *fab = cc$rms_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 = NULL; 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(struc t 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; void vms_write_one_file(char *filename, int size, FILE *outfile) { int status, i; char buffer[SECTOR_SIZE * NSECT]; int count; int use; int remain; open_file(filename); remain = size; while(remain > 0) { use = (remain > SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain); use = ROUND_UP(use); /* Round up to nearest sector boundary */ memset(buffer, 0, use); rab->rab$l_ubf = buffer; rab->rab$w_usz = sizeof(buffer); status = sys$read(rab); fwrite(buffer, 1, use, outfile); last_extent_written += use/SECTOR_SIZE; if((last_extent_written % 1000) < use/SECTOR_SIZE) fprintf(stderr,"%d..", last_extent_written); remain -= use; } close_file(rab); } int readlink(char *dn, char *sn, int sn_len) { int x; x = strlen(dn); if(x > sn_len) x = sn_len; strncpy(sn, dn, x); return x; } #endif *[MKISOFS.SRC]VMS.H;2+,. / 4P -)0123KPWO 566C7cMC89*̞OGHJ/* 14-May-1997 George Watson (watson_g@eisner.decus.org): replaced original VMS support include file with these prototypes, that match the new VMS support routines in VMS.C. */ #ifdef __VMS char *VMS_parse(char *); int readlink(char *, char *, int); char *vms_path_fixup(char *); void vms_write_one_file(char *, int, FILE *); __struct_dirent_ptr32 VMS_readdir(DIR *); int VMS_closedir(DIR *); int VMS_stat(const char *, struct stat *); #endif *[MKISOFS.SRC]WRITE.C;2+,.6/ 4P61K-)0123KPWO756݀C7rC89*̞OGHJ/* * Program write.c - dump memory structures to file for iso9660 filesystem. Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* 14-May-1997 George Watson (watson_g@eisner.decus.org): fix an error in generate_root_record, which set the length incorrectly by using ISO_DIRECTORY_RECORD_LEN instead of sizeof(). Make the same change throughout this module. */ #include #include #include "mkisofs.h" #include "iso9660.h" #include #include #include "vms.h" #ifdef __svr4__ extern char * strdup(const char *); #endif /* Max number of sectors we will write at one time */ #define NSECT 16 /* Counters for statistics */ static int table_size = 0; static int total_dir_size = 0; static int rockridge_size = 0; static struct directory **pathlist; static next_path_index = 1; /* Used to fill in some of the information in the volume descriptor. */ static struct tm *local; /* Routines to actually write the disc. We write sequentially so that we could write a tape, or write the disc directly */ #define FILL_SPACE(X) memset(vol_desc.X, ' ', sizeof(vol_desc.X)) void set_721(void *p, unsigned int i) /* LSB2 */ { unsigned char *pnt = (unsigned char *)p; pnt[0] = i & 0xff; pnt[1] = (i >> 8) & 0xff; } void set_722(void *p, unsigned int i) /* MSB2 */ { unsigned char *pnt = (unsigned char *)p; pnt[0] = (i >> 8) & 0xff; pnt[1] = i & 0xff; } void set_723(void *p, unsigned int i) /* LSB2/MSB2 pair */ { unsigned char *pnt = (unsigned char *)p; pnt[3] = pnt[0] = i & 0xff; pnt[2] = pnt[1] = (i >> 8) & 0xff; } void set_731(void *p, unsigned int i) /* LSB4 */ { unsigned char *pnt = (unsigned char *)p; pnt[0] = i & 0xff; pnt[1] = (i >> 8) & 0xff; pnt[2] = (i >> 16) & 0xff; pnt[3] = (i >> 24) & 0xff; } void set_732(void *p, unsigned int i) /* MSB4 */ { unsigned char *pnt = (unsigned char *)p; pnt[3] = i & 0xff; pnt[2] = (i >> 8) & 0xff; pnt[1] = (i >> 16) & 0xff; pnt[0] = (i >> 24) & 0xff; } int get_733(void *p) { unsigned char *pnt = (unsigned char *)p; return((pnt[0] & 0xff) | ((pnt[1] & 0xff) << 8) | ((pnt[2] & 0xff) << 16) | ((pnt[3] & 0xff) << 24)); } void set_733(void *p, unsigned int i) /* LSB4/MSB4 pair */ { unsigned char *pnt = (unsigned char *)p; pnt[7] = pnt[0] = i & 0xff; pnt[6] = pnt[1] = (i >> 8) & 0xff; pnt[5] = pnt[2] = (i >> 16) & 0xff; pnt[4] = pnt[3] = (i >> 24) & 0xff; } static void xfwrite(void *buffer, int count, int size, FILE *file) { while(count) { int got = fwrite(buffer, size, count, file); if(got <=0 ) { fprintf(stderr, "cannot fwrite %d*%d\n",size,count); exit(1); } count -= got; *(char**)&buffer += size*got; } } struct deferred_write { struct deferred_write *next; char *table; unsigned int extent; unsigned int size; char *name; }; static struct deferred_write *dw_head = NULL, *dw_tail = NULL; static struct directory_entry *sort_dir; unsigned int last_extent_written = 0; static struct iso_primary_descriptor vol_desc; static path_table_index; static time_t begun; /* We recursively walk through all of the directories and assign extent numbers to them. We have already assigned extent numbers to everything that goes in front of them */ void assign_directory_addresses(struct directory *node) { struct directory *dpnt; int dir_size; dpnt = node; while(dpnt) { dpnt->extent = last_extent; dpnt->path_index = next_path_index++; dir_size = (dpnt->size + (SECTOR_SIZE - 1)) >> 11; last_extent += dir_size; /* Leave room for the CE entries for this directory. Keep them close to the reference directory so that access will be quick. */ if(dpnt->ce_bytes) last_extent += ROUND_UP(dpnt->ce_bytes) >> 11; if(dpnt->subdir) assign_directory_addresses(dpnt->subdir); dpnt = dpnt->next; } } static void write_one_file(char *filename, unsigned int  size, FILE *outfile) { FILE *infile; char buffer[SECTOR_SIZE * NSECT]; int use; int remain; if((infile = fopen(filename, "rb")) == NULL) { #ifdef sun fprintf(stderr, "cannot open %s: (%d)\n", filename, errno); #else fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno)); #endif exit(1); } remain = size; while(remain > 0) { use = (remain > SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain); use = ROUND_UP(use); /* Round up to nearest sector boundary */ memset(buffer, 0, use); if(fread(buffer, 1, use, infile) == 0) { fprintf(stderr, "cannot read from %s\n", filename); exit(1); } xfwrite(buffer, 1, use, outfile); last_extent_written += use/SECTOR_SIZE; #if 0 if((last_extent_written % 1000) < use/SECTOR_SIZE) fprintf(stderr, "%d..", last_extent_written); #else if((last_extent_written % 5000) < use/SECTOR_SIZE) { time_t now; time_t the_end; double frac; time(&now); frac = last_extent_written / (double)last_extent; the_end = begun + (now - begun) / frac; fprintf(stderr, "%6.2f%% done, estimate finish %s", frac * 100., ctime(&the_end)); } #endif remain -= use; } fclose(infile); } static void write_files(FILE *outfile) { struct deferred_write *dwpnt, *dwnext; dwpnt = dw_head; while(dwpnt) { if(dwpnt->table) { xfwrite(dwpnt->table, 1, ROUND_UP(dwpnt->size), outfile); last_extent_written += ROUND_UP(dwpnt->size) / SECTOR_SIZE; table_size += dwpnt->size; /* fprintf(stderr,"Size %d ", dwpnt->size); */ free(dwpnt->table); } else { #ifdef __VMS vms_write_one_file(dwpnt->name, dwpnt->size, outfile); #else write_one_file(dwpnt->name, dwpnt->size, outfile); #endif free(dwpnt->name); } dwnext = dwpnt; dwpnt = dwpnt->next; free(dwnext); } } #if 0 static void dump_filelist(void) { struct deferred_write *dwpnt; dwpnt = dw_head; while(dwpnt) { fprintf(stderr, "File %s\n", dwpnt->name); dwpnt = dwpn~ MKISOFS.BCK)[MKISOFS.SRC]WRITE.C;2P6 t->next; } fprintf(stderr,"\n"); } #endif 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; while(*rpnt && *lpnt) { if(*rpnt == ';' && *lpnt != ';') return -1; if(*rpnt != ';' && *lpnt == ';') return 1; if(*rpnt == ';' && *lpnt == ';') return 0; if(*rpnt < *lpnt) return -1; if(*rpnt > *lpnt) return 1; rpnt++; lpnt++; } if(*rpnt) return 1; if(*lpnt) return -1; return 0; } void sort_directory(struct directory_entry **sort_dir) { int dcount = 0; int i, len; struct directory_entry *s_entry; struct directory_entry **sortlist; s_entry = *sort_dir; while(s_entry) { dcount++; s_entry = s_entry->next; } /* OK, now we know how many there are. Build a vector for sorting. */ sortlist = (struct directory_entry **)e_malloc( sizeof(struct directory_entry *) * dcount); dcount = 0; s_entry = *sort_dir; while(s_entry) { sortlist[dcount] = s_entry; len = s_entry->isorec.name_len[0]; s_entry->isorec.name[len] = 0; dcount++; s_entry = s_entry->next; } qsort(sortlist, dcount, sizeof(struct directory_entry *), compare_dirs); /* Now reassemble the linked list in the proper sorted order */ for(i = 0; i < dcount-1; i++) sortlist[i]->next = sortlist[i+1]; sortlist[dcount-1]->next = NULL; *sort_dir = sortlist[0]; free(sortlist); } void generate_root_record(void) { time_t ctime; time(&ctime); local = localtime(&ctime); root_record.length[0] = ISO_DIRECTORY_RECORD_LEN + 1; root_record.ext_attr_length[0] = 0; set_733(root_record.extent, root->extent); set_733(root_record.size, ROUND_UP(root->size)); iso9660_date(root_record.date, ctime); root_record.flags[0] = 2; root_record.file_unit_size[0] = 0; root_record.interleave[0] = 0; set_723(root_record.volume_sequence_number, 1); root_record.name_len[0] = 1; root_record.name[0] = 0; } static void assign_file_addresses(struct directory *dpnt) { struct directory *finddir; struct directory_entry *s_entry; struct file_hash *s_hash; struct deferred_write *dwpnt; char whole_path[1024]; while(dpnt) { s_entry = dpnt->contents; for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) { /* This saves some space if there are symlinks present */ s_hash = find_hash(s_entry->dev, s_entry->inode); if(s_hash) { if(verbose) fprintf(stderr, "Cache hi>t for %s%s%s\n", s_entry->filedir->de_name, SPATH_SEPARATOR, s_entry->name); set_733(s_entry->isorec.extent,s_hash->starting_block); set_733(s_entry->isorec.size, s_hash->size); continue; } if(strcmp(s_entry->name,".") && strcmp(s_entry->name,"..") && s_entry->isorec.flags[0] == 2) { finddir = dpnt->subdir; while(1) { if(finddir->self == s_entry) break; finddir = finddir->next; if(!finddir) { fprintf(stderr,"Fatal goof\n"); exit(1); } } set_733(s_entry->isorec.extent, finddir->extent); s_entry->starting_block = finddir->extent; s_entry->size = ROUND_UP(finddir->size); total_dir_size += s_entry->size; add_hash(s_entry); set_733(s_entry->isorec.size, ROUND_UP(finddir->size)); } else { if(strcmp(s_entry->name,".") == 0 || strcmp(s_entry->name,"..") == 0) { if(strcmp(s_entry->name,".") == 0) { set_733(s_entry->isorec.extent, dpnt->extent); /* Set these so that the hash table has the correct information */ s_entry->starting_block = dpnt->extent; s_entry->size = ROUND_UP(dpnt->size); add_hash(s_entry); s_entry->starting_block = dpnt->extent; set_733(s_entry->isorec.size, ROUND_UP(dpnt->size)); } else { if(dpnt == root) total_dir_size += root->size; set_733(s_entry->isorec.extent, dpnt->parent->extent); /* Set these so that the hash table has the correct information */ s_entry->starting_block = dpnt->parent->extent; s_entry->size = ROUND_UP(dpnt->parent->size); add_hash(s_entry); s_entry->starting_block = dpnt->parent->extent; set_733(s_entry->isorec.size, ROUND_UP(dpnt->parent->size)); } } else { /* Now we schedule the file to be written. This is all quite straightforward, just make a list and assign extents as we go. Once we get through writing all of the directories, we should be ready write out these files. */ if(s_entry->size) { dwpnt = (struct deferred_write *)e_malloc( sizeof(struct deferred_write)); if(dw_tail) { dw_tail->next = dwpnt; dw_tail = dwpnt; } else { dw_head = dwpnt; dw_tail = dwpnt; } if(s_entry->inode == TABLE_INODE) { dwpnt->table = s_entry->table; dwpnt->name = NULL; } else { dwpnt->table = NULL; strcpy(whole_path, s_entry->whole_name); dwpnt->name = strdup(whole_path); } dwpnt->next = NULL; dwpnt->size = s_entry->size; dwpnt->extent = last_extent; set_733(s_entry->isorec.extent, last_extent); s_entry->starting_block = last_extent; add_hash(s_entry); last_extent += ROUND_UP(s_entry->size) >> 11; if(verbose) fprintf(stderr,"%d %d %s\n", s_entry->starting_block, last_extent-1, whole_path); #ifdef DBG_ISO if((ROUND_UP(s_entry->size) >> 11) > 500) { fprintf(stderr, "Warning: large file %s\n", whole_path); fprintf(stderr, "Starting block is %d\n", s_entry->starting_block); fprintf(stderr, "Reported file size is %d extents\n", s_entry->size); } #endif if(last_extent > (700000000 >> 11)) { /* More than 700Mb? Punt */ fprintf(stderr, "Extent overflow processing file %s\n", whole_path); fprintf(stderr, "Starting block is %d\n", s_entry->starting_block); fprintf(stderr, "Reported file size is %d extents\n", s_entry->size); exit(1); } } else { /* 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(s_entry->isorec.extent, last_extent); } } } } if(dpnt->subdir) assign_file_addresses(dpnt->subdir); dpnt = dpnt->next; } } void generate_one_directory(struct directory *dpnt, FILE *outfile) { unsigned int total_size, ce_size; char *directory_buffer; char *ce_buffer; unsigned int ce_address; struct directory_entry *s_entry, *s_entry_d; int new_reclen; unsigned int dir_index, ce_index; total_size = (dpnt->size + (SECTOR_SIZE - 1)) & -SECTOR_SIZE; directory_buffer = (char *)e_malloc(total_size); memset(directory_buffer, 0, total_size); dir_index = 0; ce_size = (dpnt->ce_bytes + (SECTOR_SIZE - 1)) & -SECTOR_SIZE; ce_buffer = NULL; if(ce_size) { ce_buffer = (char *)e_malloc(ce_size); memset(ce_buffer, 0, ce_size); ce_index = 0; /* Absolute byte address of CE entries for this directory */ ce_address = last_extent_written + (total_size >> 11); ce_address = ce_address << 11; } s_entry = dpnt->contents; while(s_entry) { /* We do not allow directory entries to cross sector boundaries. Simply pad, and then start the next entry at the next sector */ new_reclen = s_entry->isorec.length[0]; if ((dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE) dir_index = (dir_index + (SECTOR_SIZE - 1)) & -SECTOR_SIZE; memcpy(directory_buffer + dir_index, &s_entry->isorec, ISO_DIRECTORY_RECORD_LEN + s_entry->isorec.name_len[0]); dir_index += ISO_DIRECTORY_RECORD_LEN + s_entry->isorec.name_len[0]; /* Add the Rock Ridge attributes, if present */ if(s_entry->rr_attr_size) { if(dir_index & 1) directory_buffer[dir_index++] = 0; /* If the RR attributes were too long, then write the CE records, as required. */ if(s_entry->rr_attr_size != s_entry->total_rr_attr_size) { unsigned char *pnt; int len, nbytes; /* Go through the entire record and fix up the CE entries so that the extent and offset are correct */ pnt = s_entry->rr_attributes; len = s_entry->total_rr_attr_size; while(len > 3) { if(pnt[0] == 'C' && pnt[1] == 'E') { nbytes = get_733(pnt+20); if((ce_index & (SECTOR_SIZE - 1)) + nbytes >= SECTOR_SIZE) ce_index = ROUND_UP(ce_index); set_733(pnt+4, (ce_address + ce_index) >> 11); set_733(pnt+12, (ce_address + ce_index) & (SECTOR_SIZE - 1)); /* Now store the block in the ce buffer */ memcpy(ce_buffer + ce_index, pnt + pnt[2], nbytes); ce_index += nbytes; if(ce_index & 1) ce_index++; } len -= pnt[2]; pnt += pnt[2]; } } rockridge_size += s_entry->total_rr_attr_size; memcpy(directory_buffer + dir_index, s_entry->rr_attributes, s_entry->rr_attr_size); dir_index += s_entry->rr_attr_size; } if(dir_index & 1) directory_buffer[dir_index++] = 0; s_entry_d = s_entry; s_entry = s_entry->next; if (s_entry_d->rr_attributes) free(s_entry_d->rr_attributes); free (s_entry_d->name); free (s_entry_d); } sort_dir = NULL; if(dpnt->size != dir_index) fprintf(stderr, "Unexpected directory length %d %d %s\n", dpnt->size, dir_index, dpnt->de_name); xfwrite(directory_buffer, 1, total_size, outfile); last_extent_written += total_size >> 11; free(directory_buffer); if(ce_size) { if(ce_index != dpnt->ce_bytes) fprintf(stderr, "Continuation entry record length mismatch (%d %d).\n", ce_index, dpnt->ce_bytes); xfwrite(ce_buffer, 1, ce_size, outfile); last_extent_written += ce_size >> 11; free(ce_buffer); } } static void build_pathlist(struct directory *node) { struct directory *dpnt; dpnt = node; while(dpnt) { pathlist[dpnt->path_index] = dpnt; if(dpnt->subdir) build_pathlist(dpnt->subdir); dpnt = dpnt->next; } } int compare_paths(const void *rr, const void *ll) { struct directory **r, **l; r = (struct directory **)rr; l = (struct directory **)ll; if((*r)->parent->path_index < (*l)->parent->path_index) return -1; if((*r)->parent->path_index > (*l)->parent->path_index) return 1; return strcmp((*r)->self->isorec.name, (*l)->self->isorec.name); } void generate_path_tables(void) { struct directory *dpnt; char *npnt, *npnt1; int namelen; struct directory_entry *de; int fix; int tablesize; int i,j; /* First allocate memory for the tables and initialize the memory */ tablesize = path_blocks << 11; path_table_m = (char *)e_malloc(tablesize); path_table_l = (char *)e_malloc(tablesize); memset(path_table_l, 0, tablesize); memset(path_table_m, 0, tablesize); /* Now start filling in the path tables. Start with root directory */ path_table_index = 0; pathlist = (struct directory **)e_malloc( sizeof(struct directory *) * next_path_index); memset(pathlist, 0, sizeof(struct directory *) * next_path_index); build_pathlist(root); do { fix = 0; qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *), compare_paths); for(j = 1; j < next_path_index; j++) if(pathlist[j]->path_index != j) { pathlist[j]->path_index = j; fix++; } } while(fix); for(j = 1; j < next_path_index; j++) { dpnt = pathlist[j]; if(!dpnt) { fprintf(stderr, "Entry %d not in path tables\n", j); exit(1); } npnt = dpnt->de_name; if(*npnt == 0 || dpnt == root) npnt = "."; /* So the root comes out OK */ npnt1 = strrchr(npnt, PATH_SEPARATOR); if(npnt1) npnt = npnt1 + 1; de = dpnt->self; if(!de) { fprintf(stderr,"Fatal goof\n"); exit(1); } namelen = de->isorec.name_len[0]; path_table_l[path_table_index] = namelen; path_table_m[path_table_index] = namelen; path_table_index += 2; set_731(path_table_l + path_table_index, dpnt->extent); set_732(path_table_m + path_table_index, dpnt->extent); path_table_index += 4; set_721(path_table_l + path_table_index, dpnt->parent->path_index); set_722(path_table_m + path_table_index, dpnt->parent->path_index); path_table_index += 2; for(i = 0; i < namelen; i++) { path_table_l[path_table_index] = de->isorec.name[i]; path_table_m[path_table_index] = de->isorec.name[i]; path_table_index++; } if(path_table_index & 1) path_table_index++; /* For odd lengths we pad */ } free(pathlist); if(path_table_index != path_table_size) fprintf(stderr, "Path table lengths do not match %d %d\n", path_table_index, path_table_size); } static void memcpy_max(char *to, char *from, int max) { int n = strlen(from); if(n > max) n = max; memcpy(to, from, n); } int iso_write(FILE *outfile) { char buffer[2048]; char iso_time[17]; int should_write; int i; time(&begun); assign_file_addresses(root); memset(buffer, 0, sizeof(buffer)); /* This will break in the year 2000, I suppose, but there is no good way to get the top two digits of the year. */ sprintf(iso_time, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00", 1900 + local->tm_year, local->tm_mon+1, local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec); /* First, we output 16 sectors of all zero (except for our name) */ strcpy(buffer, "mkisofs v1.05.vms7"); for(i = 0; i < 16; i++) xfwrite(buffer, 1, sizeof(buffer), outfile); memset(buffer, 0, sizeof(buffer)); last_extent_written += 16; /* Next we write out the primary descriptor for the disc */ memset(&vol_desc, 0, sizeof(vol_desc)); vol_desc.type[0] = ISO_VD_PRIMARY; memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID)); vol_desc.version[0] = 1; FILL_SPACE(system_id); memcpy_max(vol_desc.system_id, system_id, strlen(system_id)); FILL_SPACE(volume_id); memcpy_max(vol_desc.volume_id, volume_id, strlen(volume_id)); should_write = last_extent; set_733(vol_desc.volume_space_size, last_extent); set_723(vol_desc.volume_set_size, 1); set_723(vol_desc.volume_sequence_number, 1); set_723(vol_desc.logical_block_size, 2048); /* The path tables are used by DOS based machines to cache directory locations */ set_733(vol_desc.path_table_size, path_table_size); set_731(vol_desc.type_l_path_table, path_table[0]); set_731(vol_desc.opt_type_l_path_table, path_table[1]); set_732(vol_desc.type_m_path_table, path_table[2]); set_732(vol_desc.opt_type_m_path_table, path_table[3]); /* Now we copy the actual root directory record */ memcpy(vol_desc.root_directory_record, &root_record, ISO_DIRECTORY_RECORD_LEN + 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(appid) memcpy_max(vol_desc.copyright_file_id, appid, strlen(appid)); FILL_SPACE(abstract_file_id); if(appid) memcpy_max(vol_desc.abstract_file_id, appid, strlen(appid)); FILL_SPACE(bibliographic_file_id); if(appid) memcpy_max(vol_desc.bibliographic_file_id, appid, strlen(appid)); FILL_SPACE(creation_date); FILL_SPACE(modification_date); FILL_SPACE(expiration_date); FILL_SPACE(effective_date); vol_desc.file_structure_version[0] = 1; FILL_SPACE(application_data); memcpy(vol_desc.creation_date, iso_time, 17); memcpy(vol_desc.modification_date, iso_time, 17); memcpy(vol_desc.expiration_date, "0000000000000000", 17); memcpy(vol_desc.effective_date, iso_time, 17); xfwrite(&vol_desc, 1, 2048, outfile); last_extent_written++; /* Now write the end volume descriptor. Much simpler than the other one */ memset(&vol_desc, 0, sizeof(vol_desc)); vol_desc.type[0] = ISO_VD_END; memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID)); vol_desc.version[0] = 1; xfwrite(&vol_desc, 1, 2048, outfile); last_extent_written++; /* Next we write the path tables */ xfwrite(path_table_l, 1, path_blocks << 11, outfile); xfwrite(path_table_m, 1, path_blocks << 11, outfile); last_extent_written += 2*path_blocks; free(path_table_l); free(path_table_m); path_table_l = NULL; path_table_m = NULL; /* OK, all done with that crap. Now write out the directories. This is where the fur starts to fly, because we need to keep track of each file as we find it and keep track of where we put it. */ #ifdef DBG_ISO fprintf(stderr,"Total directory extents being written = %d\n", last_extent); #endif #if 0 generate_one_directory(root, outfile); #endif generate_iso9660_directories(root, outfile); if(extension_record) { xfwrite(extension_record, 1, SECTOR_SIZE, outfile); last_extent_written++; } /* Now write all of the files that we need. */ fprintf(stderr, "Total extents scheduled to be written = %d\n", last_extent); write_files(outfile); fprintf(stderr, "Total extents actually written = %d\n", last_extent_written); /* Hard links throw us off here */ if(should_write != last_extent){ fprintf(stderr, "Number of extents written not what was predicted. Please fix.\n"); fprintf(stderr, "Predicted = %d, written = %d\n", should_write, last_extent); } fprintf(stderr,"Total translation table size: %d\n", table_size); fprintf(stderr,"Total rockridge attributes bytes: %d\n", rockridge_size); fprintf(stderr,"Total directory bytes: %d\n", total_dir_size); fprintf(stderr,"Path table size(bytes): %d\n", path_table_size); #ifdef DEBUG fprintf(stderr, "next extent, last_extent, last_extent_written %d %d %d\n", next_extent, last_extent, last_extent_written); #endif return 0; } *[MKISOFS]TODO.;1+,8. / 4 - 0123KPWO 56!>o㏗7 89*̞OGHJ 1) Allow multiple input paths to be concatenated together. This is a little tricky, because the directory entries need to be correctly sorted as per iso9660 specifications. It would be better to force the user to add hard links or copies of the files rather than do the wrong thing. Leave alone for the time being, I am not sure that this feature is really needed. 2) For symlinks, we may need to strip out the leading path information if the link is to an absolute file, and the absolute address is in the space that we are dumping to the CDROM. Who the hell knows what we should really do with this, actually. Leave it for now and see if anyone squalks. 3) Find out if output needs to be written at a particular blocksize or not. /~ MKISOFS.BCKJ  KISOFS]MKI CTU)$/3Vv,-6ox 1},xO>}[W CrVZP"YGbb*w V&JY9SQVK]'m_ZK@QC7Ӊ?<xwZUu u<,C#g3if^9BXYrG ZF[J#@XvEB17YYz}RnۘXO#t&{[RgX l/UpGN:gsfwP:4 HJR@B\ Y~Js/R' }@FC/:؍, t8A(Ywqvq$FlH{,5/z\PIK)-@eYy/-}c0k0-qae w1|J% P= XQ qU(]k^ݻnIn$ǙI -u Nro8WzhJ7Hf8lo]M2&'K0a2@7 6N8b0K^S!\ 0`g{@X J@niDcSLhzMUV83}a_gp6! NLJTökW&P5P4oLe) 27?%DZg T?~.;EO{sgQ@'Y3!>0m1l_FNfZːsd68XNM{4m(xc̋r`*~ ?sf*h?b/ϪX~Rk j+ x{/*ۻ00ykb r_z}8eM~p+pl? 3?٩|to4eV ;GMs5KZr 6cy/!OYF7w2KV?b bu"ߠki{Uo_9;M )0oTI wN B`BY Xo4U+9$>yk&3P TW |9yOt(~:B!s.cPz"*V mـCg',975fs&R_\LٌuuJ7_7qKs\`#\@9l_(!׸5DVz3PV.R0Di'n=8g^t63g&~-|^dqTUyVlX i5#ru/@y,v5'}r!62,$.B;a=Xtdz0T,**,9+c!){w3WvDMQ aPC>7_6FxGQzNm; YfxE8N&}2!qO^yOfnl6a6N]V5<-1 D R< \XV|`K-ClULOB S-;+f h.l*suiM{*Q;M,FK/"fq-=::xDzMX;%'oev@Wm\Wd3&2s%1^z"=QJr3Non4>!, + TO>fX7#?D.'xy$>6?!uB KjQ@gS $?/-|[Ou`PJLJ#MmE7):T {75bo*F<0>EHHkE S4UcEbrG coF:{1=2?("${H; ž>voAH3Y5&z POZZ~YK'*e4SQW 0&l803#%Y9rX"u%}b`AYVit.yp + f8\{zEP\&J]!=G}V HpCiIwJenl6 <h%ImX@3DZCFX=ZLBOO0FBg*}>o)"9w9vE<'8mqNJxDUE[vS t[$#A xZUzz=AO|I]C&>3vVZYM^g!m-s~+ !?jw&+KJbI[4`c8MC*2"(8YrnWOMSk@,F QLWf1 I[Ug)/LGL .7Fb>kV, !v^Pq i]οzg|.X6?d+7AAR uS{x% iD!b D9D z~Yysj:G0W)HO">Kl~([B\0@e~@)B$0 Xf/D|H=?@<CDv`sU= ۿhEiu)n;vy{;mR?1xayf,:n%NLc;W?"@yK"G5"s+WR!L#4M9r Z{HJ 2s>Rn,@'YT>Y~Z&& H72=29w|E~YnC 6GZr/f}<l> h;.gMxH#.o^p5M^@SCtN]9-m+8@H^?-0R]Gmc4VK ZK^j 5isf3)a#G8hbjrD4xT]" F)E"\@Mi\%lC-9C%p KYrv/Wbzv\*w gB3 z:U5H S KlQV1\ O541y}@a5~eST YEdMLC W3MKJ)GkZz"d@F5PHDIX0z\NIUU obqDagc"'7|) Iw^{"(%<&t$uu~F 1$ V1<92TgYYF 8IQ2oruSe`yc/}e wr/ALUc'7Y|V^nFS60XC'_9r7r5NF:ZJk!C6WE]hI|Z[|@^n[,S XwTF~\;5N7-~+WX\-eX CoWn*? uQ>D{,A\/$o$XDt +R J-_`}Qt"[Whd$ tߙ2' o\+V%O8bIA EWW.iy-i[nV 8 VY(2~)HI .㜶t=> %K*)]6Ix=`eO4H%ArV"HrX [9Z9 3\F1Xk6{W^ **|l,61#wS!y!XjzDF$55IaiJR9=HB kFaJ IkP*_3rC;?L3]v|J!}(K!D>K&9X< _ bM dӷ~UDPTJ7QA#P.-[ _K EXP,QJHL oO7DL[Gj[2 HP!3_ ybgtFQu Fzk,k$g7A !u &1:YPLa gv UJ>{<:h;(3yNRfO |.3/ y$G(N̓^I+x8N1n*PC;!u3swcFj4F AjrTKk^+2nI3zn'+z9z9*!`Hi|}psn h. #XQwy3o#v2RciG"d }M?  a+{'B5]d7V g@T EryوkD9s+tck=#BG:UeZF! |C_xqmg|z(txaUXIbE ]97;jv?dRX(1d*6vl!Gc2ɪ F(%x ?gy LO[iKh T?4-J9X@bt\Gu{ M0"3#@aucW*y&tCuPXPAq $0,r!Hv`BJPRJ 846N*"<)5][B4L^ʑN?x?U9F D 78 %kyR{j(~:D *TGLUDd^ (P2AQ ::X|g%Lx3o`j{KJ U#zWo)3|f +={T9 6uWs$e?̕Nq k^n|R j{N/#`Mxu(\5~sZ!dbJLcqc%u|*4P.8RSYy-++*V(P#9k7d )(.iBYV{7,,o_=tOLJn)hv]tfѫ{2ZhVv#o[9Q#J,ogQE}(ZD9z_w iZ.{5 94h)HWCnt!2&~' @c'7>gtMpl&nI+4>?B9$UO}"sb$>"7iMim_6bM{x_)rH)qs&.n,`C|8!$~doKc@>>9fM ]"O-D[ŮG'>|bJnu|}, (.a)$R  _"-NG0zq6TE.34%_&dU$ M 0P[ V%6{w0/QAK3oog|fA& c}WIenlR^4bG8'6HROMuV2FzT?l ~XuIg /szs)vK=-e$RSVE.LZt"aN[}K6=^R^ b;kfFR4Y>o[:D:x#0h6 QG*zO }7#6ZHSy|cN5N2=`udt]H9nD0Wa:CK %ZtaKMl4E| ^n* IZtLe/6[2* A[5y3HQ\f(c?!y-$f40XJ>9ˣ["p:wUpH  D5 )ґ3QVvK3zB>K Z '9Az}IwY]y*En4{>J; ||mc8[k^yAaAAx8E^)k} [CG0W&=uB"d V/ Jt[Un lux j? QR?=M=]7aWD- s a(8%`isO(GGCUnR>2Rh/CzO=/Pwa:3m ,Ll<%t(kg L:LW[E0[i@+cx nXC>zBPJ- S{GN.?:vT(;Ss^l;i3MtNc%`Fnu&0~%,}f]H6xj;cJ)-Anj)8.4&U! 4'$3"\%%?VRN +nkC;y?hL:,(f$~<85$ou71F~ b$`\#_3[-5W?t}<0-5Fi~xtp5_ G$PfC tRBhQO\^jIS,SM*/ w^CY0El8A+CCE0m &rk1kf[a T5UDhrvEIvK2^Etq-!=\<5mWyJ)$\qc(1o ro6_n--;x3j\9(4qVJ]AkhD1x2Ee25"4$O.1z~ M4n7/Aq.6R# gn|zNHj>#M4qûgQ >RP;`w*!u} <% 2y.\?AR>V'i\o1]JQABTc!&1}QMh6|<1$>AgrT.)]|7NlY^Na.DQ ?KY#PHlTq9:d`9=ZuS@ZOWP9hBp70_?됔zE #&UfX#I[;K2\vP| N2Jg7> A-P쳺fZ=_3quU}aCY &wkYLt5]p]]S&ZI%/>|_f%0l;oc""pcCOHA@1:_!&J; fJ ~ 7 qgLPO\5V![Pa&C#Ixgu}*6\w` EFj"MnHlw`7L?+-me= _'{,Zm\Ұ<1!5XzfGTo8^rh^(h +!;\[MXX$,A8P|#Nz hs řdx= 'AH,c0LD2.ٻV =ȱArߝJnQEl/W4رA-JFX˭i"rT pˆ[6v\gІd3օ[RuF4c._yv<!ru ]8&xM&"Gqcc )G]aLr2k3L]MM8xp[fQ~/>v&A$ey[ L.099vqAC]GLVPNHcJ\!oUCv SBR?&MM'Hc2QYq;@+{ftdGlKjd^Il1)T)_WoGesyx" $4XDk`?"^P)q! uHnZ&v.ـEle{CM_!GRZ3 Og%x 2Ef1?Ϊ ;?9/5F9]mWgE/I?4k iL{ukT{'6chQ -ZG dU}{Q]#!Rubzgi| $ SG6YU ̿4_V=&= F:4 be5G|nEGcXN= .PY6*28r"e91ds}! bM RB 4toHH}>O~{ AMM)VDy2LzY-!V$m$R=x%M-,nsg22:twSZ,&4+Y`-m,6Eh E0n\( pmGעEF|NgC(A-Y_GG<{M!%^P@ We%n:|E;wrH207 &gXq zK x D9sfh4iZI\8o4atCz3u^W!aU! ^AUxQ|GpKfWhir\Y$5~V@6`anߍ#um! ba,<#IrjEuU! HgyDSHo;I. #P[(?b(s{4 |MR+g_ApGSM$e}v x(A6v0c4DOxQMt<)c5Y K"I!Y:4rUlK%U_(a@pWS m ]A=T;dMRay'IUt_xKI@+يM kG`/EH$\TɟrxB;Q4.-Ezp_QNa![NR|nRNG;-v1"Ui_gr_ F"0/ dJB"!rpaZ{6W1k6c [(z]Ex3Jp oN05GNI_8T c F`V?]Pt23>N$IZ Nl$dtxVU3FED^ 5z5)33hXG$is8WycK]QAbP b$`nd}[  [H"y6uY oiR<"׍izf+ ] d"vx`#?d\!f"-=R,|F Pt":(o{> .=:#Tx?oDJ;o+<:Fi.p]#nvC#B/V !q'|b}iJVe kv[c[Tw;U_}Yb?]1FWZ4jo Cqs\Zuy9C7o5$#+-tSU?=Rm2=6I` 3L#S*<E| {#yrdM=k^-!M o+:L7>]V_r$m~qLB|7$Il5Mg ~J00:1z9 KfRwxi,1ƚ2x S AG*UR@hM@ nEuG!H|GZt}  v^F/UoUY42~TYg:3[Ca@s>Y,N1^&Oto\k*vUa#)Q#k)#@MW-kb waQ e)dM.(4jbV^>jY6jT|CaJ /InĀe/oyKHc\V<;rO_Gzn E/RL 7BA.s#Sb?_(r<6jJ  +x$<æ9 ^^c#!g6yzP hqv!ODjH 5FdH< R 76H#^{fq(Dn$RV"~ ](aNn9?yamD!9t P1koN-fTJM;ZVMyNRyG8xId_v@,9Z(=/I ,\[AB6)%&W!Irvl;gaCAoL(DI-urr~1ERz<#erOSk m >?) m>UN xvGKb7& L Q*?10/$@7ngmY1(Xt [@E#z3>PHl%hc vtO:hu|?,O. `a_~/2Q [*2.J~my{FL;"!#506&H.yzrs:Oz3}ROQi]yZ@!e\!a}4;a)5e N5X_TRuGq d+ZM/} P]:d(z&SKRH7C BtisHCMȝin+)#XfM tm$qzbGJyHY[$],e-HBKJ|vdw2+-0 lHN e;=.(dv&Bmf}:{ 74!y,".^y1:pC XaW9y_m 4&?g2{F0 GSgP 1t,Ty.wlEmit:B6aG)Wn]E`nxlf"n)!(64 -v)X/|?6nEk`/.`n<0++0kIG IaQKZz:O 8NY/K>b+w 2{0W \"fp%3v?mrFXmv_ ZuOKyl\V`XDVo?wwkcmy[bmP:RWAMP65M#nPK L`(4% r(wx\BKhw*DJC lcR8l2K=9> S1&i,"RY@<{(?YU6YXDncdG`(3ZmM5bS`-|M AEmvEMfZw 7AW^ !U_x> Zk0& 1)x$Lh]w#y,fgNI)FYh J`M& H@ozzzmC3 z:mGAXZ+  0Q YR@bHz%_Jw*v"BZy%ogINc,r %WSsJ} ]Vpo[|BxIzc_MP+k Nk+T@z D GG?TylC >iJ@+ $LPdfm}:4n h.v= +Z.D UXu^\1X$zGj*%+Le'ErW2264G=/3}Mp XTB"Jq9).Su?sx6W]ot >{B. \!jwQ2N X yE nGm-{FLd;c{7q?.h2G7Y^)]79M3s[ )M^4]" y֙RTg9_$7B/gZ ;0 fr"0?#*]]P:JN?ar~~.Z'aXQO1?)) }JacG6u>jLHq itB_Rp`C &l+ H"SQ{dJ>0YNE_IVRm~wDyxT8AQ|xDF.4noApG$tiW(6G=h.Yoeb#sUCD6dWM| ST8M~8Rt{`\`/;>q#e^R imX.??woe| [[G>js-q8wiO./ ?aC;9dZM,A_mjtN9 ]:q^rRyO8Lf[sf*}XBy/ow).Jk`$ H(@El ?1h)-1=z/cjsYr'^[% 6V]);<7fKV3sA.ibv@W F'~a7"JBj+4j,stuK%a&8ba#AV-zHmZin*.mha?1i_(0"3, Y!2Vt=DBf)W=:=!^8K<1K>F?hw_#`@pRH!LYB~PWO@@7 ZG|Irr32@L"M[+OAEZP0ǻ$ yF\7/[@BULl kWHh/_ TFG&FA4VV f-k./QJ!r2v!M zpk+(k EL?owbEW^F)HF !;B>byaEZ!X_Yc L 2^R|% *[=ox&7,+M` JjCDPsR8w<4c a+Tj d$cF76&{vups)Bc~!Tf3~%06Z m&{RJU,T'IT+Cn +i%-y-wz 93nC.RIG?P| IȒ,\4UHH%xE6X- SJ'N_Y>EA9HX7{QP-(mpCqTS]Nw/ NS,wv5%bhm+:x_ !dxG tFh:4pk]k*#"c~|.V3<`r^E>6ej.1p#NC@K-`UeSCPSCdCNwέ5q7.DSuy9@q"I?I)6:FL,]/sRB=qcGsr2pZ^%$ M^"71LQ l~Lmr%}tEdWaDDqDj)J4\G (A]0^`\% yV&H5o$`[A ffrV@&>lsnC$_ 14IMRA  )nKY_u&u6h3[ex<(FrA1 L w(T  Zٓ%I._QAij(\.hyj15bS1e q~GW tz@qDZ)%?OG!}kAyxj@sgbVT=pE%WOsg^M*s+5 zx5c`/O. XYw>Jm*r24r-q7ZL96I/YNGww Nib;XDL{bWs&bcpkAI}0'N~Q{:I[F5tTHOy[1M(ud1'R] E(kIOD'Vp~rC5mM_C+ "k9ZLGGbv-2_+>'y}Ty.4; +SA:n;N GxN'__r<*AZ//_`@%a_$RYZNO,1F,Vqtqoo H}B"0`i'U >1[EGW Q,| R YLGSFPfwgdHMKv<ܖCNaDj8VnNAY kcH$'N:n&$\| TR_~kji/mWdqNF! L;$ Y H7M'E^/pqj2|DxX6"K0T;E0z).WJs{y6@BWQB"G( [50zIlNiq>yX2%m8]Pe0WJeF2BeV7|tU4Nt-NV-aHlJ]!?U#fqgb{D%[@!$f:|*x*g`E"78p8Dvg#!> }'W=G  Vd@B)n"*:-NC!UC^=s~:p6D Z\ofK:C#;DVB61pk>-,|@R-&KIpi}+#4ebF@I%fTP]\b" \II7CwOyvbg1%ekQChWzNP7z;5"z&q M:^Y !$U^l6E0juu~u9)ODY vA[8@a{rTd*`<?$]^BW{8|d |rI D`xlg"JS&"@GmtE*L[ FTR:tE}uX2K^ :IuM@(@EknMc"NThKv`(^8khwMaQC sCl?#,QIRyf"t-b?&$ 6z xz4saXXQMYhn"=hn"!n .?htp j9+~4jM(_k!`!j)2et7zZn[y0|7jP]% AL`{EWAupuz(]~$v5 5(dYCQUEFXKnHƪB{:]/*#.P(-Y, WS9^o"{{aI[w2#g<μž%*;V3#7TiQ@|lCB6'u L6Nu6z~Zw H[>=n&xhY-6m 90;~H9 ?KC< &0Z6nOt^ J`>I @~ud4w2SNsV%nF RRdI3I c|Ph36 3,,$Ea~o}6N.[?~=9:%633sy+Dmml{fRN{W 6Ba)ms!f2 08>~7i:c+z 9pt z;2oqXN* Pf3 34 \qOI"< sk"]\N?lo̖_ O- M!:]ZZ2fC)cs`pR JbxF D<:4R"C,N{=E8,/2GX6m3+**q~uJ7!$O046K;=z`6)Fa{`k[yA?2+^aP=#TOf`Vj4n_z4?Bh6)zt/1T5<p_2&%^_\fV.~tn\-{=(9dR:+Wtxn0 4;+hf_)lzW *,EY uM~X9RtNp }@Nm.*9cJ#EHx`aAOk'~e/_6|I2Iue"QKTaUy{XG쇟~trB|6gA}m5:SQB?p;K$(&" =gkyd7Af_+XH.=+;XBgmMpY L2(]}s}==]4NOR]! t?U* ~E&iCagMdHZh*0GcyR :?'H@p!,,<%ُ6zJQt:,ucw k[UnBugy 6hSsﳨkmK]/Q2 , Z5E'Ûkɑiw5'FsOʠ>XWPi>y47wjf:mB\-"d>=s=MM%cmKu> 0g1`=8a:i:vJ\8iO2!,CNqo#yAE[00^2\Fkub [Ju\v7nϿ.+'$UֶmFD%q!ջsf4#|>+跥-5!ƨ#^NfP-?8k]k4'vesc p{'`} b'5Ms"N<-c4.+~Hwhc+}yO S/ I2 $k#_JAP~T׽/qY4"\.&s2+j+y²^lo31.Vf(`Aqjl'HgXGnwqjT>*)*hn'"EgPs{|>jtq>t o'y`i|i`| m 'wC3o)?zeigiYywtI:`28vA sliet*H>pNzo7pTV[g$"]Fqבlr/Z73u\w ,B..'\,\HBEuQVs Ty+) Tyrxi :Rm|{|ePISLPV0("MjYpi68x"zhZ&HPNHv C.^` vo)l^Wz 0P_gqq3E5I<6h1j* _F/=@}~ RI9MSK}76c<iBq:Sgi0bDSgcU6QR+W/#>Hpor[@:UiH4=!L|#kRf{DceYN.,XB{] +:v.SY>tMTB0 'Z=pL<hUc1iZE Jd}??31i2PS3I: 6Mq\58qcorIA\Rw Rw R2S >~w;X '@Wl_yTi!*@Ia cR\kW,^o 4/Q}DWZT4&^h<&gJ #0 ]3P|RAB* CMp$g*yQETTP )e& ^g"e@bgtA BTTT@.Bd!E93e0m_JRi/}~wd2qpg=ޭٖ\rV&4(_p~Ubv^-28[TC.,uc 81(\0t'0.b)M*VM`LHH*.0a ]. R\qGrf35b>L^\SU<}uF.tMi-I\OzlpT*a2!BX U:UWx VHR%3&d-(A[O&x"=+^ ZxgvC_o|piBA]P( _{!6 b X7(2S*EZRK "6a^zVVEW:t)=DW\X>*E{?_b+zuVlq6s9rH{@,o!xf 7x%6'pQ'4v 67Lc$<1(#v`;],yIr99Gr 3@gAZHAYGy hk7_shU |!^QPSqEPxa9JWO E6 4e AH l2~[DGpQZry^"9ba(} LW}x]-8zxqd<L?`G-'W\Q PTKutj'jc u)H>7#?SFc^1/( 3MJD|.D _6bbw.bZzO9.0{=372>"O[SeJr"^u0m,$.bu=O O;/w$uNk={U_gVZF!kb[~1ivpRwOYJ+TbpxE8v0!eLQ3xl+PvLOEb,,afHD4`_uQA|~s?&^fGr .')iKa.od+ pZ.Y3.dLP)R._f.s#>x>({I{L5be^}5%ap!%ZF|M =C5=d)4[jb`>v)0 FJgXVTW,@p bP_ T %Vv n2Q&ePVx2 FPC#$ N$5[]m7mf,EB)ISiG1m8z ^pZq*qW_ d7g/79KZ&o_Y!6A5-A#UADv..N,S*vFodTl)vq8w7pm#68/6^2XJTHk#_WD_[ QW [I>\ D^WS=)hgIo Is@zMTVPM9RL6KJc6QC}05"me5X BBS [ /9Bo^Xl_E (YY*i *8-z'6Q@ N6f1r4.u<Kp)c'H40jq|)+U1?}R0?6p;|Ts$3`+c:j2 +E%xqՓQ >u@XEKl!7#dlO. HBE az#@B]mux=$]?ivqMGV 1]d.~ !b"FX[:*]%W`XK$`]R^~U5`E}nejaR?)f'v +[DaL#q5,vZaE50#CUyHOd_WT^1QbQ)& Win]puy{{S]wJ]AWE}-\{m6mij`I &vaR eDj'ULf`f@T C@9Y3!u @(Qp[x%wo k|.LC {8#|)(g{E\1ln wN @(W`WPN7HK ,`&LQq",`e?3#1n(Z+@JJ_Di&7`{Pa"&-s3'B&$MγqT3VUO6*RexaE5'f_~}A8E7z}ZKkCX(r*a)Vjm2O91POGb*gu{5L]NyeQCx?DGT*UE.hJF v_GFn3)o0 pyW,68b@DG|<`ECOxu/F !Q3C^t_b!c ( BY\O.X$lmC_z1O7 zRhMu'=I-4$Iykӂkx *LNQ2ڗ[ucP8h8R`5(R,d DrwNy[&(u"iu h#N:5{& jdQt\DG!"~ \`+։yD+C!='FyI[SƐK,R.rO x4`o%)2jA E^y:P#STyKf1G zۼKKjot:!wkE.  E };)pwAPLT8 rz`)-{kOpɔnd?}p}W#9 1Cw5C] 0[++,W6ps:^$]]N^'y)n.A3%T^DvU])VNklj^t<8GJ<-g`bTP2S+T@dLiA ;Pyxb #p iWYhe18H Bg\%7`m#"ɩ 0011#6#jDPlhRQZA-'C N1(TP, X '%fq/- lG'%T0k)џ?DE"tN$yp]c}"LL. } ƟWQ"c8+wn8r 5;~C64i I=~j<'8lmVo{2kh:6M\|D0)_X3Qy., Iwf0U,=sVCdbZpԋ@ Cmx>pwqlQ9$m U$ӅO^c?`fMMDIG#S {3!}7/YN1^)CENY7j κ-C\EVe/yqO,KY@ \FTR SrHP zu)pYL GO#AJWqxL_x5$Ga @5,)o0v*yӪ"dFi>f&Afw3ͫ@<"5[iQ(}bt/+<0>JH#lY?k_.v;4ebd1Ul:e;~rK9S{*k0Rhc}sT~m_u9T1QJ jUP0i[y8oH)!DT:jIMj>UCUBv:T\9O"-GKd,yJn!Q]m$Ueg? n+F-+sy>ڣ: G[V!G%bCbW)NW[p 5*@(Ci4l= M%+h4#!3 |f|{"PJ HVJWaQf%.K3QpS)n>2ð+Gp\D]PQjw+u8+Y >kB.W843z bShUAr`y /.k8OH5'Bq 2M9xta޻DZTj$$!m 7?l)kٖ#0 WX^J/cc6FPJxL0=e pc& &_1QXGO>(uj4^0>f?7*}ArF%-XRȽRfgy\[h߉nTy}*Ii1$~tӳ`E6pb'$Yk > 6U3Rj"bTXg]D3WdqhPGd}aHeoNTa"KU*&<>\"Y‹le' vUx LGz[0u!V#ee/FHd"eBJ)aWhapcEqisНOxeZz';+m=r RH J6&U cqz#ߡ(,I~~W 7`./> [ΜQ}cy_aE\tv -(,1 <1O1دO ~M g<-9U+C( XX}D[TT2_ +)oA p_v[ XAV Ggj ZPxbpz5%n(`4 $=2֧XTR5`U!p=X50{tNNV~΋(>V)|BXi:TjE Ui}2L0}GU%AHPxJNzC0B ]vS:^GWUXVbn[0qmv.i![p|opk~xhfcORnS Bp&Tti*ŵQQJv\1SSgNmbEGT!hl-VZ*MXR|!PZcV+W$T, ֨Yڽ" `¨OEZCgK xHUhJCfhP5~p].{(pg8>3MN3=M%DLM z﹨b*=}M!K#Ic2 R"Tb@Z)H۩"7zd9&? p6SQRlX`OsHTsnJypL!T 6ho' %9h;!p*f~QD,{3fxH i g2O$N[1KBC a af}/LcINNvGYL+:3M&&;gEgOG 2+.(*54U)GiN1xBgaa_Q,$ Z8m6%3\Un:o$|f}qP ,(t\"J8bK/KB^] 4)FmN23>*&2gla8Wxo,r`?tBqcIs~qe:K01#kOrrpc^ k.x==r1 Ɂ]DY5Ar27tMP(pgv6>ЏFZS_6?8 osbr5D#`5ebo QhOy] F$ hxe奟w5-'"'vG7K'!6u![!WW܇QQ~3#YG6#y!+_dh>nLu:!f~0f,)nvE~b2> mjO2 8Bij7]WJ+HOWs м;zHamw5 30'jGi_'y. >9rD$|/N[ho%}D-j,H3qd~ =UIOsk>l8kT%R.fILE<- Jr j3i7iK3|^2!`K.KZ܌%67Hn"hg1^Yg Nz0VT^&iX$Vm!$r&/t-H}X=;(hOA?n+;9qa,k`|QhbY{[hSJ %6zOr!`"/EKEy;r&q?;]GXh*L\x1lH3jP4MJLQTgyK0I5;"_LEsf$v`}29uQU[NL Jit3 Sd 7MY)}y2 N-rjt;Mv6m[Hb_L9)FDK`Ak"y+\>%@$0G&pN>pfl8^)87&I&U7~JH@ = .A,s^TAl;R!6V[*0D\i-=B=lGh-?-QXT:8]gtq?%== {_"[PS!H2+O\XvJX;(XBOE.0iE I$<6rYSYFdO bX=j-8(F3!?\]okWZ 7^Qc_"C>5ي'po~BNԱIQ[O ]4;Ct|SR;@F;IAXe |+H BOZ$_ctTEQ>sl:D[WR!G5@3i\DJ~{SE`-:0SR"*b{/Hov ue[YK1SZt? F]9/{b9l" ]VSS"p,q"j=_FJJN 3 {riD l $h?O{ )rIoUs< uh/Txw?d @xPHUL)eJ_}<.68Y2wP]>/0@O}a @ {?3!%QklSY9 ^}$Q9X&ztz{ o&6 +k'Bh2\4a;uv d?wB;3DIGxHQ]T j Yi[omM8acD6w_^]lQ}a*yk}sn&&` ~hbD~Y|ihO+?jAHB ~ H[\"gWf0s7=rbi2AYfz?EvJtS!l?V;]vwEVADLhDhy@A{"r\?SFxS\`t,> ^ 'I:eL$- |1 5['D.w@zgGTM@_o4 5^o$F$s,\&y<6NVvYl~/BA@S/=X.%9VvG:H+ӾdcX6sTҽt@'0J[Ɓ4"V_UN}Ug[(O]<N Ef*h>:KZO+--/e{ RQJ4sf+[- P~PC}VfZP z3SPCd`  -Uq@ Bb+^^~q/a.NP0TfL,d;SHpWeO7m<gQq8WC jIqDVgD H _AT6[tFZ CrQ` _Y†lEy!46z}gB%L:Y z@QWn+P}+^.oP[ Heu COY?X ]Ixk|u^AA|$vrK\@CQw31#4G^J%&!h?qb}O w%LQHrFOCS~:,#Vo}%8PPK'٭@GPrA[@;TPOHMHt`<C-/Ji{+#],RHHZWx<3 ۿW| pB9JOg"E VyF bWN^Mz \R!IGb+c@,*^0EYHG- RKT]P[NxUzluYf}% Z&Z\dPfWy9GݓoJḨ@~IWHcOZU& BQ!RLQF'<1#,)G6 >P7[_2 ^  FY?e6DVU1b@^B[\^:lIR6 8^  ^RO-RKt9EYVAM`GDflk_2KpBDN3)iG#D?U R@jkL\FT}fauM4>dj(/,ck(Бw/r)vaj355h~iSVAI5 {qψ:z F4-o > :K7Yir?h%iw7fl햤`}#qo2x.U}2|w ?&\Hke*=5IT3Y,nv8- TMGQ'|u k:eʲ*ee([dTO3aPyeR|XP32nU8hKS#]?c70a`NQ-dBF.T GC=g<9*\>?F-ll`` }#}/2&fkX}yu g<DBH+^2[Jry#l =}Z\]=5&Ri,u./,g.zGaR[3F' ycyL+Io/?5lg> *<`KH7_oI&vxY -8b~i|)$0~4oZ$ .h}['[4kWg5jd=_nF[#ICT>)RK@+')sFXh 2}ZUL^HzZhNsJ\?V{N, ?gl AnN!z6J+Uq 'wg#\^ULJ2OL8 T~(69P_:j=VkL_;S}faLPjCb'W; 7&6b|W+#vpFbAa ~nIVIi~<j0XgMR8t>6 ?qqx3ln :<*$`id,ehi * 66$9QRfB^R_H%J$waUb&Q:?2f+F_MI' leonGndY:- h K\PDr/ySXS0LASr}e]DRE': -&.]}nGWTYDjnGb1O4LqkXbhSZ?hl B(xwc{f 8'05BW<GC;ZD B]dB Hh/ }gInGH/ dPvj-ZV{,HATeB a)KSmaZLt7vsnoF[@*0']m3TITa;E2I Ay*~+. Ik'kR E. ,dU/?: J-@{I!NddS$gA8?wq]\[RR/6K#XCf[U5vF3b.HB%`zQ2bBP-v%dUSt?z  _Y?zg/j2`'by;qWMI'\/WrI_)$3!@P=XY&a_LSMKZnmb#%}yet6+!jit:G"w%P'_RHS2x"ky$c%#(!~=0>om5R$9*UA9y"2`~hLUED&W;_y KAM NY(Ljk00i $+8-He0DB]EPR:{M)k)V{c-g.}TC^7c]{L' Y,q07[Q?SWiB`LWUqYU" KYC^#-ELZg85O[\O L# uE@),,5V24\*_}Mrm8g&WRYH@b/F&gXG [*hSvEwy)qX1"iNs2f ,v"y'WAx;a^2(\;|l Tw5(h!`Oo=Erh;>gUFdB$'y`ZUJp( Wj'>zbfwGX\XmrdNFzh#@]?#* mXkj:,I@Doa9%3K-pZ4G yB|q':s x-c?qvG4ONzCU" EX@gUei}o)w0,&e =5 c -;t_h2pkr.Yn[Aj9jF62}:JytWlODV{2O]%@%}2WZ5W{z!1ii6}U1(3û%La8q-b>3tS'vגd&Ji?woVlz?ps.AV<һՐQ#RQr@,ֈw<="8lu+%s,1k*h0<0kl4\H]7EZfmU I RS e`gb(`}ENJf\REWCSUH3dn` ;T [V$)jh7%s