Original virgin sources for version 1.2 of mkisofs, by Eric Youngdale of

Yggdrasil Computing Inc.  This is a useful concession to us CDROM mastering
weenies out here.
Obtained from: Yggdrasil Computing, Inc.
This commit is contained in:
Jordan K. Hubbard 1995-02-12 08:00:42 +00:00
parent 4519b73393
commit 6f50ceba0f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/mkisofs/; revision=6318
27 changed files with 6339 additions and 0 deletions

345
gnu/usr.bin/mkisofs/COPYING Normal file
View File

@ -0,0 +1,345 @@
The GPL below is copyrighted by the Free Software
Foundation, but the instance of code that it refers to (the mkisofs
utility is copyrighted by Yggdrasil Computing, Incorporated).
----------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -0,0 +1,660 @@
Wed Jan 11 13:46:50 1995 Eric Youngdale (eric@localhost)
* mkisofs.c: Modify extension record to conform to IEEE P1282
specifications. This is commented out right now, but a trivial
change to a #define enables this. I need to see the specs
to see whether anything else changed before this becomes final.
* write.c (FDECL4): Fix so that we properly determine error
conditions.
* mkisofs.h: Change rr_attributes to unsigned.
* tree.c(increment_nlink): Change pnt since rr_attributes is now
unsigned.
Ultrix patches from petav@argon.e20.physik.tu-muenchen.de (Peter Averkamp)
* rock.c: Fix for ultrix systems, we have 64 bit device numbers.
Type cast when generating file size. Change rr_attributes to
unsigned.
* mkisofs.c: For ultrix systems, define our own function
for strdup.
* mkisofs.c: Fix usage() since some compilers do not concatenate
strings properly (i.e. ultrix).
Bugs found with Sentinel II:
* write.c: Fix a couple of memory leaks.
* mkisofs.c: Bugfix - always put a zero byte at end of name
for ".." entry.
* tree.c: Set isorec.date from fstatbuf.st_ctime, not current_time,
since current_time might not be set.
Sat Dec 3 14:55:42 1994 Eric Youngdale (eric@andante)
* mkisofs.c: When returning entry for ".." file, set second byte
to 0.
* write.c: Free name and rr_attributes fields when writing.
Mon Nov 28 13:36:27 1994 Eric Youngdale (eric@andante)
* mkisofs.h: Change rr_attributes to unsigned.
* rock.c: Ditto. Work around >>32 bug in ultrix for 64 bit data types.
* mkisofs.c (usage): Fix for ultrix - use continuation lines
instead of assuming that strings are catenated by the compiler.
Mon Jun 20 20:25:26 1994 Eric Youngdale (eric@esp22)
* mkisofs.c, mkisofs.8, Makefile (version_string): Bump to pre-1.02.
* mkisofs.h: Fix declaration of e_malloc to use DECL macros.
* tree.c: Fix bug in previous change.
* diag/*.c: Add appropriate copyright notices.
Sat Apr 9 13:30:46 1994 Eric Youngdale (ericy@cais.com)
* Configure: New file - shell script that determines a bunch of
things to properly build mkisofs.
* Makefile.in: New file - copy of Makefile, but Configure sets a
few things up for it.
* tree.c: Do not depend upon opendir to return NULL if we cannot
open a directory - actually try and read the first entry. The
foibles of NFS seem to require this.
* write.c: Fix definition of xfwrite (Use FDECL4)
Add some changes to allow more configurability of some of the
volume header fields:
* mkisofs.8: Document new configuration options.
* mkisofs.c: Add variables to hold new fields. Add function to
read .mkisofsrc files.
* defaults.h: Another way of configuring the same things.
Add some changes from Leo Weppelman leo@ahwau.ahold.nl.
* mkisofs.c: Allow -A to specify application ID. Fix usage(),
getopt and add case switch.
* rock.c: Fix handling of device numbers (dev_t high should only
be used when sizeof(dev_t) > 32 bits).
Add a bunch of changes from Manuel Bouyer.
* diag/Makefile: New file.
* diag/dump.c, diag/isodump.c: Use termios if system supports it.
* (throughout): Replace all occurences of "malloc" with e_malloc.
* mkisofs.c: For NetBSD, attempt to increase the rlimit for
the size of the data segment to about 33 Mb.
* mkisofs.c (e_malloc): New function. Calls malloc, and prints
nice error message and exits if NULL is returned.
Sun Jan 23 19:23:57 1994 Eric Youngdale (eric@esp22)
* mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.01.
Add a bunch of stuff so that mkisofs will work on a VMS system.
* (ALL): Change any direct use of the "st_ino" field from
the statbuf to use a macro.
* mkisofs.h: Define appropriate macros for both VMS and unix.
* (ALL): Add type casts whenever we use the UNCACHED_DEV macro.
* rock.c: Wrap a #ifndef VMS around block and character device
stuff.
* write.c: Add prototype for strdup if VMS is defined.
* make.com: Script for building mkisofs on a VMS system.
* Makefile: Include make.com in the distribution.
* mkisofs.c: Include <sys/type.h> on VMS systems.
* tree.c: Include <sys/file.h> and "vms.h" on VMS systems.
* mkisofs.h (PATH_SEPARATOR, SPATH_SEPARATOR): New macros
that define the ascii character that separates the last directory
component from the filename.
* tree.c, mkisofs.c: Use them.
* vms.c: New file. Contains version of getopt, strdup, opendir,
readdir and closedir.
* vms.h: New file. Defines S_IS* macros. Define gmtime as
localtime, since gmtime under VMS returns NULL.
Sat Jan 15 13:57:42 1994 Eric Youngdale (eric@esp22)
* mkisofs.h (transparent_compression): New prototype.
* mkisofs.c (transparent_compression): Declare, use
'-z' option to turn on.
* tree.c: Change TRANS.TBL;1 to TRANS.TBL (version gets
added later, if required).
* rock.c: If transparent compression requested, verify
file is really suitable (check magic numbers), and extract
correct file length to store in SUSP record.
Sat Jan 15 01:57:42 1994 Eric Youngdale (eric@esp22)
* write.c (compare_dirs): Bugfix for patch from Jan 6.
* mkisofs.h (struct directory_entry): Add element total_rr_attr_size.
(struct file_hash): Add element ce_bytes.
* write.c (iso_write): Update last_extent_written, as required,
and check it against last_extent as a sanity check.
(generate_one_directory): If ce_bytes is non-zero, allocate
a buffer and fill it with the CE records. Also, update
the extent and offset entries in the CE SUSP field and
output after directory is written.
(assign_directory_addresses): Allow for CE sectors after each
directory.
* tree.c (sort_n_finish): Set field ce_bytes by summing
the sizes of all CE blocks in each files RR attributes.
Do not count these bytes for main directory.
* rock.c (generate_rock_ridge_attributes): Generate
CE entries to break up large records into manageable sizes.
Allow long names to be split, and allow long symlinks to be split.
Allow splitting before each SUSP field as well, to make
sure we do not screw outselves.
Thu Jan 6 21:47:43 1994 Eric Youngdale (eric@esp22)
Bugfix.
* write.c (compare_dirs): Only compare directory names up to
the ';' for the version number.
Add four new options: (1) Full 31 character filenames,
(2) Omit version number, (3) Omit trailing period from filenames,
(4) Skip deep directory relocation.
* iso9660.h: Allow 34 characters for filename.
* mkisofs.8: Update for new options.
* mkisofs.c: Add flag variables for new options.
Mention new options in usage(), tell getopt about
new options, and set appropriate flags when
new options are specified.
* mkisofs.c (iso9660_file_length): Implement new options.
* mkisofs.h: Declare flag variables for new options.
* tree.c (sort_n_finish): Increase declaration of newname and
rootname to 34 characters. If full_iso9660_filenames in effect,
use different rules for making unique names.
* tree.c (scan_directory_tree): Use RR_relocation_depth instead of
constant for threshold for starting deep directory relocation.
Wed Jan 5 01:32:34 1994 John Brezak (brezak@ch.hp.com)
* Makefile.bsd: New file. For NetBSD.
* rock.c, tree.c: Do not include sys/sysmacros.h for NetBSD.
Fri Dec 31 13:22:52 1993 Eric Youngdale (eric@esp22)
* mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.00.
* tree.c (scan_directory_tree): Handle case where we do not
have permissions to open a directory.
* write.c (xfwrite): New function - wrapper for fwrite,
except that we print message and punt if write fails.
* write.c: Move include of mkisofs.h and iso9660.h until after
string.h and stdlib.h is included.
* write.c: Do not attempt to use strerror on sun systems.
Thu Dec 9 13:17:28 1993 R.-D. Marzusch (marzusch@odiehh.hanse.de)
* exclude.c, exclude.h: New files. Contains list of files to
exclude from consideration.
* Makefile: Compile exclude.c, add dependencies to other files.
* mkisofs.8: Describe -x option.
* mkisofs.c: Include exclude.h, handle -x option.
Fri Dec 10 01:07:43 1993 Peter van der Veen (peterv@qnx.com)
* mkisofs.c, mkisofs.h: Moved declaration of root_record.
* mkisofs.h: Added prototype for get_733().
* write.c(iso_write), tree.c, rock.c(generate_rock_ridge_attributes):
Added defines for QNX operation system
* rock.c(generate_rock_ridge_attributes): symbolic links should
not have CONTINUE component flag set unless there are multiple
component records, and mkisofs does not generate these.
st_ctime was stored as the creation time, changed to attribute time.
QNX has a creation time, so that is stored as well under QNX.
Thu Oct 28 19:54:38 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.99.
* write.c(iso_write): Put hour, minute, second into date fields in
volume descriptor.
* write.c (iso_write): Set file_structure_version to 1, instead of
' ' (Seems to screw up Macs).
Sun Oct 17 01:13:36 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.98.
Increment nlink in root directory when rr_moved directory is present.
* tree.c (increment_nlink): New function.
* tree.c (finish_cl_pl_entries): Call increment_nlink for all
references to the root directory.
* tree.c (root_statbuf): New variable.
* tree.c (scan_directory_tree): Initialize root_statbuf when we
stat the root directory.
* tree.c (generate_reloc_directory): Use root_statbuf when
generating the Rock Ridge stuff for the ".." entry in the
reloc_dir.
* tree.c (scan_directory_tree): Use root_statbuf when generating
the ".." entry in the root directory.
Sat Oct 16 10:28:30 1993 Eric Youngdale (eric@kafka)
Fix path tables so that they are sorted.
* tree.c (assign_directory_addresses): Move to write.c
* write.c (generate_path_tables): Create an array of pointers to
the individual directories, and sort it based upon the name and
the parent path table index. Then update all of the indexes and
repeat the sort until the path table indexes no longer need to be
changed, and then write the path table.
Fix problem where hard links were throwing off the total extent count.
* write.c (iso_write): Call assign_file_addresses, and then
use last_extent to determine how big the volume is.
* write.c (generate_one_directory): Decrement n_data_extents
for hard links to non-directories so that the expected number
of extents is written correctly.
* write.c(assign_file_addresses): New function.
Fri Oct 15 22:35:43 1993 Eric Youngdale (eric@kafka)
The standard says we should do these things:
* tree.c (generate_reloc_directory): Add RR attributes to
the rr_moved directory.
* mkisofs.c(main): Change ER text strings back to recommended
values.
Tue Oct 12 21:07:38 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.97.
* tree.c (scan_directory_tree): Do not insert PL entry into
root directory record (i.e. !parent)
* tree.c (finish_cl_pl_entries): Do not rely upon name
comparison to locate parent - use d_entry->self instead,
which is guaranteed to be correct.
* mkisofs.h: New variable n_data_extents.
* tree.c: Declare and initialize n_data_extents to 0.
(scan_directory_tree) for non-directories, add
ROUND_UP(statbuf.st_size) to n_data_extents.
(sort_n_finish): Increment n_data_extents for translation tables,
as appropriate.
* write.c(iso_write): Add n_data_extents to the
volume_space_size field.
* hash.c(add_hash): If size != 0 and extent == 0, or
if size == 0 and extent != 0, then complain about
inserting this into the hash table. Kind of a sanity check.
Sat Oct 9 16:39:15 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.96.
Numerous bugfixes, thanks to a one-off disc from rab@cdrom.com.
* write.c(generate_one_directory): Wait until after we have
filled in the starting_extent field to s_entry before calling
add_hash. This fixes a problem where the hash table gets an
extent of 0 for all regular files, and this turns up when you have
hard links on the disc. (The hash table allows us to have each
hard link point to the same extent on the cdrom, thereby saving
some space).
* tree.c(scan_directory_tree): Set statbuf.st_dev and
statbuf.st_ino to the UNCACHED numbers for symlinks that we
are not following. This prevents the function find_hash from
returning an inode that cooresponds to the file the symlink points
to, which in turn prevents generate_one_directory from filling in
a bogus file length (should be zero for symlinks).
* tree.c(scan_directory_tree): Always call lstat for the file
so that non-RockRidge discs get correct treatment of symlinks.
Improve error message when we ignore a symlink on a non-RR disc.
* write.c(generate_one_directory): Set fields for starting_extent
and size in the "." and ".." entries before we add them to the
file hash. Fixes problems with incorrect backlinks for second
level directories.
Wed Oct 6 19:53:40 1993 Eric Youngdale (eric@kafka)
* write.c (write_one_file): Print message and punt if we are
unable to open the file.
* tree.c(scan_directory_tree): For regular files, use the access
function to verify that the file is readable in the first place.
If not, issue a warning and skip it. For directories, it probably
does not matter, since we would not be able to descend into them
in the first place.
Wed Sep 29 00:02:47 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.95.
* write.c, tree.c: Cosmetic changes to printed information.
* tree.c(scan_directory_tree): Set size to zero for
special stub entries that correspond to the
relocated directories. Hopefully last big bug.
* mkisofs.h: Change TABLE_INODE, UNCACHED_* macros
to be 0x7fff... to be compatible with signed datatypes.
Mon Sep 27 20:14:49 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.94.
* write.c (write_path_tables): Actually search the
directory for the matching entry in case we renamed
the directory because of a name conflict.
* tree.c(scan_directory_tree): Take directory_entry pointer
as second argument so that we can create a backpointer
in the directory structure that points back to the original
dir.
* mkisofs.c: Fix call to scan_directory_tree to use new calling
sequence.
* write.c(generate_one_directory): Punt if the last_extent counter
ever exceeds 700Mb/2048. Print name of responsible file,
extent counter, and starting extent. Perhaps we can catch it in
the act.
Sun Sep 26 20:58:05 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.93.
* tree.c(scan_directory_tree): Handle symlinks better. Either
leave them as symlinks, or erase any trace that they were a
symlink but do not do it 1/2 way as before. Also, watch for
directory loops created with symlinks.
* mkisofs.h: Add new flag follow_links.
* mkisofs.c: Add command line switch "-f" to toggle follow_links.
* mkisofs.8: Document new switch.
* tree.c: Add code to handle symlinks using new flag.
* hash.c: Add add_directory_hash, find_directory_hash functions.
* mkisofs.h: Add prototypes.
Sat Sep 25 14:26:31 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.92.
* mkisofs.c: Make sure path is an actual directory before trying
to scan it.
* mkisofs.h: Add DECL and FDECL? macros for sparc like systems.
Do proper define of optind and optarg under SVr4.
* tree.c: Change translation table name from YMTRANS.TBL to TRANS.TBL.
* mkisofs.c: Neaten up message in extension record when RRIP is
in use.
* Throughout - change all function declarations so that
traditional C compilers (i.e. sparc) will work.
* Makefile: Change to use system default C compiler.
* mkisofs.c: Add some stuff so that this will compile under VMS.
Many things missing for VMS still.
* iso9660.h: Do not use zero length array in struct definition.
* tree.c (sort_n_finish): Account for this.
* Change copyright notice.
Wed Aug 25 08:06:51 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.91.
* mkisofs.h: Only include sys/dir.h for linux. Other systems
will need other things.
* mkisofs.c, tree.c: Include unistd.h.
* Makefile: Use OBJS to define list of object files.
Sun Aug 22 20:55:17 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.9.
* write.c (iso_7*): Fix so that they work properly on Motorola
systems.
Fri Aug 20 00:14:36 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.8.
* rock.c: Do not mask off write permissions from posix file modes.
Wed Aug 18 09:02:12 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.7.
* rock.c: Do not write NM field for . and .. (redundant and a
waste of space).
* mkisofs.c: Take -P and -p options for publisher and preparer id
fields.
* write.c: Store publisher and preparer id in volume
descriptor.
* rock.c: Write optional SP field to identify SUSP. Write
optional CE field to point to the extension header.
* tree.c: Request SP and CE fields be added to root directory.
* tree.c: Fix bug in name conflict resolution.
* write.c: Fill in date fields in the colume descriptor.
* write.c (write_one_file): If the file is large enough, write in
chunks of 16 sectors to improve performance.
* hash.c (add_hash, find_hash, etc): Do not hash s_entry, instead
store relevant info in hash structure (we free s_entry structs as
we write files, and we need to have access to the hash table the
whole way through.
* write.c: Add a few statistics about directory sizes, RR sizes,
translation table sizes, etc.
* tree.c: Use major, not MAJOR. Same for minor. Define S_ISSOCK
and S_ISLNK if not defined.
* rock.c: Define S_ISLNK if not defined.
* mkisofs.c: Print out max memory usage. Fix bug in call to getopt.
* mkisofs.c, Makefile (version_string): Bump to 0.6.
* tree.c: Simplify the calculation of isorec.len, isorec.name_len
and the calculation of the path table sizes by doing it all at
one point after conflict resolution is done.
* tree.c: scan_directory_tree is now responsible for generating
the line that goes into the YMTRANS.TBL file. These lines are
collected later on into something that will be dumped to the
file. Correctly handle all of the special file types.
Mon Aug 16 21:59:47 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.5.
* mkisofs.c: Add -a option (to force all files to be
transferred). Remove find_file_hash stuff.
* write.c: Pad length even if Rock Ridge is not in use.
* hash.c: Rewrite hash_file_* stuff so that it can be used to
easily detect (and look up) filenames that have been accepted
for use in this directory. Used for name collision detection.
* tree.c (sort_n_finish): If two names collide, generate a unique
one (verified with the hash routines). Change the lower priority
name if there is a difference.
Sat Aug 14 13:18:21 1993 Eric Youngdale (eric@kafka)
* mkisofs.c, Makefile (version_string): Bump to 0.4.
* tree.c (load_translation_table): New function - read
YMTRANS.TBL. (scan_directory_tree) Call it.
* mkisofs.c (iso9660_file_length): Call find_file_hash to see
if translated name is specified. If so, use it.
* hash.c (name_hash, add_file_hash, find_file_hash,
flush_file_hash): New functions for hashing stuff from
YMTRANS.TBL.
* mkisofs.h: Add a bunch of prototypes for the new functions.
* mkisofs.8: Update.
* mkisofs.c, Makefile (version_string): Bump to 0.3.
* Makefile: Add version number to tar file in dist target.
* mkisofs.c: Call finish_cl_pl_entries() after directories have
been generated, and extent numbers assigned.
* write.c (generate_one_directory): Update s_entry->size for
directories (as well as isorec.size).
* rock.c: Add code to generate CL, PL, and RE entries. The
extent numbers for the CL and PL entries are NULL, and these
are filled in later once we know where they actually belong.
* mkisofs.h: Add parent_rec to directory_entry. Used to fix CL/PL
stuff.
* tree.c (scan_directory_tree): Set flag to generate CL/PL/RE
entries as required, update sizes as well.
Fri Aug 13 19:49:30 1993 Eric Youngdale (eric@kafka)
* mkisofs.c (version_string): Bump to 0.2.
* hash.c: Do not use entries with inode == 0xffffffff or dev ==
0xffff.
* write.c (write_path_tables): Strip leading directory specifications.
* mkisofs.h: Add definition for reloc_dir symbol. Add prototype
for sort_n_finish, add third parameter to scan_directory_tree
(for true parent, when directories are relocated).
* mkisofs.c (main): Modify call to scan_directory_tree. Call
sort_n_finish for reloc_dir.
* tree.c (sort_n_finish): New function - moved code from
scan_directory_tree.
* tree.c (generate_reloc_directory): New function. Generate
directory to hold relocated directories.
* tree.c (scan_directory_tree): Strip leading directories when
generating this_dir->name. If depth is too great, then move
directory to reloc_dir (creating if it does not exist, and leave
a dummy (non-directory) entry in the regular directory so that
we can eventually add the required Rock Ridge record.
* tree.c (scan_directory_tree): Use s_entry instead of sort_dir,
assign to this_dir->contents sooner.
Thu Aug 12 22:38:17 1993 Eric Youngdale (eric@kafka)
* mkisofs.c (usage): Fix syntax.
* mkisofs.c (main): Add new argument to scan_directory_tree
* tree.c (scan_directory_tree): If directory is at depth 8 or
more, create rr_moved directory in main directory.
Mon Jul 26 19:45:47 1993 Eric Youngdale (eric@kafka)
* mkisofs v 0.1 released.

43
gnu/usr.bin/mkisofs/Configure Executable file
View File

@ -0,0 +1,43 @@
#!/bin/sh
#
# This script attempts to automatically configure for the host system.
#
MKDEV=
MACROS=
MALLOC=
if [ -f /usr/include/sys/mkdev.h ]
then
MKDEV=-DHASMKDEV
fi
if [ -f /usr/include/sys/sysmacros.h ]
then
MACROS=-DHASSYSMACROS
fi
if [ -f /usr/include/malloc.h ]
then
MALLOC=-DHASMALLOC_H
fi
#
# OK, we have all of the configuration stuff done. Now generate the Makefile.
#
echo XCFLAGS=${MKDEV} ${MACROS} ${MALLOC} > Makefrag
sed -e "/XCFLAGS=/ r Makefrag" Makefile.in > Makefile
rm -f Makefrag
#
# Now generate config.h
#
rm -rf config.h
touch config.h
if [ -f /usr/include/termios.h ]
then
echo "#define USE_TERMIOS" >> config.h
fi
echo "The Makefile is now properly configured for your system."

View File

@ -0,0 +1,50 @@
CFLAGS=-g -Wall -c
CC=gcc
#
# XCFLAGS is automatically set by Configure.
#
XCFLAGS=
XCFLAGS= -DHASSYSMACROS -DHASMALLOC_H
CFLAGS=-g -c $(XCFLAGS)
LDFLAGS=
OBJS=mkisofs.o tree.o write.o hash.o rock.o exclude.o
World: mkisofs
Makefile: Makefile.in Configure
./Configure
echo "Type make again to build mkisofs."
mkisofs: Makefile $(OBJS)
$(CC) $(LDFLAGS) -o mkisofs $(OBJS)
install: mkisofs mkisofs.8
strip mkisofs
cp mkisofs /usr/bin/
if [ -d /usr/man/man8 ]; then cp mkisofs.8 /usr/man/man8/; fi
tree.o: tree.c mkisofs.h iso9660.h exclude.h
$(CC) $(CFLAGS) tree.c
write.o: write.c mkisofs.h iso9660.h
$(CC) $(CFLAGS) write.c
hash.o: hash.c mkisofs.h
$(CC) $(CFLAGS) hash.c
rock.o: rock.c mkisofs.h iso9660.h
$(CC) $(CFLAGS) rock.c
exclude.o: exclude.c exclude.h
$(CC) $(CFLAGS) exclude.c
mkisofs.o: mkisofs.c iso9660.h mkisofs.h exclude.h
$(CC) $(CFLAGS) mkisofs.c
clean:
/bin/rm -f *.o core mkisofs *~ #*#
dist:
tar -cvf - README Configure Makefile.in make.com TODO COPYING ChangeLog *.8 *.c *.h diag | gzip > mkisofs-1.02.tar.gz

View File

@ -0,0 +1,49 @@
#CFLAGS=-g -Wall -c
#CC=gcc
#
# XCFLAGS is automatically set by Configure.
#
XCFLAGS=
CFLAGS=-g -c $(XCFLAGS)
LDFLAGS=
OBJS=mkisofs.o tree.o write.o hash.o rock.o exclude.o
World: mkisofs
Makefile: Makefile.in Configure
./Configure
echo "Type make again to build mkisofs."
mkisofs: Makefile $(OBJS)
$(CC) $(LDFLAGS) -o mkisofs $(OBJS)
install: mkisofs mkisofs.8
strip mkisofs
cp mkisofs /usr/bin/
if [ -d /usr/man/man8 ]; then cp mkisofs.8 /usr/man/man8/; fi
tree.o: tree.c mkisofs.h iso9660.h exclude.h
$(CC) $(CFLAGS) tree.c
write.o: write.c mkisofs.h iso9660.h
$(CC) $(CFLAGS) write.c
hash.o: hash.c mkisofs.h
$(CC) $(CFLAGS) hash.c
rock.o: rock.c mkisofs.h iso9660.h
$(CC) $(CFLAGS) rock.c
exclude.o: exclude.c exclude.h
$(CC) $(CFLAGS) exclude.c
mkisofs.o: mkisofs.c iso9660.h mkisofs.h exclude.h
$(CC) $(CFLAGS) mkisofs.c
clean:
/bin/rm -f *.o core mkisofs *~ #*#
dist:
tar -cvf - README Configure Makefile.in make.com TODO COPYING ChangeLog *.8 *.c *.h diag | gzip > mkisofs-1.02.tar.gz

View File

@ -0,0 +1,76 @@
This program requires a lot of virtual memory to run since it
builds all of the directories in memory. The exact requirements
depend upon a lot of things, but for Rock Ridge discs 12Mb would not
be unreasonable. Without RockRidge and without the translation
tables, the requirements would be considerably less.
*****************************
Notes for version 1.2.
Minor bugfixes here and there. Support for compiled in
defaults for many of the text fields in the volume header are now
present, and there is also support for a file ".mkisofsrc" that can
also read settings for these parameters.
A short script "Configure" was added to allow us to set up special
compile options that depend upon the system that we are running on.
This should help stamp out the sphaghetti-isms that were starting to grow
up in various places in the code.
You should get more meaningful error messages if you run out of
memory.
*****************************
Notes for version 1.1.
The big news is that SUSP CE entries are now generated for
extremely long filenames and symlink names. This virtually guarantees
that there is no limit (OK, well, about 600Mb) for file name lengths.
I have tested this as well as I can, and it seems to work with linux.
This would only be used very rarely I suspect.
Also, I believe that support for VMS is done. You must be
careful, because only Stream-LF and FIxed length record files can be
recorded. The rest are rejected with error messages. Perhaps I am
being too severe here.
There is a bugfix in the sorting of entries on the disc - we
need to stop comparing once we reach the ';' character.
There are four new options -z -d -D -l -V. Some of these tell
mkisofs to relax some of the iso9660 restrictions, and many systems
apparently do not really seem to mind. Use these with caution.
Some diagnostic programs to scan disc images are in the diag
directory. These are not as portable as mkisofs, and may have some
bugs. Still they are useful because they can check for bugs that I might
have introduced as I add new features.
*****************************
Notes for version 1.0.
In version 1.0, the date fields in the TF fields were fixed -
previously I was storing st_ctime as the file creation time instead of
the file attribute change time. Thanks to Peter van der Veen for
pointing this out. I have one slight concern with this change,
however. The Young Minds software is definitely supplying 3 dates
(creation, modification and access), and I would strongly suspect that
they are incorrectly putting the file attribute change time in the
file creation slot. I would be curious to see how the different RRIP
filesystems treat this. Anyway, this is something to keep in the back
of your mind.
The symlink handling was not quite correct in 0.99 - this is
now fixed. Only some systems seemed to have been affected by this bug.
A command line option is now present to allow you to
specifically exclude certain files from the distribution.
The case where you do not have permissions to read a directory
is now handled better by mkisofs. The directory that cannot be opened
is converted into a zero-length file, and processing continues normally.
A few portability things have been fixed (hopefully).

15
gnu/usr.bin/mkisofs/TODO Normal file
View File

@ -0,0 +1,15 @@
1) Allow multiple input paths to be concatenated together.
This is a little tricky, because the directory entries need to be
correctly sorted as per iso9660 specifications. It would be better to
force the user to add hard links or copies of the files rather than do
the wrong thing. Leave alone for the time being, I am not sure that
this feature is really needed.
2) For symlinks, we may need to strip out the leading path
information if the link is to an absolute file, and the absolute
address is in the space that we are dumping to the CDROM. Who the
hell knows what we should really do with this, actually. Leave it
for now and see if anyone squalks.
3) Find out if output needs to be written at a particular
blocksize or not.

View File

@ -0,0 +1 @@
#define USE_TERMIOS

View File

@ -0,0 +1,18 @@
/*
* Header file defaults.h - assorted default values for character strings in
* the volume descriptor.
*/
#define PREPARER_DEFAULT NULL
#define PUBLISHER_DEFAULT NULL
#define APPID_DEFAULT NULL
#define COPYRIGHT_DEFAULT NULL
#define BIBLIO_DEFAULT NULL
#define ABSTRACT_DEFAULT NULL
#define VOLSET_ID_DEFAULT NULL
#define VOLUME_ID_DEFAULT "CDROM"
#ifdef __QNX__
#define SYSTEM_ID_DEFAULT "QNX"
#else
#define SYSTEM_ID_DEFAULT "LINUX"
#endif

View File

@ -0,0 +1,10 @@
all: dump isodump isovfy
dump:dump.c
gcc -o dump dump.c
isodump:isodump.c
gcc -o isodump isodump.c
isovfy:isovfy.c
gcc -o isovfy isovfy.c
clean:
rm dump isodump isovfy

View File

@ -0,0 +1,74 @@
I am enclosing 3 test programs that I use to verify the
integrity of an iso9660 disc. The first one (isodump) is pretty
simple - it dumps to the screen the contents of the various
directories. The second one (isovfy) goes through and looks for
problems of one kind or another.
To use, type something like "./isodump /dev/ramdisk" or
"./isodump /dev/scd0", depending upon where the iso9660 disc is. It
starts by displaying the files in the first sector of the root
directory. It has some pretty simple one letter commands that you
can use to traverse the directory tree.
a - move back one sector.
b - move forward one sector.
g - go to new logical sector.
q - quit
The a and b commands do not try and stop you from going past the
beginning or end of a sector, and the g command does not have any way
of knowing whether the sector you request is actually a directory or
not.
The output is displayed in several columns. The first column
is the total length of the directory record for the file. The second
column (in [] brackets) is the volume number. Next comes the starting
extent number (in hex), and then comes the file size in bytes. Then
cones the filename (not the Rock Ridge version), and this is preceeded
by an "*" if the file is a directory. After this is a summary of the
Rock Ridge fields present along with a display of the translation of
the symbolic link name if the SL Rock Ridge record is present.
I tailored this program for debugging some of the problems
that I was having earlier. The idea is that you can tailor it
to test for problems that you might be having, so it is not intended
as a be-all and end-all dump program.
If you move to a sector that does not contain directory
information, the results are unpredictable.
The second program, isovfy, is run in the same way as isodump,
except that you do not have to do much except let it run. I have it
written to verify all kinds of different things, and as people find
other sorts of problems other tests could be added.
The third program, dump.c, basically does a hexdump of the cd.
This is screen oriented, and there are some simple commands:
a - move back one sector.
b - move forward one sector.
f - enter new search string.
+ - search forward for search string.
g - go to new logical sector.
q - quit
Note that with the 'g' command, sectors are always given in
hex, and represent 2048 byte sectors (as on the cdrom). If you know
how to decode a raw iso9660 directory, you can pick out the starting
extent number from the hexdump and know where to go from there. The
starting extent appears something like 30 bytes prior to the start of
the iso9660 (not Rock Ridge) filename, and it appears in a 7.3.3
format (meaning that it occupies 8 bytes, 4 in little endian format,
and 4 in big endian format). Thus you should see a mirror image of
the bytes when looking at the extent number.
The isovfy program can also dump the contents of the path
tables, but this capability is commented out right now. Feel free
to enable this to see what is in the tables. Ultimately I may fix
it so that this checks the integrity of the tables as well.
The isovfy program gives warnings about things like files that
have a size of 0 but have an extent number assigned. The mkisofs program
should never do this, but the YM software does leave these around.
I think it is probably harmless in the YM case.~

View File

@ -0,0 +1,201 @@
/*
* File dump.c - dump a file/device both in hex and in ASCII.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "../config.h"
#include <stdio.h>
#ifdef USE_TERMIOS
#include <termios.h>
#include <sys/ioctl.h>
#else
#include <termio.h>
#endif
#include <signal.h>
FILE * infile;
int file_addr;
unsigned char buffer[256];
unsigned char search[64];
#define PAGE 256
#ifdef USE_TERMIOS
struct termios savetty;
struct termios newtty;
#else
struct termio savetty;
struct termio newtty;
#endif
reset_tty(){
#ifdef USE_TERMIOS
if(tcsetattr(0, TCSANOW, &savetty) == -1)
#else
if(ioctl(0, TCSETAF, &savetty)==-1)
#endif
{
printf("cannot put tty into normal mode\n");
exit(1);
}
}
set_tty(){
#ifdef USE_TERMIOS
if(tcsetattr(0, TCSANOW, &newtty) == -1)
#else
if(ioctl(0, TCSETAF, &newtty)==-1)
#endif
{
printf("cannot put tty into raw mode\n");
exit(1);
}
}
/* Come here when we get a suspend signal from the terminal */
onsusp ()
{
/* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
signal(SIGTTOU, SIG_IGN);
reset_tty ();
fflush (stdout);
signal(SIGTTOU, SIG_DFL);
/* Send the TSTP signal to suspend our process group */
signal(SIGTSTP, SIG_DFL);
/* sigsetmask(0);*/
kill (0, SIGTSTP);
/* Pause for station break */
/* We're back */
signal (SIGTSTP, onsusp);
set_tty ();
}
crsr2(int row, int col){
printf("\033[%d;%dH",row,col);
}
showblock(int flag){
unsigned int k;
int i, j;
lseek(fileno(infile), file_addr, 0);
read(fileno(infile), buffer, sizeof(buffer));
if(flag) {
for(i=0;i<16;i++){
crsr2(i+3,1);
printf("%8.8x ",file_addr+(i<<4));
for(j=15;j>=0;j--){
printf("%2.2x",buffer[(i<<4)+j]);
if(!(j & 0x3)) printf(" ");
};
for(j=0;j< 16;j++){
k = buffer[(i << 4) + j];
if(k >= ' ' && k < 0x80) printf("%c",k);
else printf(".");
};
}
};
crsr2(20,1);
printf(" Zone, zone offset: %6x %4.4x ",file_addr>>11, file_addr & 0x7ff);
fflush(stdout);
}
getbyte()
{
char c1;
c1 = buffer[file_addr & (PAGE-1)];
file_addr++;
if ((file_addr & (PAGE-1)) == 0) showblock(0);
return c1;
}
main(int argc, char * argv[]){
char c;
int nbyte;
int i,j;
if(argc < 2) return 0;
infile = fopen(argv[1],"rb");
for(i=0;i<30;i++) printf("\n");
file_addr = 0;
/* Now setup the keyboard for single character input. */
#ifdef USE_TERMIOS
if(tcgetattr(0, &savetty) == -1)
#else
if(ioctl(0, TCGETA, &savetty) == -1)
#endif
{
printf("stdin must be a tty\n");
exit(1);
}
newtty=savetty;
newtty.c_lflag&=~ICANON;
newtty.c_lflag&=~ECHO;
newtty.c_cc[VMIN]=1;
set_tty();
signal(SIGTSTP, onsusp);
do{
if(file_addr < 0) file_addr = 0;
showblock(1);
read (0, &c, 1);
if (c == 'a') file_addr -= PAGE;
if (c == 'b') file_addr += PAGE;
if (c == 'g') {
crsr2(20,1);
printf("Enter new starting block (in hex):");
scanf("%x",&file_addr);
file_addr = file_addr << 11;
crsr2(20,1);
printf(" ");
};
if (c == 'f') {
crsr2(20,1);
printf("Enter new search string:");
fgets(search,sizeof(search),stdin);
while(search[strlen(search)-1] == '\n') search[strlen(search)-1] = 0;
crsr2(20,1);
printf(" ");
};
if (c == '+') {
while(1==1){
while(1==1){
c = getbyte(&file_addr);
if (c == search[0]) break;
};
for (j=1;j<strlen(search);j++)
if(search[j] != getbyte()) break;
if(j==strlen(search)) break;
};
file_addr &= ~(PAGE-1);
showblock(1);
};
if (c == 'q') break;
} while(1==1);
reset_tty();
fclose(infile);
}

View File

@ -0,0 +1,434 @@
/*
* File isodump.c - dump iso9660 directory information.
*
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "../config.h"
#include <stdio.h>
#ifdef USE_TERMIOS
#include <termios.h>
#include <sys/ioctl.h>
#else
#include <termio.h>
#endif
#include <signal.h>
FILE * infile;
int file_addr;
unsigned char buffer[2048];
unsigned char search[64];
#define PAGE sizeof(buffer)
#define ISODCL(from, to) (to - from + 1)
int
isonum_731 (char * p)
{
return ((p[0] & 0xff)
| ((p[1] & 0xff) << 8)
| ((p[2] & 0xff) << 16)
| ((p[3] & 0xff) << 24));
}
int
isonum_733 (char * p)
{
return (isonum_731 (p));
}
struct iso_primary_descriptor {
unsigned char type [ISODCL ( 1, 1)]; /* 711 */
unsigned char id [ISODCL ( 2, 6)];
unsigned char version [ISODCL ( 7, 7)]; /* 711 */
unsigned char unused1 [ISODCL ( 8, 8)];
unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */
unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */
unsigned char unused2 [ISODCL ( 73, 80)];
unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
unsigned char unused3 [ISODCL ( 89, 120)];
unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */
unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */
unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */
unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */
unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */
unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */
unsigned char publisher_id [ISODCL (319, 446)]; /* achars */
unsigned char preparer_id [ISODCL (447, 574)]; /* achars */
unsigned char application_id [ISODCL (575, 702)]; /* achars */
unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */
unsigned char unused4 [ISODCL (883, 883)];
unsigned char application_data [ISODCL (884, 1395)];
unsigned char unused5 [ISODCL (1396, 2048)];
};
struct iso_directory_record {
unsigned char length [ISODCL (1, 1)]; /* 711 */
unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */
unsigned char extent [ISODCL (3, 10)]; /* 733 */
unsigned char size [ISODCL (11, 18)]; /* 733 */
unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */
unsigned char flags [ISODCL (26, 26)];
unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */
unsigned char interleave [ISODCL (28, 28)]; /* 711 */
unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
unsigned char name_len [ISODCL (33, 33)]; /* 711 */
unsigned char name [0];
};
#ifdef USE_TERMIOS
struct termios savetty;
struct termios newtty;
#else
struct termio savetty;
struct termio newtty;
#endif
reset_tty(){
#ifdef USE_TERMIOS
if(tcsetattr(0, TCSANOW, &savetty) == -1)
#else
if(ioctl(0, TCSETAF, &savetty)==-1)
#endif
{
printf("cannot put tty into normal mode\n");
exit(1);
}
}
set_tty(){
#ifdef USE_TERMIOS
if(tcsetattr(0, TCSANOW, &newtty) == -1)
#else
if(ioctl(0, TCSETAF, &newtty)==-1)
#endif
{
printf("cannot put tty into raw mode\n");
exit(1);
}
}
/* Come here when we get a suspend signal from the terminal */
onsusp ()
{
/* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
signal(SIGTTOU, SIG_IGN);
reset_tty ();
fflush (stdout);
signal(SIGTTOU, SIG_DFL);
/* Send the TSTP signal to suspend our process group */
signal(SIGTSTP, SIG_DFL);
/* sigsetmask(0);*/
kill (0, SIGTSTP);
/* Pause for station break */
/* We're back */
signal (SIGTSTP, onsusp);
set_tty ();
}
crsr2(int row, int col){
printf("\033[%d;%dH",row,col);
}
int parse_rr(unsigned char * pnt, int len, int cont_flag)
{
int slen;
int ncount;
int extent;
int cont_extent, cont_offset, cont_size;
int flag1, flag2;
unsigned char *pnts;
char symlink[1024];
int goof;
/* printf(" RRlen=%d ", len); */
symlink[0] = 0;
cont_extent = cont_offset = cont_size = 0;
ncount = 0;
flag1 = flag2 = 0;
while(len >= 4){
if(ncount) printf(",");
else printf("[");
printf("%c%c", pnt[0], pnt[1]);
if(pnt[3] != 1) {
printf("**BAD RRVERSION");
return;
};
ncount++;
if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1;
if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2;
if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4;
if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8;
if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16;
if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32;
if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64;
if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128;
if(strncmp(pnt, "PX", 2) == 0) {
extent = isonum_733(pnt+12);
printf("=%x", extent);
};
if(strncmp(pnt, "CE", 2) == 0) {
cont_extent = isonum_733(pnt+4);
cont_offset = isonum_733(pnt+12);
cont_size = isonum_733(pnt+20);
printf("=[%x,%x,%d]", cont_extent, cont_offset,
cont_size);
};
if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) {
extent = isonum_733(pnt+4);
printf("=%x", extent);
};
if(strncmp(pnt, "SL", 2) == 0) {
int cflag;
cflag = pnt[4];
pnts = pnt+5;
slen = pnt[2] - 5;
while(slen >= 1){
switch(pnts[0] & 0xfe){
case 0:
strncat(symlink, pnts+2, pnts[1]);
break;
case 2:
strcat (symlink, ".");
break;
case 4:
strcat (symlink, "..");
break;
case 8:
if((pnts[0] & 1) == 0)strcat (symlink, "/");
break;
case 16:
strcat(symlink,"/mnt");
printf("Warning - mount point requested");
break;
case 32:
strcat(symlink,"kafka");
printf("Warning - host_name requested");
break;
default:
printf("Reserved bit setting in symlink", goof++);
break;
};
if((pnts[0] & 0xfe) && pnts[1] != 0) {
printf("Incorrect length in symlink component");
};
if((pnts[0] & 1) == 0) strcat(symlink,"/");
slen -= (pnts[1] + 2);
pnts += (pnts[1] + 2);
};
if(cflag) printf("+");
printf("=%s", symlink);
symlink[0] = 0;
};
len -= pnt[2];
pnt += pnt[2];
if(len <= 3 && cont_extent) {
unsigned char sector[2048];
lseek(fileno(infile), cont_extent << 11, 0);
read(fileno(infile), sector, sizeof(sector));
flag2 |= parse_rr(&sector[cont_offset], cont_size, 1);
};
};
if(ncount) printf("]");
if (!cont_flag && flag1 != flag2)
printf("Flag %x != %x", flag1, flag2, goof++);
return flag2;
}
int
dump_rr(struct iso_directory_record * idr)
{
int len;
char * pnt;
len = idr->length[0] & 0xff;
len -= sizeof(struct iso_directory_record);
len -= idr->name_len[0];
pnt = (char *) idr;
pnt += sizeof(struct iso_directory_record);
pnt += idr->name_len[0];
if((idr->name_len[0] & 1) == 0){
pnt++;
len--;
};
parse_rr(pnt, len, 0);
}
showblock(int flag){
unsigned int k;
int i, j;
int line;
struct iso_directory_record * idr;
lseek(fileno(infile), file_addr, 0);
read(fileno(infile), buffer, sizeof(buffer));
for(i=0;i<60;i++) printf("\n");
fflush(stdout);
i = line = 0;
if(flag) {
while(1==1){
crsr2(line+3,1);
idr = (struct iso_directory_record *) &buffer[i];
if(idr->length[0] == 0) break;
printf("%3d ", idr->length[0]);
printf("[%2d] ", idr->volume_sequence_number[0]);
printf("%5x ", *((unsigned int *) idr->extent));
printf("%8d ", *((unsigned int *) idr->size));
printf ((idr->flags[0] & 2) ? "*" : " ");
if(idr->name_len[0] == 1 && idr->name[0] == 0)
printf(". ");
else if(idr->name_len[0] == 1 && idr->name[0] == 1)
printf(".. ");
else {
for(j=0; j<idr->name_len[0]; j++) printf("%c", idr->name[j]);
for(j=0; j<14 -idr->name_len[0]; j++) printf(" ");
};
dump_rr(idr);
printf("\n");
i += buffer[i];
if (i > 2048 - sizeof(struct iso_directory_record)) break;
line++;
};
};
printf("\n");
printf(" Zone, zone offset: %6x %4.4x ",file_addr>>11, file_addr & 0x7ff);
fflush(stdout);
}
getbyte()
{
char c1;
c1 = buffer[file_addr & (PAGE-1)];
file_addr++;
if ((file_addr & (PAGE-1)) == 0) showblock(0);
return c1;
}
main(int argc, char * argv[]){
char c;
char buffer[2048];
int nbyte;
int i,j;
struct iso_primary_descriptor ipd;
struct iso_directory_record * idr;
if(argc < 2) return 0;
infile = fopen(argv[1],"rb");
file_addr = 16 << 11;
lseek(fileno(infile), file_addr, 0);
read(fileno(infile), &ipd, sizeof(ipd));
idr = (struct iso_directory_record *) &ipd.root_directory_record;
file_addr = isonum_733(idr->extent);
file_addr = file_addr << 11;
/* Now setup the keyboard for single character input. */
#ifdef USE_TERMIOS
if(tcgetattr(0, &savetty) == -1)
#else
if(ioctl(0, TCGETA, &savetty) == -1)
#endif
{
printf("stdin must be a tty\n");
exit(1);
}
newtty=savetty;
newtty.c_lflag&=~ICANON;
newtty.c_lflag&=~ECHO;
newtty.c_cc[VMIN]=1;
set_tty();
signal(SIGTSTP, onsusp);
do{
if(file_addr < 0) file_addr = 0;
showblock(1);
read (0, &c, 1);
if (c == 'a') file_addr -= PAGE;
if (c == 'b') file_addr += PAGE;
if (c == 'g') {
crsr2(20,1);
printf("Enter new starting block (in hex):");
scanf("%x",&file_addr);
file_addr = file_addr << 11;
crsr2(20,1);
printf(" ");
};
if (c == 'f') {
crsr2(20,1);
printf("Enter new search string:");
fgets(search,sizeof(search),stdin);
while(search[strlen(search)-1] == '\n') search[strlen(search)-1] = 0;
crsr2(20,1);
printf(" ");
};
if (c == '+') {
while(1==1){
while(1==1){
c = getbyte(&file_addr);
if (c == search[0]) break;
};
for (j=1;j<strlen(search);j++)
if(search[j] != getbyte()) break;
if(j==strlen(search)) break;
};
file_addr &= ~(PAGE-1);
showblock(1);
};
if (c == 'q') break;
} while(1==1);
reset_tty();
fclose(infile);
}

View File

@ -0,0 +1,487 @@
/*
* File isovfy.c - verify consistency of iso9660 filesystem.
*
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <signal.h>
FILE * infile;
#define PAGE sizeof(buffer)
#define ISODCL(from, to) (to - from + 1)
struct iso_primary_descriptor {
unsigned char type [ISODCL ( 1, 1)]; /* 711 */
unsigned char id [ISODCL ( 2, 6)];
unsigned char version [ISODCL ( 7, 7)]; /* 711 */
unsigned char unused1 [ISODCL ( 8, 8)];
unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */
unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */
unsigned char unused2 [ISODCL ( 73, 80)];
unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
unsigned char unused3 [ISODCL ( 89, 120)];
unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */
unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */
unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */
unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */
unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */
unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */
unsigned char publisher_id [ISODCL (319, 446)]; /* achars */
unsigned char preparer_id [ISODCL (447, 574)]; /* achars */
unsigned char application_id [ISODCL (575, 702)]; /* achars */
unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */
unsigned char unused4 [ISODCL (883, 883)];
unsigned char application_data [ISODCL (884, 1395)];
unsigned char unused5 [ISODCL (1396, 2048)];
};
struct iso_directory_record {
unsigned char length [ISODCL (1, 1)]; /* 711 */
unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */
unsigned char extent [ISODCL (3, 10)]; /* 733 */
unsigned char size [ISODCL (11, 18)]; /* 733 */
unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */
unsigned char flags [ISODCL (26, 26)];
unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */
unsigned char interleave [ISODCL (28, 28)]; /* 711 */
unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
unsigned char name_len [ISODCL (33, 33)]; /* 711 */
unsigned char name [38];
};
int
isonum_721 (char * p)
{
return ((p[0] & 0xff)
| ((p[1] & 0xff) << 8));
}
int
isonum_731 (char * p)
{
return ((p[0] & 0xff)
| ((p[1] & 0xff) << 8)
| ((p[2] & 0xff) << 16)
| ((p[3] & 0xff) << 24));
}
int
isonum_722 (char * p)
{
return ((p[1] & 0xff)
| ((p[0] & 0xff) << 8));
}
int
isonum_732 (char * p)
{
return ((p[3] & 0xff)
| ((p[2] & 0xff) << 8)
| ((p[1] & 0xff) << 16)
| ((p[0] & 0xff) << 24));
}
int
isonum_733 (char * p)
{
return (isonum_731 (p));
}
char lbuffer[1024];
int iline;
int rr_goof;
int
dump_rr(struct iso_directory_record * idr){
int len;
char * pnt;
len = idr->length[0] & 0xff;
len -= (sizeof(struct iso_directory_record) - sizeof(idr->name));
len -= idr->name_len[0];
pnt = (char *) idr;
pnt += (sizeof(struct iso_directory_record) - sizeof(idr->name));
pnt += idr->name_len[0];
if((idr->name_len[0] & 1) == 0){
pnt++;
len--;
};
rr_goof = 0;
parse_rr(pnt, len, 0);
return rr_goof;
}
int parse_rr(unsigned char * pnt, int len, int cont_flag)
{
int slen;
int ncount;
int flag1, flag2;
int extent;
unsigned char *pnts;
int cont_extent, cont_offset, cont_size;
char symlink[1024];
iline += sprintf(lbuffer+iline," RRlen=%d ", len);
cont_extent = cont_offset = cont_size = 0;
symlink[0] = 0;
ncount = 0;
flag1 = flag2 = 0;
while(len >= 4){
if(ncount) iline += sprintf(lbuffer+iline,",");
else iline += sprintf(lbuffer+iline,"[");
iline += sprintf(lbuffer+iline,"%c%c", pnt[0], pnt[1]);
if(pnt[0] < 'A' || pnt[0] > 'Z' || pnt[1] < 'A' ||
pnt[1] > 'Z') {
iline += sprintf(lbuffer+iline,"**BAD SUSP %d %d]",
pnt[0], pnt[1], rr_goof++);
return flag2;
};
if(pnt[3] != 1) {
iline += sprintf(lbuffer+iline,"**BAD RRVERSION", rr_goof++);
return flag2;
};
ncount++;
if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1;
if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2;
if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4;
if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8;
if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16;
if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32;
if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64;
if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128;
if(strncmp(pnt, "CE", 2) == 0) {
cont_extent = isonum_733(pnt+4);
cont_offset = isonum_733(pnt+12);
cont_size = isonum_733(pnt+20);
iline += sprintf(lbuffer+iline, "=[%x,%x,%d]",
cont_extent, cont_offset, cont_size);
};
if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) {
extent = isonum_733(pnt+4);
iline += sprintf(lbuffer+iline,"=%x", extent);
if(extent == 0) rr_goof++;
};
if(strncmp(pnt, "SL", 2) == 0) {
pnts = pnt+5;
slen = pnt[2] - 5;
while(slen >= 1){
switch(pnts[0] & 0xfe){
case 0:
strncat(symlink, pnts+2, pnts[1]);
break;
case 2:
strcat (symlink, ".");
break;
case 4:
strcat (symlink, "..");
break;
case 8:
strcat (symlink, "/");
break;
case 16:
strcat(symlink,"/mnt");
iline += sprintf(lbuffer+iline,"Warning - mount point requested");
break;
case 32:
strcat(symlink,"kafka");
iline += sprintf(lbuffer+iline,"Warning - host_name requested");
break;
default:
iline += sprintf(lbuffer+iline,"Reserved bit setting in symlink", rr_goof++);
break;
};
if((pnts[0] & 0xfe) && pnts[1] != 0) {
iline += sprintf(lbuffer+iline,"Incorrect length in symlink component");
};
if((pnts[0] & 1) == 0)
strcat(symlink,"/");
slen -= (pnts[1] + 2);
pnts += (pnts[1] + 2);
};
if(symlink[0] != 0) {
iline += sprintf(lbuffer+iline,"=%s", symlink);
symlink[0] = 0;
}
};
len -= pnt[2];
pnt += pnt[2];
if(len <= 3 && cont_extent) {
unsigned char sector[2048];
lseek(fileno(infile), cont_extent << 11, 0);
read(fileno(infile), sector, sizeof(sector));
flag2 |= parse_rr(&sector[cont_offset], cont_size, 1);
};
};
if(ncount) iline += sprintf(lbuffer+iline,"]");
if (!cont_flag && flag1 && flag1 != flag2)
iline += sprintf(lbuffer+iline,"Flag %x != %x", flag1, flag2, rr_goof++);
return flag2;
}
int dir_count = 0;
int dir_size_count = 0;
int ngoof = 0;
check_tree(int file_addr, int file_size, int parent_addr){
unsigned char buffer[2048];
unsigned int k;
int rflag;
int i, i1, j, goof;
int extent, size;
int line;
int orig_file_addr, parent_file_addr;
struct iso_directory_record * idr;
i1 = 0;
orig_file_addr = file_addr >> 11; /* Actual extent of this directory */
parent_file_addr = parent_addr >> 11;
if((dir_count % 100) == 0) printf("[%d %d]\n", dir_count, dir_size_count);
#if 0
printf("Starting directory %d %d %d\n", file_addr, file_size, parent_addr);
#endif
dir_count++;
dir_size_count += file_size >> 11;
if(file_size & 0x3ff) printf("********Directory has unusual size\n");
for(k=0; k < (file_size >> 11); k++){
lseek(fileno(infile), file_addr, 0);
read(fileno(infile), buffer, sizeof(buffer));
i = 0;
while(1==1){
goof = iline=0;
idr = (struct iso_directory_record *) &buffer[i];
if(idr->length[0] == 0) break;
iline += sprintf(&lbuffer[iline],"%3d ", idr->length[0]);
extent = isonum_733(idr->extent);
size = isonum_733(idr->size);
iline += sprintf(&lbuffer[iline],"%5x ", extent);
iline += sprintf(&lbuffer[iline],"%8d ", size);
iline += sprintf (&lbuffer[iline], "%c", (idr->flags[0] & 2) ? '*' : ' ');
if(idr->name_len[0] > 33 || idr->name_len[0] < 0)
iline += sprintf(&lbuffer[iline],"File name length=(%d)",
idr->name_len[0], goof++);
else if(idr->name_len[0] == 1 && idr->name[0] == 0) {
iline += sprintf(&lbuffer[iline],". ");
rflag = 0;
if(orig_file_addr !=*((unsigned int *) idr->extent))
iline += sprintf(&lbuffer[iline],"***** Directory has null extent.", goof++);
if(i1)
iline += sprintf(&lbuffer[iline],"***** . not first entry.", rr_goof++);
} else if(idr->name_len[0] == 1 && idr->name[0] == 1) {
iline += sprintf(&lbuffer[iline],".. ");
rflag = 0;
if(parent_file_addr !=*((unsigned int *) idr->extent))
iline += sprintf(&lbuffer[iline],"***** Directory has null extent.", goof++);
if(i1 != 1)
iline += sprintf(&lbuffer[iline],"***** .. not second entry.", rr_goof++);
} else {
if(i1 < 2) iline += sprintf(&lbuffer[iline]," Improper sorting.", rr_goof++);
for(j=0; j<idr->name_len[0]; j++) iline += sprintf(&lbuffer[iline],"%c", idr->name[j]);
for(j=0; j<14 -idr->name_len[0]; j++) iline += sprintf(&lbuffer[iline]," ");
rflag = 1;
};
if(size && extent == 0) iline += sprintf(&lbuffer[iline],"****Extent==0, size != 0", goof++);
if(size == 0 && extent) iline += sprintf(&lbuffer[iline],"****Extent!=0, size == 0", goof++);
if(idr->flags[0] & 0xfd)
iline += sprintf(&lbuffer[iline],"Flags=(%x) ", idr->flags[0], goof++);
if(idr->flags[0] & 0xfd)
iline += sprintf(&lbuffer[iline],"Flags=(%x) ", idr->flags[0], goof++);
if(idr->interleave[0])
iline += sprintf(&lbuffer[iline],"Interleave=(%d) ", idr->interleave[0], goof++);
if(idr->file_unit_size[0])
iline += sprintf(&lbuffer[iline],"File unit size=(%d) ", idr->file_unit_size[0], goof++);
if(idr->volume_sequence_number[0] != 1)
iline += sprintf(&lbuffer[iline],"Volume sequence number=(%d) ", idr->volume_sequence_number[0], goof++);
goof += dump_rr(idr);
iline += sprintf(&lbuffer[iline],"\n");
if(goof){
ngoof++;
lbuffer[iline++] = 0;
printf("%x: %s", orig_file_addr, lbuffer);
};
if(rflag && (idr->flags[0] & 2)) check_tree((*((unsigned int *) idr->extent)) << 11,
*((unsigned int *) idr->size),
orig_file_addr << 11);
i += buffer[i];
i1++;
if (i > 2048 - sizeof(struct iso_directory_record)) break;
};
file_addr += sizeof(buffer);
};
fflush(stdout);
}
/* This function simply dumps the contents of the path tables. No
consistency checking takes place, although this would proably be a good
idea. */
struct path_table_info{
char * name;
unsigned int extent;
unsigned short index;
unsigned short parent;
};
check_path_tables(int typel_extent, int typem_extent, int path_table_size){
int file_addr;
int count;
int j;
char * pnt;
char * typel, *typem;
/* Now read in the path tables */
typel = (char *) malloc(path_table_size);
lseek(fileno(infile), typel_extent << 11, 0);
read(fileno(infile), typel, path_table_size);
typem = (char *) malloc(path_table_size);
lseek(fileno(infile), typem_extent << 11, 0);
read(fileno(infile), typem, path_table_size);
j = path_table_size;
pnt = typel;
count = 1;
while(j){
int namelen, extent, index;
char name[32];
namelen = *pnt++; pnt++;
extent = isonum_731(pnt); pnt += 4;
index = isonum_721(pnt); pnt+= 2;
j -= 8+namelen;
memset(name, 0, sizeof(name));
strncpy(name, pnt, namelen);
pnt += namelen;
if(j & 1) { j--; pnt++;};
printf("%4.4d %4.4d %8.8x %s\n",count++, index, extent, name);
};
j = path_table_size;
pnt = typem;
count = 1;
while(j){
int namelen, extent, index;
char name[32];
namelen = *pnt++; pnt++;
extent = isonum_732(pnt); pnt += 4;
index = isonum_722(pnt); pnt+= 2;
j -= 8+namelen;
memset(name, 0, sizeof(name));
strncpy(name, pnt, namelen);
pnt += namelen;
if(j & 1) { j--; pnt++;};
printf("%4.4d %4.4d %8.8x %s\n", count++, index, extent, name);
};
}
main(int argc, char * argv[]){
int file_addr, file_size;
char c;
int nbyte;
struct iso_primary_descriptor ipd;
struct iso_directory_record * idr;
int typel_extent, typem_extent;
int path_table_size;
int i,j;
if(argc < 2) return 0;
infile = fopen(argv[1],"rb");
file_addr = 16 << 11;
lseek(fileno(infile), file_addr, 0);
read(fileno(infile), &ipd, sizeof(ipd));
idr = (struct iso_directory_record *) &ipd.root_directory_record;
file_addr = isonum_733(idr->extent);
file_size = isonum_733(idr->size);
printf("Root at extent %x, %d bytes\n", file_addr, file_size);
file_addr = file_addr << 11;
check_tree(file_addr, file_size, file_addr);
typel_extent = isonum_731(ipd.type_l_path_table);
typem_extent = isonum_732(ipd.type_m_path_table);
path_table_size = isonum_733(ipd.path_table_size);
/* Enable this to get the dump of the path tables */
#if 0
check_path_tables(typel_extent, typem_extent, path_table_size);
#endif
fclose(infile);
if(!ngoof) printf("No errors found\n");
}

View File

@ -0,0 +1,54 @@
/*
* 9-Dec-93 R.-D. Marzusch, marzusch@odiehh.hanse.de:
* added 'exclude' option (-x) to specify pathnames NOT to be included in
* CD image.
*/
#include <stdio.h>
#ifndef VMS
#ifdef HASMALLOC_H
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#endif
#include <string.h>
/* this allows for 1000 entries to be excluded ... */
#define MAXEXCL 1000
static char * excl[MAXEXCL];
void exclude(fn)
char * fn;
{
register int i;
for (i=0; excl[i] && i<MAXEXCL; i++);
if (i == MAXEXCL) {
fprintf(stderr,"Can't exclude '%s' - too many entries in table\n",fn);
return;
}
excl[i] = malloc(strlen(fn)+1);
if (! excl[i]) {
fprintf(stderr,"Can't allocate memory for excluded filename\n");
return;
}
strcpy(excl[i],fn);
}
int is_excluded(fn)
char * fn;
{
/* very dumb search method ... */
register int i;
for (i=0; excl[i] && i<MAXEXCL; i++) {
if (strcmp(excl[i],fn) == 0) {
return 1; /* found -> excluded filenmae */
}
}
return 0; /* not found -> not excluded */
}

View File

@ -0,0 +1,8 @@
/*
* 9-Dec-93 R.-D. Marzusch, marzusch@odiehh.hanse.de:
* added 'exclude' option (-x) to specify pathnames NOT to be included in
* CD image.
*/
void exclude();
int is_excluded();

177
gnu/usr.bin/mkisofs/hash.c Normal file
View File

@ -0,0 +1,177 @@
/*
* File hash.c - generate hash tables for iso9660 filesystem.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdlib.h>
#include "mkisofs.h"
#define NR_HASH 1024
#define HASH_FN(DEV, INO) ((DEV + INO + (INO >> 2) + (INO << 8)) % NR_HASH)
static struct file_hash * hash_table[NR_HASH] = {0,};
void FDECL1(add_hash, struct directory_entry *, spnt){
struct file_hash * s_hash;
unsigned int hash_number;
if(spnt->size == 0 || spnt->starting_block == 0)
if(spnt->size != 0 || spnt->starting_block != 0) {
fprintf(stderr,"Non zero-length file assigned zero extent.\n");
exit(1);
};
if (spnt->dev == (dev_t) UNCACHED_DEVICE || spnt->inode == UNCACHED_INODE) return;
hash_number = HASH_FN((unsigned int) spnt->dev, (unsigned int) spnt->inode);
#if 0
if (verbose) fprintf(stderr,"%s ",spnt->name);
#endif
s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash));
s_hash->next = hash_table[hash_number];
s_hash->inode = spnt->inode;
s_hash->dev = spnt->dev;
s_hash->starting_block = spnt->starting_block;
s_hash->size = spnt->size;
hash_table[hash_number] = s_hash;
}
struct file_hash * FDECL2(find_hash, dev_t, dev, ino_t, inode){
unsigned int hash_number;
struct file_hash * spnt;
hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL;
spnt = hash_table[hash_number];
while(spnt){
if(spnt->inode == inode && spnt->dev == dev) return spnt;
spnt = spnt->next;
};
return NULL;
}
static struct file_hash * directory_hash_table[NR_HASH] = {0,};
void FDECL2(add_directory_hash, dev_t, dev, ino_t, inode){
struct file_hash * s_hash;
unsigned int hash_number;
if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return;
hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash));
s_hash->next = directory_hash_table[hash_number];
s_hash->inode = inode;
s_hash->dev = dev;
directory_hash_table[hash_number] = s_hash;
}
struct file_hash * FDECL2(find_directory_hash, dev_t, dev, ino_t, inode){
unsigned int hash_number;
struct file_hash * spnt;
hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL;
spnt = directory_hash_table[hash_number];
while(spnt){
if(spnt->inode == inode && spnt->dev == dev) return spnt;
spnt = spnt->next;
};
return NULL;
}
struct name_hash{
struct name_hash * next;
struct directory_entry * de;
};
#define NR_NAME_HASH 128
static struct name_hash * name_hash_table[NR_NAME_HASH] = {0,};
static unsigned int FDECL1(name_hash, const char *, name){
unsigned int hash = 0;
const char * p;
p = name;
while (*p) hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++;
return hash % NR_NAME_HASH;
}
void FDECL1(add_file_hash, struct directory_entry *, de){
struct name_hash * new;
int hash;
new = (struct name_hash *) e_malloc(sizeof(struct name_hash));
new->de = de;
new->next = NULL;
hash = name_hash(de->isorec.name);
/* Now insert into the hash table */
new->next = name_hash_table[hash];
name_hash_table[hash] = new;
}
struct directory_entry * FDECL1(find_file_hash, char *, name){
struct name_hash * nh;
for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
if(strcmp(nh->de->isorec.name, name) == 0) return nh->de;
return NULL;
}
int FDECL1(delete_file_hash, struct directory_entry *, de){
struct name_hash * nh, *prev;
int hash;
prev = NULL;
hash = name_hash(de->isorec.name);
for(nh = name_hash_table[hash]; nh; nh = nh->next) {
if(nh->de == de) break;
prev = nh;
};
if(!nh) return 1;
if(!prev)
name_hash_table[hash] = nh->next;
else
prev->next = nh->next;
free(nh);
return 0;
}
void flush_file_hash(){
struct name_hash * nh, *nh1;
int i;
for(i=0; i<NR_NAME_HASH; i++) {
nh = name_hash_table[i];
while(nh) {
nh1 = nh->next;
free(nh);
nh = nh1;
};
name_hash_table[i] = NULL;
};
}

View File

@ -0,0 +1,107 @@
/*
* Header file iso9660.h - assorted structure definitions and typecasts.
* specific to iso9660 filesystem.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _ISOFS_FS_H
#define _ISOFS_FS_H
/*
* The isofs filesystem constants/structures
*/
/* This part borrowed from the bsd386 isofs */
#define ISODCL(from, to) (to - from + 1)
struct iso_volume_descriptor {
char type[ISODCL(1,1)]; /* 711 */
char id[ISODCL(2,6)];
char version[ISODCL(7,7)];
char data[ISODCL(8,2048)];
};
/* volume descriptor types */
#define ISO_VD_PRIMARY 1
#define ISO_VD_END 255
#define ISO_STANDARD_ID "CD001"
struct iso_primary_descriptor {
char type [ISODCL ( 1, 1)]; /* 711 */
char id [ISODCL ( 2, 6)];
char version [ISODCL ( 7, 7)]; /* 711 */
char unused1 [ISODCL ( 8, 8)];
char system_id [ISODCL ( 9, 40)]; /* achars */
char volume_id [ISODCL ( 41, 72)]; /* dchars */
char unused2 [ISODCL ( 73, 80)];
char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
char unused3 [ISODCL ( 89, 120)];
char volume_set_size [ISODCL (121, 124)]; /* 723 */
char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
char logical_block_size [ISODCL (129, 132)]; /* 723 */
char path_table_size [ISODCL (133, 140)]; /* 733 */
char type_l_path_table [ISODCL (141, 144)]; /* 731 */
char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
char type_m_path_table [ISODCL (149, 152)]; /* 732 */
char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
char volume_set_id [ISODCL (191, 318)]; /* dchars */
char publisher_id [ISODCL (319, 446)]; /* achars */
char preparer_id [ISODCL (447, 574)]; /* achars */
char application_id [ISODCL (575, 702)]; /* achars */
char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
char file_structure_version [ISODCL (882, 882)]; /* 711 */
char unused4 [ISODCL (883, 883)];
char application_data [ISODCL (884, 1395)];
char unused5 [ISODCL (1396, 2048)];
};
/* We use this to help us look up the parent inode numbers. */
struct iso_path_table{
unsigned char name_len[2]; /* 721 */
char extent[4]; /* 731 */
char parent[2]; /* 721 */
char name[1];
};
struct iso_directory_record {
unsigned char length [ISODCL (1, 1)]; /* 711 */
char ext_attr_length [ISODCL (2, 2)]; /* 711 */
char extent [ISODCL (3, 10)]; /* 733 */
char size [ISODCL (11, 18)]; /* 733 */
char date [ISODCL (19, 25)]; /* 7 by 711 */
char flags [ISODCL (26, 26)];
char file_unit_size [ISODCL (27, 27)]; /* 711 */
char interleave [ISODCL (28, 28)]; /* 711 */
char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
unsigned char name_len [ISODCL (33, 33)]; /* 711 */
char name [34]; /* Not really, but we need something here */
};
#endif

View File

@ -0,0 +1,16 @@
$! Set the def dir to proper place for use in batch. Works for interactive too.
$flnm = f$enviroment("PROCEDURE") ! get current procedure name
$set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
$!
$!
$if "''p1'".eqs."LINK" then goto link
$gcc/debug mkisofs.c
$gcc/debug write.c
$gcc/debug tree.c
$gcc/debug hash.c
$gcc/debug rock.c
$gcc/debug vms.c
$gcc/debug exclude.c
$link:
$link mkisofs.obj+write.obj+tree.obj+hash.obj+rock.obj+vms.obj+exclude.obj+ -
gnu_cc:[000000]gcclib/lib+sys$library:vaxcrtl/lib

View File

@ -0,0 +1,237 @@
.\" -*- nroff -*-
.TH MKISOFS 8 "August 1993" "Version 1.03"
.SH NAME
mkisofs \- create a iso9660 filesystem with optional Rock Ridge attributes.
.SH SYNOPSIS
.B mkisofs
[
.B \-R
]
[
.B \-T
]
[
.B \-v
]
[
.B \-z
]
[
.B \-a
]
[
.B \-f
]
[
.B \-d
]
[
.B \-D
]
[
.B \-l
]
[
.B \-V
]
[
.B \-V
.I volid
]
[
.B \-p
.I preparer
]
[
.B \-P
.I publisher
]
[
.B \-A
.I application_id
]
[
.B \-x
.I path
]
.B \-o
.I filename
.I path
.SH DESCRIPTION
.B mkisofs
is effectively a pre-mastering program to generate the iso9660 filesystem - it
takes a snapshot of a given directory tree, and generates a binary image which
will correspond to an iso9660 filesystem when written to a block device.
.PP
.B mkisofs
is also capable of generating the System Use Sharing Protocol records specified
by the Rock Ridge Interchange Protocol. This is used to further describe the
files in the iso9660 filesystem to a unix host, and provides information such
as longer filenames, uid/gid, posix permissions, and block and character
devices.
.PP
Each file written to the iso9660 filesystem must have a filename in the 8.3
format (8 characters, period, 3 characters, all upper case), even if Rock Ridge
is in use. This filename is used on systems that are not able to make use of
the Rock Ridge extensions (such as MS-DOS), and each filename in each directory
must be different from the other filenames in the same directory.
.B mkisofs
generally tries to form correct names by forcing the unix filename to upper
case and truncating as required, but often times this yields unsatisfactory
results when there are cases where the
truncated names are not all unique.
.B mkisofs
assigns weightings to each filename, and if two names that are otherwise the
same are found the name with the lower priority is renamed to have a 3 digit
number as an extension (where the number is guaranteed to be unique). An
example of this would be the files foo.bar and
foo.bar.~1~ - the file foo.bar.~1~ would be written as FOO.000;1 and the file
foo.bar would be written as FOO.BAR;1
.PP
.br
.B path
is the path of the directory tree to be copied into the iso9660 filesystem.
.SH OPTIONS
.TP
.I -a
Include all files on the iso9660 filesystem. Normally files that contain the
characters '~' or '#' will not be included (these are typically backup files
for editors under unix).
.TP
.I -A application_id
Specifies a text string that will be written into the volume header.
This should describe the application that will be on the disc. There
is space on the disc for 128 characters of information. This parameter can
also be set in the file .mkisofsrc with APPL=id. If specified in both
places, the command line version is used.
.TP
.I -d
Omit trailing period from files that do not have a period. This violates the
ISO9660 standard, but it happens to work on many systems. Use with caution.
.TP
.I -D
Do not use deep directory relocation, and instead just pack them in the
way we see them. This violates the ISO9660 standard, but it works on many
systems. Use with caution.
.TP
.I -f
Follow symbolic links when generating the filesystem. When this option is not
in use, symbolic links will be entered using Rock Ridge if enabled, otherwise
the file will be ignored.
.TP
.I -l
Allow full 32 character filenames. Normally the ISO9660 filename will be in an
8.3 format which is compatible with MS-DOS, even though the ISO9660 standard
allows filenames of up to 32 characters. If you use this option, the disc may
be difficult to use on a MS-DOS system, but this comes in handy on some other
systems (such as the Amiga). Use with caution.
.TP
.I -N
Omit version numbers from ISO9660 file names. This may violate the ISO9660
standard, but no one really uses the version numbers anyway. Use with caution.
.TP
.I -o filename
is the name of the file to which the iso9660 filesystem image should be
written. This can be a disk file, a tape drive, or it can correspond directly
to the device name of the optical disc writer. If not specified, stdout is
]used. Note that the output can also be a block special device for a regular
disk drive, in which case the disk partition can be mounted and examined to
ensure that the premastering was done correctly.
.TP
.I -P publisher_id
Specifies a text string that will be written into the volume header.
This should describe the publisher of the CDROM, usually with a
mailing address and phone number. There is space on the disc for 128
characters of information. This parameter can also be set in the file
.mkisofsrc with PUBL=. If specified in both places, the command line
version is used.
.TP
.I -p preparer_id
Specifies a text string that will be written into the volume header.
This should describe the preparer of the CDROM, usually with a mailing
address and phone number. There is space on the disc for 128
characters of information. This parameter can also be set in the file
.mkisofsrc with PREP=. If specified in both places, the command
line version is used.
.TP
.I -R
Generate SUSP and RR records using the Rock Ridge protocol to further describe
the files on the iso9660 filesystem.
.TP
.I -T
Generate a file TRANS.TBL in each directory on the CDROM, which can be used
on non-Rock Ridge capable systems to help establish the correct file names.
There is also information present in the file that indicates the major and
minor numbers for block and character devices, and each symlink has the name of
the link file given.
.TP
.I -V volid
Specifies the volume ID to be written into the master block. This
parameter can also be set in the file .mkisofsrc with VOLI=id. If
specified in both places, the command line version is used.
.TP
.I -v
Verbose execution.
.TP
.I -x path
Exclude
.I path
from being written to CDROM.
.I path
must be the complete pathname that results from concatenating the pathname
given as command line argument and the path relative to this directory.
Multiple paths may be excluded (up to 1000).
Example:
mkisofs -o cd -x /local/dir1 -x /local/dir2 /local
.TP
.I -z
Generate special SUSP records for transparently compressed files. This is
only of use and interest for hosts that support transparent decompression.
This is an experimental feature, and no hosts yet support this, but there
are ALPHA patches for linux that can make use of this feature.
.SH CONFIGURATION
.B mkisofs
looks for a file .mkisofsrc, first in the current working directory, and if not
found there then in the directory in which the
.B mkisofs
binary is stored. This file is assumed to contain a series of lines
of the form "TAG=value", and in this way you can specify certain
options. Only the first four characters of the tag are used, and the
case of the tag is not significant. Some fields in the volume header
are not settable on the command line, but can be altered through this
facility. These are the copyright information (COPY), the
bibliographic information (BIBL), the abstract (ABST), the volume set
ID (VOLS) and the system ID (SYSI).
.PP
.B mkisofs
can also be configured at compile time with defaults for many of these fields.
See the file defaults.h.
.SH AUTHOR
.B mkisofs
is not based on the standard mk*fs tools for unix, because we must generate
a complete copy of an existing filesystem on a disk in the iso9660
filesystem. The name mkisofs is probably a bit of a misnomer, since it
not only creates the filesystem, but it also populates it as well.
.PP
.br
Eric Youngdale <ericy@cais.com> wrote both the linux isofs9660 filesystem
and the mkisofs utility, and is currently maintaining them. The copyright for
the mkisofs utility is held by Yggdrasil Computing, Incorporated.
.SH BUGS
Any files that have hard links to files not in the tree being copied to the
iso9660 filessytem will have an incorrect file reference count.
.PP
There may be some other ones. Please, report them to the author.
.SH FUTURE IMPROVEMENTS
Allow specfication of multiple paths on the command line to be included in
iso9660 filesystem. Can be tricky - directory entries in the root directory
need to be properly sorted.
.SH AVAILABILITY
.B mkisofs
is available for anonymous ftp from tsx-11.mit.edu in
/pub/linux/BETA/cdrom/mkisofs and many other mirror sites. With the 1.0
release, it is no longer considered to be in beta testing. Most of the bugs
that are being discovered now are very minor (and interestingly enough also
seem to be present in the YM software). Reports indicate that people are
gearing up for production runs using version 1.00.

View File

@ -0,0 +1,546 @@
/*
* Program mkisofs.c - generate iso9660 filesystem based upon directory
* tree on hard disk.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "mkisofs.h"
#ifdef linux
#include <getopt.h>
#endif
#include "iso9660.h"
#include <ctype.h>
#ifndef VMS
#include <time.h>
#else
#include <sys/time.h>
#include "vms.h"
#endif
#include <stdlib.h>
#include <sys/stat.h>
#ifndef VMS
#include <unistd.h>
#endif
#include "exclude.h"
#ifdef __NetBSD__
#include <sys/time.h>
#include <sys/resource.h>
#endif
struct directory * root = NULL;
static char version_string[] = "mkisofs v1.03";
FILE * discimage;
unsigned int next_extent = 0;
unsigned int last_extent = 0;
unsigned int path_table_size = 0;
unsigned int path_table[4] = {0,};
unsigned int path_blocks = 0;
struct iso_directory_record root_record;
static int timezone_offset;
char * extension_record = NULL;
int extension_record_extent = 0;
static int extension_record_size = 0;
/* These variables are associated with command line options */
int use_RockRidge = 0;
int verbose = 0;
int all_files = 0;
int follow_links = 0;
int generate_tables = 0;
char * preparer = PREPARER_DEFAULT;
char * publisher = PUBLISHER_DEFAULT;
char * appid = APPID_DEFAULT;
char * copyright = COPYRIGHT_DEFAULT;
char * biblio = BIBLIO_DEFAULT;
char * abstract = ABSTRACT_DEFAULT;
char * volset_id = VOLSET_ID_DEFAULT;
char * volume_id = VOLUME_ID_DEFAULT;
char * system_id = SYSTEM_ID_DEFAULT;
int omit_period = 0; /* Violates iso9660, but these are a pain */
int transparent_compression = 0; /* So far only works with linux */
int omit_version_number = 0; /* May violate iso9660, but noone uses vers*/
int RR_relocation_depth = 6; /* Violates iso9660, but most systems work */
int full_iso9660_filenames = 0; /* Used with Amiga. Disc will not work with
DOS */
struct rcopts{
char * tag;
char ** variable;
};
struct rcopts rcopt[] = {
{"PREP", &preparer},
{"PUBL", &publisher},
{"APPI", &appid},
{"COPY", &copyright},
{"BIBL", &biblio},
{"ABST", &abstract},
{"VOLS", &volset_id},
{"VOLI", &volume_id},
{"SYSI", &system_id},
{NULL, NULL}
};
#ifdef ultrix
char *strdup(s)
char *s;{char *c;if(c=(char *)malloc(strlen(s)+1))strcpy(c,s);return c;}
#endif
void FDECL1(read_rcfile, char *, appname)
{
FILE * rcfile;
struct rcopts * rco;
char * pnt, *pnt1;
char linebuffer[256];
rcfile = fopen(".mkisofsrc","r");
if(!rcfile) {
if(strlen(appname)+sizeof(".mkisofsrc") > sizeof(linebuffer)) return;
strcpy(linebuffer, appname);
pnt = strrchr(linebuffer,'/');
if(!pnt) return;
pnt++;
strcpy(pnt, ".mkisofsrc");
rcfile = fopen(linebuffer,"r");
fprintf(stderr, "Using %s.\n", linebuffer);
} else {
fprintf(stderr, "Using ./.mkisofsrc.\n");
}
if(!rcfile) return;
/* OK, we got it. Now read in the lines and parse them */
while(!feof(rcfile))
{
fgets(linebuffer, sizeof(linebuffer), rcfile);
pnt = linebuffer;
while(1==1) {
if(*pnt == ' ' || *pnt == '\t' || *pnt == '\n' || *pnt == 0) break;
if(islower(*pnt)) *pnt = toupper(*pnt);
pnt++;
}
/* OK, now find the '=' sign */
while(*pnt && *pnt != '=' && *pnt != '#') pnt++;
if(*pnt == '#') continue; /* SKip comment */
if(*pnt != '=') continue; /* Skip to next line */
pnt++; /* Skip past '=' sign */
while(*pnt == ' ' || *pnt == '\t') pnt++; /* And skip past whitespace */
/* Now get rid of trailing newline */
pnt1 = pnt;
while(*pnt1) {
if(*pnt1 == '\n') *pnt1 = 0;
else
pnt1++;
};
pnt1 = linebuffer;
while(*pnt1 == ' ' || *pnt1 == '\t') pnt1++;
/* OK, now figure out which option we have */
for(rco = rcopt; rco->tag; rco++) {
if(strncmp(rco->tag, pnt1, 4) == 0)
{
*rco->variable = strdup(pnt);
break;
};
}
}
fclose(rcfile);
}
char * path_table_l = NULL;
char * path_table_m = NULL;
int goof = 0;
void usage(){
fprintf(stderr,"Usage:\n");
fprintf(stderr,
"mkisofs [-o outfile] [-R] [-V volid] [-v] [-a] \
[-T]\n [-l] [-d] [-V] [-D] [-p preparer] \
[-P publisher] [ -A app_id ] [-z] \
[-x path -x path ...] path\n");
exit(1);
}
int get_iso9660_timezone_offset(){
struct tm gm;
struct tm * pt;
time_t ctime;
int local_min, gmt_min;
time(&ctime);
pt = gmtime(&ctime);
gm = *pt;
pt = localtime(&ctime);
if(gm.tm_year < pt->tm_year)
gm.tm_yday = -1;
if(gm.tm_year > pt->tm_year)
pt->tm_yday = -1;
gmt_min = gm.tm_min + 60*(gm.tm_hour + 24*gm.tm_yday);
local_min = pt->tm_min + 60*(pt->tm_hour + 24*pt->tm_yday);
return (gmt_min - local_min)/15;
}
/* Fill in date in the iso9660 format */
int FDECL2(iso9660_date,char *, result, time_t, ctime){
struct tm *local;
local = localtime(&ctime);
result[0] = local->tm_year;
result[1] = local->tm_mon + 1;
result[2] = local->tm_mday;
result[3] = local->tm_hour;
result[4] = local->tm_min;
result[5] = local->tm_sec;
result[6] = timezone_offset;
return 0;
}
int FDECL3(iso9660_file_length,const char*, name, struct directory_entry *, sresult,
int, dirflag){
int seen_dot = 0;
int seen_semic = 0;
char * result;
int priority = 32767;
int tildes = 0;
int ignore = 0;
int extra = 0;
int current_length = 0;
int chars_after_dot = 0;
int chars_before_dot = 0;
const char * pnt;
result = sresult->isorec.name;
if(strcmp(name,".") == 0){
if(result) *result = 0;
return 1;
};
if(strcmp(name,"..") == 0){
if(result) {
*result++ = 1;
*result++ = 0;
}
return 1;
};
pnt = name;
while(*pnt){
#ifdef VMS
if(strcmp(pnt,".DIR;1") == 0) break;
#endif
if(*pnt == '#') {priority = 1; pnt++; continue; };
if(*pnt == '~') {priority = 1; tildes++; pnt++; continue;};
if(*pnt == ';') {seen_semic = 1; *result++ = *pnt++; continue; };
if(ignore) {pnt++; continue;};
if(seen_semic){
if(*pnt >= '0' && *pnt <= '9') *result++ = *pnt;
extra++;
pnt++;
continue;
};
if(full_iso9660_filenames) {
/* Here we allow a more relaxed syntax. */
if(*pnt == '.') {
if (seen_dot) {ignore++; continue;}
seen_dot++;
}
if(current_length < 30) *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt);
} else { /* Dos style filenames */
if(*pnt == '.') {
if (seen_dot) {ignore++; continue;}
if(result) *result++ = '.';
seen_dot++;
} else if (seen_dot) {
if(chars_after_dot < 3) {
chars_after_dot++;
if(result) *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt);
}
} else {
if(chars_before_dot < 8) {
chars_before_dot++;
if(result) *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt);
};
};
};
current_length++;
pnt++;
};
if(tildes == 2){
int prio1 = 0;
pnt = name;
while (*pnt && *pnt != '~') pnt++;
if (*pnt) pnt++;
while(*pnt && *pnt != '~'){
prio1 = 10*prio1 + *pnt - '0';
pnt++;
};
priority = prio1;
};
if (!dirflag){
if (!seen_dot && !omit_period) {
if (result) *result++ = '.';
extra++;
};
if(!omit_version_number && !seen_semic) {
if(result){
*result++ = ';';
*result++ = '1';
};
extra += 2;
}
};
if(result) *result++ = 0;
sresult->priority = priority;
return chars_before_dot + chars_after_dot + seen_dot + extra;
}
int FDECL2(main, int, argc, char **, argv){
char * outfile;
struct directory_entry de;
unsigned int mem_start;
struct stat statbuf;
char * scan_tree;
int c;
if (argc < 2)
usage();
/* Get the defaults from the .mkisofsrc file */
read_rcfile(argv[0]);
outfile = NULL;
while ((c = getopt(argc, argv, "o:V:RfvaTp:P:x:dDlNzA:")) != EOF)
switch (c)
{
case 'p':
preparer = optarg;
if(strlen(preparer) > 128) {
fprintf(stderr,"Preparer string too long\n");
exit(1);
};
break;
case 'P':
publisher = optarg;
if(strlen(publisher) > 128) {
fprintf(stderr,"Publisher string too long\n");
exit(1);
};
break;
case 'A':
appid = optarg;
if(strlen(appid) > 128) {
fprintf(stderr,"Application-id string too long\n");
exit(1);
};
break;
case 'd':
omit_period++;
break;
case 'D':
RR_relocation_depth = 32767;
break;
case 'l':
full_iso9660_filenames++;
break;
case 'N':
omit_version_number++;
break;
case 'o':
outfile = optarg;
break;
case 'f':
follow_links++;
break;
case 'R':
use_RockRidge++;
break;
case 'V':
volume_id = optarg;
break;
case 'v':
verbose++;
break;
case 'a':
all_files++;
break;
case 'T':
generate_tables++;
break;
case 'z':
#ifdef VMS
fprintf(stderr,"Transparent compression not supported with VMS\n");
exit(1);
#else
transparent_compression++;
#endif
break;
case 'x':
exclude(optarg);
break;
default:
usage();
exit(1);
}
#ifdef __NetBSD__
{
int resource;
struct rlimit rlp;
if (getrlimit(RLIMIT_DATA,&rlp) == -1)
perror("Warning: getrlimit");
else {
rlp.rlim_cur=33554432;
if (setrlimit(RLIMIT_DATA,&rlp) == -1)
perror("Warning: setrlimit");
}
}
#endif
mem_start = (unsigned int) sbrk(0);
if(verbose) fprintf(stderr,"%s\n", version_string);
/* Now find the timezone offset */
timezone_offset = get_iso9660_timezone_offset();
/* The first step is to scan the directory tree, and take some notes */
scan_tree = argv[optind];
if(!scan_tree){
usage();
exit(1);
};
#ifndef VMS
if(scan_tree[strlen(scan_tree)-1] != '/') {
scan_tree = (char *) e_malloc(strlen(argv[optind])+2);
strcpy(scan_tree, argv[optind]);
strcat(scan_tree, "/");
};
#endif
if(use_RockRidge){
#if 1
extension_record = generate_rr_extension_record("RRIP_1991A",
"THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
"PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.", &extension_record_size);
#else
extension_record = generate_rr_extension_record("IEEE_P1282",
"THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
"PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT,PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION.", &extension_record_size);
#endif
};
stat(argv[optind], &statbuf);
add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
de.filedir = root; /* We need this to bootstrap */
scan_directory_tree(argv[optind], &de);
root->self = root->contents; /* Fix this up so that the path tables get done right */
if(reloc_dir) sort_n_finish(reloc_dir);
if (goof) exit(1);
if (outfile){
discimage = fopen(outfile, "w");
if (!discimage){
fprintf(stderr,"Unable to open disc image file\n");
exit(1);
};
} else
discimage = stdout;
/* Now assign addresses on the disc for the path table. */
path_blocks = (path_table_size + (SECTOR_SIZE - 1)) >> 11;
if (path_blocks & 1) path_blocks++;
path_table[0] = 0x14;
path_table[1] = path_table[0] + path_blocks;
path_table[2] = path_table[1] + path_blocks;
path_table[3] = path_table[2] + path_blocks;
last_extent = path_table[3] + path_blocks; /* The next free block */
/* The next step is to go through the directory tree and assign extent
numbers for all of the directories */
assign_directory_addresses(root);
if(extension_record) {
struct directory_entry * s_entry;
extension_record_extent = last_extent++;
s_entry = root->contents;
set_733(s_entry->rr_attributes + s_entry->rr_attr_size - 24,
extension_record_extent);
set_733(s_entry->rr_attributes + s_entry->rr_attr_size - 8,
extension_record_size);
};
if (use_RockRidge && reloc_dir)
finish_cl_pl_entries();
/* Now we generate the path tables that are used by DOS to improve directory
access times. */
generate_path_tables();
/* Generate root record for volume descriptor. */
generate_root_record();
dump_tree(root);
iso_write(discimage);
fprintf(stderr,"Max brk space used %x\n",
((unsigned int)sbrk(0)) - mem_start);
fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9);
#ifdef VMS
return 1;
#else
return 0;
#endif
}
void *e_malloc(size_t size)
{
void* pt;
if((pt=malloc(size))==NULL) {
printf("Not enougth memory\n");
exit (1);
}
return pt;
}

View File

@ -0,0 +1,243 @@
/*
* Header file mkisofs.h - assorted structure definitions and typecasts.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
/* This symbol is used to indicate that we do not have things like
symlinks, devices, and so forth available. Just files and dirs */
#ifdef VMS
#define NON_UNIXFS
#endif
#ifdef DJGPP
#define NON_UNIXFS
#endif
#ifdef VMS
#include <sys/dir.h>
#define dirent direct
#else
#include <dirent.h>
#endif
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef linux
#include <sys/dir.h>
#endif
#ifdef ultrix
extern char *strdup();
#endif
#ifdef __STDC__
#define DECL(NAME,ARGS) NAME ARGS
#define FDECL1(NAME,TYPE0, ARG0) \
NAME(TYPE0 ARG0)
#define FDECL2(NAME,TYPE0, ARG0,TYPE1, ARG1) \
NAME(TYPE0 ARG0, TYPE1 ARG1)
#define FDECL3(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2) \
NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2)
#define FDECL4(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3) \
NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3)
#define FDECL5(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4) \
NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3, TYPE4 ARG4)
#define FDECL6(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4, TYPE5, ARG5) \
NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3, TYPE4 ARG4, TYPE5 ARG5)
#else
#define DECL(NAME,ARGS) NAME()
#define FDECL1(NAME,TYPE0, ARG0) NAME(ARG0) TYPE0 ARG0;
#define FDECL2(NAME,TYPE0, ARG0,TYPE1, ARG1) NAME(ARG0, ARG1) TYPE0 ARG0; TYPE1 ARG1;
#define FDECL3(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2) \
NAME(ARG0, ARG1, ARG2) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2;
#define FDECL4(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3) \
NAME(ARG0, ARG1, ARG2, ARG3, ARG4) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3;
#define FDECL5(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4) \
NAME(ARG0, ARG1, ARG2, ARG3, ARG4) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; TYPE4 ARG4;
#define FDECL6(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4, TYPE5, ARG5) \
NAME(ARG0, ARG1, ARG2, ARG3, ARG4, ARG5) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; TYPE4 ARG4; TYPE5 ARG5;
#define const
#endif
#ifdef __svr4__
#include <stdlib.h>
#else
extern int optind;
extern char *optarg;
/* extern int getopt (int __argc, char **__argv, char *__optstring); */
#endif
#include "iso9660.h"
#include "defaults.h"
struct directory_entry{
struct directory_entry * next;
struct iso_directory_record isorec;
unsigned int starting_block;
unsigned int size;
unsigned int priority;
char * name;
char * table;
struct directory * filedir;
struct directory_entry * parent_rec;
unsigned int flags;
ino_t inode; /* Used in the hash table */
dev_t dev; /* Used in the hash table */
unsigned char * rr_attributes;
unsigned int rr_attr_size;
unsigned int total_rr_attr_size;
};
struct file_hash{
struct file_hash * next;
ino_t inode; /* Used in the hash table */
dev_t dev; /* Used in the hash table */
unsigned int starting_block;
unsigned int size;
};
struct directory{
struct directory * next; /* Next directory at same level as this one */
struct directory * subdir; /* First subdirectory in this directory */
struct directory * parent;
struct directory_entry * contents;
struct directory_entry * self;
char * whole_name; /* Entire path */
char * de_name; /* Entire path */
unsigned int ce_bytes; /* Number of bytes of CE entries reqd for this dir */
unsigned int depth;
unsigned int size;
unsigned int extent;
unsigned short path_index;
};
struct deferred{
struct deferred * next;
unsigned int starting_block;
char * name;
struct directory * filedir;
unsigned int flags;
};
extern void DECL(sort_n_finish,(struct directory *));
extern int goof;
extern struct directory * root;
extern struct directory * reloc_dir;
extern unsigned int next_extent;
extern unsigned int last_extent;
extern unsigned int path_table_size;
extern unsigned int path_table[4];
extern unsigned int path_blocks;
extern char * path_table_l;
extern char * path_table_m;
extern struct iso_directory_record root_record;
extern int use_RockRidge;
extern int follow_links;
extern int verbose;
extern int all_files;
extern int generate_tables;
extern int omit_period;
extern int omit_version_number;
extern int transparent_compression;
extern int RR_relocation_depth;
extern int full_iso9660_filenames;
extern int DECL(scan_directory_tree,(char * path, struct directory_entry * self));
extern void DECL(dump_tree,(struct directory * node));
extern void DECL(assign_directory_addresses,(struct directory * root));
extern int DECL(iso9660_file_length,(const char* name,
struct directory_entry * sresult, int flag));
extern int DECL(iso_write,(FILE * outfile));
extern void generate_path_tables();
extern void DECL(generate_iso9660_directories,(struct directory *, FILE*));
extern void DECL(generate_one_directory,(struct directory *, FILE*));
extern void generate_root_record();
extern int DECL(iso9660_date,(char *, time_t));
extern void DECL(add_hash,(struct directory_entry *));
extern struct file_hash * DECL(find_hash,(dev_t, ino_t));
extern void DECL(add_directory_hash,(dev_t, ino_t));
extern struct file_hash * DECL(find_directory_hash,(dev_t, ino_t));
extern void flush_file_hash();
extern int DECL(delete_file_hash,(struct directory_entry *));
extern struct directory_entry * DECL(find_file_hash,(char *));
extern void DECL(add_file_hash,(struct directory_entry *));
extern void finish_cl_pl_entries();
extern int DECL(get_733,(char *));
extern void DECL(set_723,(char *, unsigned int));
extern void DECL(set_733,(char *, unsigned int));
extern void DECL(sort_directory,(struct directory_entry **));
extern int DECL(generate_rock_ridge_attributes,(char *, char *,
struct directory_entry *,
struct stat *, struct stat *,
int deep_flag));
extern char * DECL(generate_rr_extension_record,(char * id, char * descriptor,
char * source, int * size));
extern char * extension_record;
extern int extension_record_extent;
extern int n_data_extents;
/* These are a few goodies that can be specified on the command line, and are
filled into the root record */
extern char * preparer;
extern char * publisher;
extern char * copyright;
extern char * biblio;
extern char * abstract;
extern char * appid;
extern char * volset_id;
extern char * system_id;
extern char * volume_id;
extern void * DECL(e_malloc,(size_t));
#define SECTOR_SIZE (2048)
#define ROUND_UP(X) ((X + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
#define NEED_RE 1
#define NEED_PL 2
#define NEED_CL 4
#define NEED_CE 8
#define NEED_SP 16
#define TABLE_INODE (sizeof(ino_t) >= 4 ? 0x7ffffffe : 0x7ffe)
#define UNCACHED_INODE (sizeof(ino_t) >= 4 ? 0x7fffffff : 0x7fff)
#define UNCACHED_DEVICE (sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff)
#ifdef VMS
#define STAT_INODE(X) (X.st_ino[0])
#define PATH_SEPARATOR ']'
#define SPATH_SEPARATOR ""
#else
#define STAT_INODE(X) (X.st_ino)
#define PATH_SEPARATOR '/'
#define SPATH_SEPARATOR "/"
#endif

530
gnu/usr.bin/mkisofs/rock.c Normal file
View File

@ -0,0 +1,530 @@
/*
* File rock.c - generate RRIP records for iso9660 filesystems.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdlib.h>
#ifndef VMS
#if defined(HASSYSMACROS) && !defined(HASMKDEV)
#include <sys/sysmacros.h>
#endif
#include <unistd.h>
#endif
#ifdef HASMKDEV
#include <sys/types.h>
#include <sys/mkdev.h>
#endif
#include "mkisofs.h"
#include "iso9660.h"
#include <string.h>
#ifdef NON_UNIXFS
#define S_ISLNK(m) (0)
#else
#ifndef S_ISLNK
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
#endif
#define SU_VERSION 1
#define SL_ROOT 8
#define SL_PARENT 4
#define SL_CURRENT 2
#define SL_CONTINUE 1
#define CE_SIZE 28
#define CL_SIZE 12
#define ER_SIZE 8
#define NM_SIZE 5
#define PL_SIZE 12
#define PN_SIZE 20
#define PX_SIZE 36
#define RE_SIZE 4
#define SL_SIZE 20
#define ZZ_SIZE 15
#ifdef __QNX__
#define TF_SIZE (5 + 4 * 7)
#else
#define TF_SIZE (5 + 3 * 7)
#endif
/* If we need to store this number of bytes, make sure we
do not box ourselves in so that we do not have room for
a CE entry for the continuation record */
#define MAYBE_ADD_CE_ENTRY(BYTES) \
(BYTES + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0)
/*
* Buffer to build RR attributes
*/
static unsigned char Rock[16384];
static unsigned char symlink_buff[256];
static int ipnt = 0;
static int recstart = 0;
static int currlen = 0;
static int mainrec = 0;
static int reclimit;
static add_CE_entry(){
if(recstart)
set_733((char*)Rock + recstart - 8, ipnt + 28 - recstart);
Rock[ipnt++] ='C';
Rock[ipnt++] ='E';
Rock[ipnt++] = CE_SIZE;
Rock[ipnt++] = SU_VERSION;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
recstart = ipnt;
currlen = 0;
if(!mainrec) mainrec = ipnt;
reclimit = SECTOR_SIZE - 8; /* Limit to one sector */
}
#ifdef __STDC__
int generate_rock_ridge_attributes (char * whole_name, char * name,
struct directory_entry * s_entry,
struct stat * statbuf,
struct stat * lstatbuf,
int deep_opt)
#else
int generate_rock_ridge_attributes (whole_name, name,
s_entry,
statbuf,
lstatbuf,
deep_opt)
char * whole_name; char * name; struct directory_entry * s_entry;
struct stat * statbuf, *lstatbuf;
int deep_opt;
#endif
{
int flagpos, flagval;
int need_ce;
statbuf = statbuf; /* this shuts up unreferenced compiler warnings */
mainrec = recstart = ipnt = 0;
reclimit = 0xf8;
/* Obtain the amount of space that is currently used for the directory
record. Assume max for name, since name conflicts may cause us
to rename the file later on */
currlen = sizeof(s_entry->isorec);
/* Identify that we are using the SUSP protocol */
if(deep_opt & NEED_SP){
Rock[ipnt++] ='S';
Rock[ipnt++] ='P';
Rock[ipnt++] = 7;
Rock[ipnt++] = SU_VERSION;
Rock[ipnt++] = 0xbe;
Rock[ipnt++] = 0xef;
Rock[ipnt++] = 0;
};
/* First build the posix name field */
Rock[ipnt++] ='R';
Rock[ipnt++] ='R';
Rock[ipnt++] = 5;
Rock[ipnt++] = SU_VERSION;
flagpos = ipnt;
flagval = 0;
Rock[ipnt++] = 0; /* We go back and fix this later */
if(strcmp(name,".") && strcmp(name,"..")){
char * npnt;
int remain, use;
remain = strlen(name);
npnt = name;
while(remain){
use = remain;
need_ce = 0;
/* Can we fit this SUSP and a CE entry? */
if(use + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
use = reclimit - currlen - CE_SIZE - (ipnt - recstart);
need_ce++;
}
/* Only room for 256 per SUSP field */
if(use > 0xf8) use = 0xf8;
/* First build the posix name field */
Rock[ipnt++] ='N';
Rock[ipnt++] ='M';
Rock[ipnt++] = NM_SIZE + use;
Rock[ipnt++] = SU_VERSION;
Rock[ipnt++] = (remain != use ? 1 : 0);
flagval |= (1<<3);
strncpy((char *)&Rock[ipnt], npnt, use);
npnt += use;
ipnt += use;
remain -= use;
if(remain && need_ce) add_CE_entry();
};
};
/*
* Add the posix modes
*/
if(MAYBE_ADD_CE_ENTRY(PX_SIZE)) add_CE_entry();
Rock[ipnt++] ='P';
Rock[ipnt++] ='X';
Rock[ipnt++] = PX_SIZE;
Rock[ipnt++] = SU_VERSION;
flagval |= (1<<0);
set_733((char*)Rock + ipnt, lstatbuf->st_mode);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_nlink);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_uid);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_gid);
ipnt += 8;
/*
* Check for special devices
*/
#ifndef NON_UNIXFS
if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) {
if(MAYBE_ADD_CE_ENTRY(PN_SIZE)) add_CE_entry();
Rock[ipnt++] ='P';
Rock[ipnt++] ='N';
Rock[ipnt++] = PN_SIZE;
Rock[ipnt++] = SU_VERSION;
flagval |= (1<<1);
if(sizeof(dev_t) <= 4) {
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_rdev);
ipnt += 8;
}
else {
#ifdef ultrix
set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 16) >> 16);
#else
set_733((char*)Rock + ipnt, lstatbuf->st_rdev >> 32);
#endif
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_rdev);
ipnt += 8;
}
};
#endif
/*
* Check for and symbolic links. VMS does not have these.
*/
if (S_ISLNK(lstatbuf->st_mode)){
int lenpos, lenval, j0, j1;
int cflag, nchar;
unsigned char * cpnt, *cpnt1;
nchar = readlink(whole_name, symlink_buff, sizeof(symlink_buff));
symlink_buff[nchar] = 0;
set_733(s_entry->isorec.size, 0);
cpnt = &symlink_buff[0];
flagval |= (1<<2);
while(nchar){
if(MAYBE_ADD_CE_ENTRY(SL_SIZE)) add_CE_entry();
Rock[ipnt++] ='S';
Rock[ipnt++] ='L';
lenpos = ipnt;
Rock[ipnt++] = SL_SIZE;
Rock[ipnt++] = SU_VERSION;
Rock[ipnt++] = 0; /* Flags */
lenval = 5;
while(*cpnt){
cpnt1 = (unsigned char *) strchr((char *) cpnt, '/');
if(cpnt1) {
nchar--;
*cpnt1 = 0;
};
/* We treat certain components in a special way. */
if(cpnt[0] == '.' && cpnt[1] == '.' && cpnt[2] == 0){
if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
Rock[ipnt++] = SL_PARENT;
Rock[ipnt++] = 0; /* length is zero */
lenval += 2;
nchar -= 2;
} else if(cpnt[0] == '.' && cpnt[1] == 0){
if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
Rock[ipnt++] = SL_CURRENT;
Rock[ipnt++] = 0; /* length is zero */
lenval += 2;
nchar -= 1;
} else if(cpnt[0] == 0){
if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
Rock[ipnt++] = SL_ROOT;
Rock[ipnt++] = 0; /* length is zero */
lenval += 2;
} else {
/* If we do not have enough room for a component, start
a new continuations segment now */
if(MAYBE_ADD_CE_ENTRY(6)) {
add_CE_entry();
if(cpnt1){
*cpnt1 = '/';
cpnt1 = NULL; /* A kluge so that we can restart properly */
}
break;
}
j0 = strlen((char *) cpnt);
while(j0) {
j1 = j0;
if(j1 > 0xf8) j1 = 0xf8;
need_ce = 0;
if(j1 + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
j1 = reclimit - currlen - CE_SIZE - (ipnt - recstart);
need_ce++;
}
Rock[ipnt++] = (j1 != j0 ? SL_CONTINUE : 0);
Rock[ipnt++] = j1;
strncpy((char *) Rock + ipnt, (char *) cpnt, j1);
ipnt += j1;
lenval += j1 + 2;
cpnt += j1;
nchar -= j1; /* Number we processed this time */
j0 -= j1;
if(need_ce) {
add_CE_entry();
if(cpnt1) {
*cpnt1 = '/';
cpnt1 = NULL; /* A kluge so that we can restart properly */
}
break;
}
}
};
if(cpnt1) {
cpnt = cpnt1 + 1;
} else
break;
};
Rock[lenpos] = lenval;
if(nchar) Rock[lenpos + 2] = SL_CONTINUE; /* We need another SL entry */
} /* while nchar */
} /* Is a symbolic link */
/*
* Add in the Rock Ridge TF time field
*/
if(MAYBE_ADD_CE_ENTRY(TF_SIZE)) add_CE_entry();
Rock[ipnt++] ='T';
Rock[ipnt++] ='F';
Rock[ipnt++] = TF_SIZE;
Rock[ipnt++] = SU_VERSION;
#ifdef __QNX__
Rock[ipnt++] = 0x0f;
#else
Rock[ipnt++] = 0x0e;
#endif
flagval |= (1<<7);
#ifdef __QNX__
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime);
ipnt += 7;
#endif
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime);
ipnt += 7;
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime);
ipnt += 7;
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime);
ipnt += 7;
/*
* Add in the Rock Ridge RE time field
*/
if(deep_opt & NEED_RE){
if(MAYBE_ADD_CE_ENTRY(RE_SIZE)) add_CE_entry();
Rock[ipnt++] ='R';
Rock[ipnt++] ='E';
Rock[ipnt++] = RE_SIZE;
Rock[ipnt++] = SU_VERSION;
flagval |= (1<<6);
};
/*
* Add in the Rock Ridge PL record, if required.
*/
if(deep_opt & NEED_PL){
if(MAYBE_ADD_CE_ENTRY(PL_SIZE)) add_CE_entry();
Rock[ipnt++] ='P';
Rock[ipnt++] ='L';
Rock[ipnt++] = PL_SIZE;
Rock[ipnt++] = SU_VERSION;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
flagval |= (1<<5);
};
/*
* Add in the Rock Ridge CL field, if required.
*/
if(deep_opt & NEED_CL){
if(MAYBE_ADD_CE_ENTRY(CL_SIZE)) add_CE_entry();
Rock[ipnt++] ='C';
Rock[ipnt++] ='L';
Rock[ipnt++] = CL_SIZE;
Rock[ipnt++] = SU_VERSION;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
flagval |= (1<<4);
};
#ifndef VMS
/* If transparent compression was requested, fill in the correct
field for this file */
if(transparent_compression &&
S_ISREG(lstatbuf->st_mode) &&
strlen(name) > 3 &&
strcmp(name + strlen(name) - 3,".gZ") == 0){
FILE * zipfile;
char * checkname;
unsigned int file_size;
unsigned char header[8];
int OK_flag;
/* First open file and verify that the correct algorithm was used */
file_size = 0;
OK_flag = 1;
zipfile = fopen(whole_name, "r");
fread(header, 1, sizeof(header), zipfile);
/* Check some magic numbers from gzip. */
if(header[0] != 0x1f || header[1] != 0x8b || header[2] != 8) OK_flag = 0;
/* Make sure file was blocksized. */
if((header[3] & 0x40 == 0)) OK_flag = 0;
/* OK, now go to the end of the file and get some more info */
if(OK_flag){
int status;
status = (long)lseek(fileno(zipfile), (off_t)(-8), SEEK_END);
if(status == -1) OK_flag = 0;
}
if(OK_flag){
if(read(fileno(zipfile), (char*)header, sizeof(header)) != sizeof(header))
OK_flag = 0;
else {
int blocksize;
blocksize = (header[3] << 8) | header[2];
file_size = ((unsigned int)header[7] << 24) |
((unsigned int)header[6] << 16) |
((unsigned int)header[5] << 8) | header[4];
#if 0
fprintf(stderr,"Blocksize = %d %d\n", blocksize, file_size);
#endif
if(blocksize != SECTOR_SIZE) OK_flag = 0;
}
}
fclose(zipfile);
checkname = strdup(whole_name);
checkname[strlen(whole_name)-3] = 0;
zipfile = fopen(checkname, "r");
if(zipfile) {
OK_flag = 0;
fprintf(stderr,"Unable to insert transparent compressed file - name conflict\n");
fclose(zipfile);
}
free(checkname);
if(OK_flag){
if(MAYBE_ADD_CE_ENTRY(ZZ_SIZE)) add_CE_entry();
Rock[ipnt++] ='Z';
Rock[ipnt++] ='Z';
Rock[ipnt++] = ZZ_SIZE;
Rock[ipnt++] = SU_VERSION;
Rock[ipnt++] = 'g'; /* Identify compression technique used */
Rock[ipnt++] = 'z';
Rock[ipnt++] = 3;
set_733((char*)Rock + ipnt, file_size); /* Real file size */
ipnt += 8;
};
}
#endif
/*
* Add in the Rock Ridge CE field, if required. We use this for the
* extension record that is stored in the root directory.
*/
if(deep_opt & NEED_CE) add_CE_entry();
/*
* Done filling in all of the fields. Now copy it back to a buffer for the
* file in question.
*/
/* Now copy this back to the buffer for the file */
Rock[flagpos] = flagval;
/* If there was a CE, fill in the size field */
if(recstart)
set_733((char*)Rock + recstart - 8, ipnt - recstart);
s_entry->rr_attributes = (unsigned char *) e_malloc(ipnt);
s_entry->total_rr_attr_size = ipnt;
s_entry->rr_attr_size = (mainrec ? mainrec : ipnt);
memcpy(s_entry->rr_attributes, Rock, ipnt);
return ipnt;
}
/* Guaranteed to return a single sector with the relevant info */
char * FDECL4(generate_rr_extension_record, char *, id, char *, descriptor,
char *, source, int *, size){
int ipnt = 0;
char * pnt;
int len_id, len_des, len_src;
len_id = strlen(id);
len_des = strlen(descriptor);
len_src = strlen(source);
Rock[ipnt++] ='E';
Rock[ipnt++] ='R';
Rock[ipnt++] = ER_SIZE + len_id + len_des + len_src;
Rock[ipnt++] = 1;
Rock[ipnt++] = len_id;
Rock[ipnt++] = len_des;
Rock[ipnt++] = len_src;
Rock[ipnt++] = 1;
memcpy(Rock + ipnt, id, len_id);
ipnt += len_id;
memcpy(Rock + ipnt, descriptor, len_des);
ipnt += len_des;
memcpy(Rock + ipnt, source, len_src);
ipnt += len_src;
if(ipnt > SECTOR_SIZE) {
fprintf(stderr,"Extension record too long\n");
exit(1);
};
pnt = (char *) e_malloc(SECTOR_SIZE);
memset(pnt, 0, SECTOR_SIZE);
memcpy(pnt, Rock, ipnt);
*size = ipnt;
return pnt;
}

889
gnu/usr.bin/mkisofs/tree.c Normal file
View File

@ -0,0 +1,889 @@
/*
* File tree.c - scan directory tree and build memory structures for iso9660
* filesystem
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#ifndef VMS
#include <unistd.h>
#ifdef HASSYSMACROS
#include <sys/sysmacros.h>
#endif
#else
#include <sys/file.h>
#include <vms/fabdef.h>
#include "vms.h"
extern char * strdup(const char *);
#endif
#include "mkisofs.h"
#include "iso9660.h"
#include <sys/stat.h>
#include "exclude.h"
#ifdef NON_UNIXFS
#define S_ISLNK(m) (0)
#define S_ISSOCK(m) (0)
#define S_ISFIFO(m) (0)
#else
#ifndef S_ISLNK
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
#ifndef S_ISSOCK
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#endif
#endif
#ifdef __svr4__
extern char * strdup(const char *);
#endif
static unsigned char symlink_buff[256];
extern int verbose;
struct stat fstatbuf = {0,}; /* We use this for the artificial entries we create */
struct stat root_statbuf = {0, }; /* Stat buffer for root directory */
struct directory * reloc_dir = NULL;
void FDECL1(sort_n_finish, struct directory *, this_dir)
{
struct directory_entry *s_entry, *s_entry1;
time_t current_time;
struct directory_entry * table;
int count;
int new_reclen;
char * c;
int tablesize = 0;
char newname[34], rootname[34];
/* Here we can take the opportunity to toss duplicate entries from the
directory. */
table = NULL;
if(fstatbuf.st_ctime == 0){
time (&current_time);
fstatbuf.st_uid = 0;
fstatbuf.st_gid = 0;
fstatbuf.st_ctime = current_time;
fstatbuf.st_mtime = current_time;
fstatbuf.st_atime = current_time;
};
flush_file_hash();
s_entry = this_dir->contents;
while(s_entry){
/* First assume no conflict, and handle this case */
if(!(s_entry1 = find_file_hash(s_entry->isorec.name))){
add_file_hash(s_entry);
s_entry = s_entry->next;
continue;
};
if(s_entry1 == s_entry){
fprintf(stderr,"Fatal goof\n");
exit(1);
};
/* OK, handle the conflicts. Try substitute names until we come
up with a winner */
strcpy(rootname, s_entry->isorec.name);
if(full_iso9660_filenames) {
if(strlen(rootname) > 27) rootname[27] = 0;
}
c = strchr(rootname, '.');
if (c) *c = 0;
count = 0;
while(count < 1000){
sprintf(newname,"%s.%3.3d%s", rootname, count,
(s_entry->isorec.flags[0] == 2 ||
omit_version_number ? "" : ";1"));
#ifdef VMS
/* Sigh. VAXCRTL seems to be broken here */
{ int ijk = 0;
while(newname[ijk]) {
if(newname[ijk] == ' ') newname[ijk] = '0';
ijk++;
};
}
#endif
if(!find_file_hash(newname)) break;
count++;
};
if(count >= 1000){
fprintf(stderr,"Unable to generate unique name for file %s\n", s_entry->name);
exit(1);
};
/* OK, now we have a good replacement name. Now decide which one
of these two beasts should get the name changed */
if(s_entry->priority < s_entry1->priority) {
fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, this_dir->whole_name, SPATH_SEPARATOR, s_entry->name, s_entry1->name);
s_entry->isorec.name_len[0] = strlen(newname);
new_reclen = sizeof(struct iso_directory_record) -
sizeof(s_entry->isorec.name) +
strlen(newname);
if(use_RockRidge) {
if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
new_reclen += s_entry->rr_attr_size;
};
if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
s_entry->isorec.length[0] = new_reclen;
strcpy(s_entry->isorec.name, newname);
} else {
delete_file_hash(s_entry1);
fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, this_dir->whole_name, SPATH_SEPARATOR, s_entry1->name, s_entry->name);
s_entry1->isorec.name_len[0] = strlen(newname);
new_reclen = sizeof(struct iso_directory_record) -
sizeof(s_entry1->isorec.name) +
strlen(newname);
if(use_RockRidge) {
if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
new_reclen += s_entry1->rr_attr_size;
};
if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
s_entry1->isorec.length[0] = new_reclen;
strcpy(s_entry1->isorec.name, newname);
add_file_hash(s_entry1);
};
add_file_hash(s_entry);
s_entry = s_entry->next;
};
if(generate_tables && !find_file_hash("TRANS.TBL") && (reloc_dir != this_dir)){
/* First we need to figure out how big this table is */
for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
if(strcmp(s_entry->name, ".") == 0 ||
strcmp(s_entry->name, "..") == 0) continue;
if(s_entry->table) tablesize += 35 + strlen(s_entry->table);
};
table = (struct directory_entry *)
e_malloc(sizeof (struct directory_entry));
memset(table, 0, sizeof(struct directory_entry));
table->table = NULL;
table->next = this_dir->contents;
this_dir->contents = table;
table->filedir = root;
table->isorec.flags[0] = 0;
table->priority = 32768;
iso9660_date(table->isorec.date, fstatbuf.st_ctime);
table->inode = TABLE_INODE;
table->dev = (dev_t) UNCACHED_DEVICE;
set_723(table->isorec.volume_sequence_number, 1);
set_733(table->isorec.size, tablesize);
table->size = tablesize;
table->filedir = this_dir;
table->name = strdup("<translation table>");
table->table = (char *) e_malloc(ROUND_UP(tablesize));
memset(table->table, 0, ROUND_UP(tablesize));
iso9660_file_length ("TRANS.TBL", table, 1);
if(use_RockRidge){
fstatbuf.st_mode = 0444 | S_IFREG;
fstatbuf.st_nlink = 1;
generate_rock_ridge_attributes("",
"TRANS.TBL", table,
&fstatbuf, &fstatbuf, 0);
};
};
for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
new_reclen = strlen(s_entry->isorec.name);
if(s_entry->isorec.flags[0] == 2){
if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) {
path_table_size += new_reclen + sizeof(struct iso_path_table) - 1;
if (new_reclen & 1) path_table_size++;
} else {
new_reclen = 1;
if (this_dir == root && strlen(s_entry->name) == 1)
path_table_size += sizeof(struct iso_path_table);
}
};
if(path_table_size & 1) path_table_size++; /* For odd lengths we pad */
s_entry->isorec.name_len[0] = new_reclen;
new_reclen +=
sizeof(struct iso_directory_record) -
sizeof(s_entry->isorec.name);
if (new_reclen & 1)
new_reclen++;
if(use_RockRidge){
new_reclen += s_entry->rr_attr_size;
if (new_reclen & 1)
new_reclen++;
};
if(new_reclen > 0xff) {
fprintf(stderr,"Fatal error - RR overflow for file %s\n",
s_entry->name);
exit(1);
};
s_entry->isorec.length[0] = new_reclen;
};
sort_directory(&this_dir->contents);
if(table){
char buffer[1024];
count = 0;
for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
if(s_entry == table) continue;
if(!s_entry->table) continue;
if(strcmp(s_entry->name, ".") == 0 ||
strcmp(s_entry->name, "..") == 0) continue;
sprintf(buffer,"%c %-34s%s",s_entry->table[0],
s_entry->isorec.name, s_entry->table+1);
memcpy(table->table + count, buffer, strlen(buffer));
count += strlen(buffer);
free(s_entry->table);
s_entry->table = NULL;
};
if(count != tablesize) {
fprintf(stderr,"Translation table size mismatch %d %d\n",
count, tablesize);
exit(1);
};
};
/* Now go through the directory and figure out how large this one will be.
Do not split a directory entry across a sector boundary */
s_entry = this_dir->contents;
this_dir->ce_bytes = 0;
while(s_entry){
new_reclen = s_entry->isorec.length[0];
if ((this_dir->size & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE)
this_dir->size = (this_dir->size + (SECTOR_SIZE - 1)) &
~(SECTOR_SIZE - 1);
this_dir->size += new_reclen;
/* See if continuation entries were used on disc */
if(use_RockRidge &&
s_entry->rr_attr_size != s_entry->total_rr_attr_size) {
unsigned char * pnt;
int len;
int nbytes;
pnt = s_entry->rr_attributes;
len = s_entry->total_rr_attr_size;
/* We make sure that each continuation entry record is not
split across sectors, but each file could in theory have more
than one CE, so we scan through and figure out what we need. */
while(len > 3){
if(pnt[0] == 'C' && pnt[1] == 'E') {
nbytes = get_733(pnt+20);
if((this_dir->ce_bytes & (SECTOR_SIZE - 1)) + nbytes >=
SECTOR_SIZE) this_dir->ce_bytes =
ROUND_UP(this_dir->ce_bytes);
/* Now store the block in the ce buffer */
this_dir->ce_bytes += nbytes;
if(this_dir->ce_bytes & 1) this_dir->ce_bytes++;
};
len -= pnt[2];
pnt += pnt[2];
}
}
s_entry = s_entry->next;
}
}
static void generate_reloc_directory()
{
int new_reclen;
time_t current_time;
struct directory_entry *s_entry;
/* Create an entry for our internal tree */
time (&current_time);
reloc_dir = (struct directory *)
e_malloc(sizeof(struct directory));
memset(reloc_dir, 0, sizeof(struct directory));
reloc_dir->parent = root;
reloc_dir->next = root->subdir;
root->subdir = reloc_dir;
reloc_dir->depth = 1;
reloc_dir->whole_name = strdup("./rr_moved");
reloc_dir->de_name = strdup("rr_moved");
reloc_dir->extent = 0;
new_reclen = strlen(reloc_dir->de_name);
/* Now create an actual directory entry */
s_entry = (struct directory_entry *)
e_malloc(sizeof (struct directory_entry));
memset(s_entry, 0, sizeof(struct directory_entry));
s_entry->next = root->contents;
reloc_dir->self = s_entry;
root->contents = s_entry;
root->contents->name = strdup(reloc_dir->de_name);
root->contents->filedir = root;
root->contents->isorec.flags[0] = 2;
root->contents->priority = 32768;
iso9660_date(root->contents->isorec.date, current_time);
root->contents->inode = UNCACHED_INODE;
root->contents->dev = (dev_t) UNCACHED_DEVICE;
set_723(root->contents->isorec.volume_sequence_number, 1);
iso9660_file_length (reloc_dir->de_name, root->contents, 1);
if(use_RockRidge){
fstatbuf.st_mode = 0555 | S_IFDIR;
fstatbuf.st_nlink = 2;
generate_rock_ridge_attributes("",
"rr_moved", s_entry,
&fstatbuf, &fstatbuf, 0);
};
/* Now create the . and .. entries in rr_moved */
/* Now create an actual directory entry */
s_entry = (struct directory_entry *)
e_malloc(sizeof (struct directory_entry));
memcpy(s_entry, root->contents,
sizeof(struct directory_entry));
s_entry->name = strdup(".");
iso9660_file_length (".", s_entry, 1);
s_entry->filedir = reloc_dir;
reloc_dir->contents = s_entry;
if(use_RockRidge){
fstatbuf.st_mode = 0555 | S_IFDIR;
fstatbuf.st_nlink = 2;
generate_rock_ridge_attributes("",
".", s_entry,
&fstatbuf, &fstatbuf, 0);
};
s_entry = (struct directory_entry *)
e_malloc(sizeof (struct directory_entry));
memcpy(s_entry, root->contents,
sizeof(struct directory_entry));
s_entry->name = strdup("..");
iso9660_file_length ("..", s_entry, 1);
s_entry->filedir = root;
reloc_dir->contents->next = s_entry;
reloc_dir->contents->next->next = NULL;
if(use_RockRidge){
fstatbuf.st_mode = 0555 | S_IFDIR;
fstatbuf.st_nlink = 2;
generate_rock_ridge_attributes("",
"..", s_entry,
&root_statbuf, &root_statbuf, 0);
};
}
static void FDECL1(increment_nlink, struct directory_entry *, s_entry){
unsigned char * pnt;
int len, nlink;
pnt = s_entry->rr_attributes;
len = s_entry->total_rr_attr_size;
while(len){
if(pnt[0] == 'P' && pnt[1] == 'X') {
nlink = get_733(pnt+12);
set_733(pnt+12, nlink+1);
break;
};
len -= pnt[2];
pnt += pnt[2];
};
}
void finish_cl_pl_entries(){
struct directory_entry *s_entry, *s_entry1;
struct directory * d_entry;
s_entry = reloc_dir->contents;
s_entry = s_entry->next->next; /* Skip past . and .. */
for(; s_entry; s_entry = s_entry->next){
d_entry = reloc_dir->subdir;
while(d_entry){
if(d_entry->self == s_entry) break;
d_entry = d_entry->next;
};
if(!d_entry){
fprintf(stderr,"Unable to locate directory parent\n");
exit(1);
};
/* First fix the PL pointer in the directory in the rr_reloc dir */
s_entry1 = d_entry->contents->next;
set_733(s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8,
s_entry->filedir->extent);
/* Now fix the CL pointer */
s_entry1 = s_entry->parent_rec;
set_733(s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8,
d_entry->extent);
s_entry->filedir = reloc_dir; /* Now we can fix this */
}
/* Next we need to modify the NLINK terms in the assorted root directory records
to account for the presence of the RR_MOVED directory */
increment_nlink(root->self);
increment_nlink(root->self->next);
d_entry = root->subdir;
while(d_entry){
increment_nlink(d_entry->contents->next);
d_entry = d_entry->next;
};
}
/*
* This function scans the directory tree, looking for files, and it makes
* note of everything that is found. We also begin to construct the ISO9660
* directory entries, so that we can determine how large each directory is.
*/
int
FDECL2(scan_directory_tree,char *, path, struct directory_entry *, de){
DIR * current_dir;
char whole_path[1024];
struct dirent * d_entry;
struct directory_entry *s_entry, *s_entry1;
struct directory * this_dir, *next_brother, *parent;
struct stat statbuf, lstatbuf;
int status, dflag;
char * cpnt;
int new_reclen;
int deep_flag;
current_dir = opendir(path);
d_entry = NULL;
/* Apparently NFS sometimes allows you to open the directory, but
then refuses to allow you to read the contents. Allow for this */
if(current_dir) d_entry = readdir(current_dir);
if(!current_dir || !d_entry) {
fprintf(stderr,"Unable to open directory %s\n", path);
de->isorec.flags[0] &= ~2; /* Mark as not a directory */
if(current_dir) closedir(current_dir);
return 0;
};
parent = de->filedir;
/* Set up the struct for the current directory, and insert it into the
tree */
#ifdef VMS
vms_path_fixup(path);
#endif
this_dir = (struct directory *) e_malloc(sizeof(struct directory));
this_dir->next = NULL;
new_reclen = 0;
this_dir->subdir = NULL;
this_dir->self = de;
this_dir->contents = NULL;
this_dir->whole_name = strdup(path);
cpnt = strrchr(path, PATH_SEPARATOR);
if(cpnt)
cpnt++;
else
cpnt = path;
this_dir->de_name = strdup(cpnt);
this_dir->size = 0;
this_dir->extent = 0;
if(!parent || parent == root){
if (!root) {
root = this_dir; /* First time through for root directory only */
root->depth = 0;
root->parent = root;
} else {
this_dir->depth = 1;
if(!root->subdir)
root->subdir = this_dir;
else {
next_brother = root->subdir;
while(next_brother->next) next_brother = next_brother->next;
next_brother->next = this_dir;
};
this_dir->parent = parent;
};
} else {
/* Come through here for normal traversal of tree */
#ifdef DEBUG
fprintf(stderr,"%s(%d) ", path, this_dir->depth);
#endif
if(parent->depth > RR_relocation_depth) {
fprintf(stderr,"Directories too deep %s\n", path);
exit(1);
};
this_dir->parent = parent;
this_dir->depth = parent->depth + 1;
if(!parent->subdir)
parent->subdir = this_dir;
else {
next_brother = parent->subdir;
while(next_brother->next) next_brother = next_brother->next;
next_brother->next = this_dir;
};
};
/* Now we scan the directory itself, and look at what is inside of it. */
dflag = 0;
while(1==1){
/* The first time through, skip this, since we already asked for
the first entry when we opened the directory. */
if(dflag) d_entry = readdir(current_dir);
dflag++;
if(!d_entry) break;
/* OK, got a valid entry */
/* If we do not want all files, then pitch the backups. */
if(!all_files){
if(strchr(d_entry->d_name,'~')) continue;
if(strchr(d_entry->d_name,'#')) continue;
};
if(strlen(path)+strlen(d_entry->d_name) + 2 > sizeof(whole_path)){
fprintf(stderr, "Overflow of stat buffer\n");
exit(1);
};
/* Generate the complete ASCII path for this file */
strcpy(whole_path, path);
#ifndef VMS
if(whole_path[strlen(whole_path)-1] != '/')
strcat(whole_path, "/");
#endif
strcat(whole_path, d_entry->d_name);
/* Should we exclude this file? */
if (is_excluded(whole_path)) {
if (verbose) {
fprintf(stderr, "Excluded: %s\n",whole_path);
}
continue;
}
#if 0
if (verbose) fprintf(stderr, "%s\n",whole_path);
#endif
status = stat(whole_path, &statbuf);
lstat(whole_path, &lstatbuf);
if(this_dir == root && strcmp(d_entry->d_name, ".") == 0)
root_statbuf = statbuf; /* Save this for later on */
/* We do this to make sure that the root entries are consistent */
if(this_dir == root && strcmp(d_entry->d_name, "..") == 0) {
statbuf = root_statbuf;
lstatbuf = root_statbuf;
};
if(S_ISLNK(lstatbuf.st_mode)){
/* Here we decide how to handle the symbolic links. Here we
handle the general case - if we are not following links or there is an
error, then we must change something. If RR is in use, it is easy, we
let RR describe the file. If not, then we punt the file. */
if((status || !follow_links)){
if(use_RockRidge){
status = 0;
statbuf.st_size = 0;
STAT_INODE(statbuf) = UNCACHED_INODE;
statbuf.st_dev = (dev_t) UNCACHED_DEVICE;
statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG;
} else {
if(follow_links) fprintf(stderr,
"Unable to stat file %s - ignoring and continuing.\n",
whole_path);
else fprintf(stderr,
"Symlink %s ignored - continuing.\n",
whole_path);
continue; /* Non Rock Ridge discs - ignore all symlinks */
};
}
/* Here we handle a different kind of case. Here we have a symlink,
but we want to follow symlinks. If we run across a directory loop,
then we need to pretend that we are not following symlinks for this file.
If this is the first time we have seen this, then make this seem
as if there was no symlink there in the first place */
else if(strcmp(d_entry->d_name, ".") &&
strcmp(d_entry->d_name, "..")) {
if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))){
fprintf(stderr, "Infinite loop detected (%s)\n", whole_path);
if(!use_RockRidge) continue;
statbuf.st_size = 0;
STAT_INODE(statbuf) = UNCACHED_INODE;
statbuf.st_dev = (dev_t) UNCACHED_DEVICE;
statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG;
} else {
lstatbuf = statbuf;
add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
};
};
};
#ifdef VMS
if(!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX &&
statbuf.st_fab_rfm != FAB$C_STMLF)) {
fprintf(stderr,"Warning - file %s has an unsupported VMS record"
" format (%d)\n",
whole_path, statbuf.st_fab_rfm);
};
#endif
if(S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK))){
fprintf(stderr, "File %s is not readable (errno = %d) - ignoring\n",
whole_path, errno);
continue;
}
/* Add this so that we can detect directory loops with hard links.
If we are set up to follow symlinks, then we skip this checking. */
if(!follow_links && S_ISDIR(lstatbuf.st_mode) && strcmp(d_entry->d_name, ".") &&
strcmp(d_entry->d_name, "..")) {
if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) {
fprintf(stderr,"Directory loop - fatal goof (%s %x %d).\n",
whole_path, statbuf.st_dev, STAT_INODE(statbuf));
exit(1);
};
add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
};
if (!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) &&
!S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode)
&& !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) &&
!S_ISDIR(lstatbuf.st_mode)) {
fprintf(stderr,"Unknown file type %s - ignoring and continuing.\n",
whole_path);
continue;
};
/* Who knows what trash this is - ignore and continue */
if(status) {
fprintf(stderr,
"Unable to stat file %s - ignoring and continuing.\n",
whole_path);
continue;
};
s_entry = (struct directory_entry *)
e_malloc(sizeof (struct directory_entry));
s_entry->next = this_dir->contents;
this_dir->contents = s_entry;
deep_flag = 0;
s_entry->table = NULL;
s_entry->name = strdup(d_entry->d_name);
s_entry->filedir = this_dir;
s_entry->isorec.flags[0] = 0;
s_entry->isorec.ext_attr_length[0] = 0;
iso9660_date(s_entry->isorec.date, statbuf.st_ctime);
s_entry->isorec.file_unit_size[0] = 0;
s_entry->isorec.interleave[0] = 0;
if(parent && parent == reloc_dir && strcmp(d_entry->d_name, "..") == 0){
s_entry->inode = UNCACHED_INODE;
s_entry->dev = (dev_t) UNCACHED_DEVICE;
deep_flag = NEED_PL;
} else {
s_entry->inode = STAT_INODE(statbuf);
s_entry->dev = statbuf.st_dev;
};
set_723(s_entry->isorec.volume_sequence_number, 1);
iso9660_file_length(d_entry->d_name, s_entry, S_ISDIR(statbuf.st_mode));
s_entry->rr_attr_size = 0;
s_entry->total_rr_attr_size = 0;
s_entry->rr_attributes = NULL;
/* Directories are assigned sizes later on */
if (!S_ISDIR(statbuf.st_mode)) {
set_733(s_entry->isorec.size, statbuf.st_size);
if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) ||
S_ISFIFO(lstatbuf.st_mode) || S_ISSOCK(lstatbuf.st_mode)
|| S_ISLNK(lstatbuf.st_mode))
s_entry->size = 0;
else
s_entry->size = statbuf.st_size;
} else
s_entry->isorec.flags[0] = 2;
if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..") &&
S_ISDIR(statbuf.st_mode) && this_dir->depth > RR_relocation_depth){
if(!reloc_dir) generate_reloc_directory();
s_entry1 = (struct directory_entry *)
e_malloc(sizeof (struct directory_entry));
memcpy(s_entry1, this_dir->contents,
sizeof(struct directory_entry));
s_entry1->table = NULL;
s_entry1->name = strdup(this_dir->contents->name);
s_entry1->next = reloc_dir->contents;
reloc_dir->contents = s_entry1;
s_entry1->priority = 32768;
s_entry1->parent_rec = this_dir->contents;
deep_flag = NEED_RE;
if(use_RockRidge) {
generate_rock_ridge_attributes(whole_path,
d_entry->d_name, s_entry1,
&statbuf, &lstatbuf, deep_flag);
};
deep_flag = 0;
/* We need to set this temporarily so that the parent to this is correctly
determined. */
s_entry1->filedir = reloc_dir;
scan_directory_tree(whole_path, s_entry1);
s_entry1->filedir = this_dir;
statbuf.st_size = 0;
statbuf.st_mode &= 0777;
set_733(s_entry->isorec.size, 0);
s_entry->size = 0;
s_entry->isorec.flags[0] = 0;
s_entry->inode = UNCACHED_INODE;
deep_flag = NEED_CL;
};
if(generate_tables && strcmp(s_entry->name, ".") && strcmp(s_entry->name, "..")) {
char buffer[2048];
switch(lstatbuf.st_mode & S_IFMT){
case S_IFDIR:
sprintf(buffer,"D\t%s\n",
s_entry->name);
break;
#ifndef NON_UNIXFS
case S_IFBLK:
sprintf(buffer,"B\t%s\t%d %d\n",
s_entry->name,
major(statbuf.st_rdev), minor(statbuf.st_rdev));
break;
case S_IFIFO:
sprintf(buffer,"P\t%s\n",
s_entry->name);
break;
case S_IFCHR:
sprintf(buffer,"C\t%s\t%d %d\n",
s_entry->name,
major(statbuf.st_rdev), minor(statbuf.st_rdev));
break;
case S_IFLNK:
readlink(whole_path, symlink_buff, sizeof(symlink_buff));
sprintf(buffer,"L\t%s\t%s\n",
s_entry->name, symlink_buff);
break;
case S_IFSOCK:
sprintf(buffer,"S\t%s\n",
s_entry->name);
break;
#endif /* NON_UNIXFS */
case S_IFREG:
default:
sprintf(buffer,"F\t%s\n",
s_entry->name);
break;
};
s_entry->table = strdup(buffer);
};
if(S_ISDIR(statbuf.st_mode)){
int dflag;
if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..")) {
dflag = scan_directory_tree(whole_path, s_entry);
/* If unable to scan directory, mark this as a non-directory */
if(!dflag)
lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
}
};
if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".") == 0)
deep_flag |= NEED_CE | NEED_SP; /* For extension record */
/* Now figure out how much room this file will take in the directory */
if(use_RockRidge) {
generate_rock_ridge_attributes(whole_path,
d_entry->d_name, s_entry,
&statbuf, &lstatbuf, deep_flag);
}
}
closedir(current_dir);
sort_n_finish(this_dir);
return 1;
}
void FDECL2(generate_iso9660_directories, struct directory *, node, FILE*, outfile){
struct directory * dpnt;
dpnt = node;
while (dpnt){
generate_one_directory(dpnt, outfile);
if(dpnt->subdir) generate_iso9660_directories(dpnt->subdir, outfile);
dpnt = dpnt->next;
};
}
void FDECL1(dump_tree, struct directory *, node){
struct directory * dpnt;
dpnt = node;
while (dpnt){
fprintf(stderr,"%4d %5d %s\n",dpnt->extent, dpnt->size, dpnt->de_name);
if(dpnt->subdir) dump_tree(dpnt->subdir);
dpnt = dpnt->next;
};
}

269
gnu/usr.bin/mkisofs/vms.c Normal file
View File

@ -0,0 +1,269 @@
/*
* File vms.c - assorted bletcherous hacks for VMS.
Written by Eric Youngdale (1993).
*/
#ifdef VMS
#include <rms.h>
#include <descrip.h>
#include <ssdef.h>
#include <sys/types.h>
#include <sys/stat.h>
#define opendir fake_opendir
#include "mkisofs.h"
#undef opendir
#include <stdio.h>
static struct RAB *rab; /* used for external mailfiles */
static int rms_status;
static error_exit(char * text){
fprintf(stderr,"%s\n", text);
exit(33);
}
char * strrchr(const char *, char);
char * strdup(char * source){
char * pnt;
pnt = (char *) e_malloc(strlen(source) + 1);
strcpy(pnt, source);
return pnt;
}
int VMS_stat(char * path, struct stat * spnt){
char * spath;
char sbuffer[255];
char * pnt, *ppnt;
char * pnt1;
ppnt = strrchr(path,']');
if(ppnt) ppnt++;
else ppnt = path;
spath = path;
if(strcmp(ppnt,".") == 0 || strcmp(ppnt,"..") == 0){
strcpy(sbuffer, path);
/* Find end of actual name */
pnt = strrchr(sbuffer,']');
if(!pnt) return 0;
pnt1 = pnt;
while(*pnt1 != '[' && *pnt1 != '.') pnt1--;
if(*pnt1 != '[' && strcmp(ppnt,"..") == 0) {
pnt1--;
while(*pnt1 != '[' && *pnt1 != '.') pnt1--;
};
if(*pnt1 == '.') {
*pnt1 = ']';
pnt = pnt1;
while(*pnt != '.' && *pnt != ']') pnt++;
*pnt++ = ']';
while(*pnt != '.' && *pnt != ']') pnt++;
*pnt = 0;
strcat(sbuffer,".DIR;1");
};
if(*pnt1 == '[') {
pnt1++;
*pnt1 = 0;
strcat(pnt1,"000000]");
pnt1 = strrchr(path,'[') + 1;
pnt = sbuffer + strlen(sbuffer);
while(*pnt1 && *pnt1 != '.' && *pnt1 != ']') *pnt++ = *pnt1++;
*pnt = 0;
strcat(sbuffer,".DIR;1");
};
spath = sbuffer;
};
return stat(spath, spnt);
}
static int dircontext[32] = {0,};
static char * searchpath[32];
static struct direct d_entry[32];
int optind = 0;
char * optarg;
int getopt(int argc, char *argv[], char * flags){
char * pnt;
char c;
optind++;
if(*argv[optind] != '-') return EOF;
optarg = 0;
c = *(argv[optind]+1);
pnt = (char *) strchr(flags, c);
if(!pnt) return c; /* Not found */
if(pnt[1] == ':') {
optind++;
optarg = argv[optind];
};
return c;
}
void vms_path_fixup(char * name){
char * pnt1;
pnt1 = name + strlen(name) - 6;
/* First strip the .DIR;1 */
if(strcmp(pnt1, ".DIR;1") == 0) *pnt1 = 0;
pnt1 = (char*) strrchr(name, ']');
if(pnt1) {
if(pnt1[1] == 0) return;
*pnt1 = '.';
strcat(name,"]");
return;
};
pnt1 = (char*) strrchr(name, '>');
if(pnt1) {
if(pnt1[1] == 0) return;
*pnt1 = '.';
strcat(name,">");
return;
};
}
int opendir(char * path){
int i;
for(i=1; i<32; i++) {
if(dircontext[i] == 0){
dircontext[i] = -1;
searchpath[i] = (char *) e_malloc(strlen(path) + 6);
strcpy(searchpath[i], path);
vms_path_fixup(searchpath[i]);
strcat(searchpath[i],"*.*.*");
return i;
};
};
exit(0);
}
struct direct * readdir(int context){
int i;
char cresult[100];
char * pnt;
int status;
$DESCRIPTOR(dpath,searchpath[context]);
$DESCRIPTOR(result,cresult);
if(dircontext[context] == -1) {
dircontext[context] = -2;
strcpy(d_entry[context].d_name, ".");
return &d_entry[context];
};
if(dircontext[context] == -2) {
dircontext[context] = -3;
strcpy(d_entry[context].d_name, "..");
return &d_entry[context];
};
if(dircontext[context] == -3) dircontext[context] = 0;
dpath.dsc$w_length = strlen(searchpath[context]);
lib$find_file(&dpath, &result, &dircontext[context],
0, 0, &status, 0);
if(status == SS$_NOMOREFILES) return 0;
/* Now trim trailing spaces from the name */
i = result.dsc$w_length - 1;
while(i && cresult[i] == ' ') i--;
cresult[i+1] = 0;
/* Now locate the actual portion of the file we want */
pnt = (char *) strrchr(cresult,']');
if(pnt) pnt++;
else
pnt = cresult;
strcpy(d_entry[context].d_name, pnt);
return &d_entry[context];
}
void closedir(int context){
lib$find_file_end(&dircontext[context]);
free(searchpath[context]);
searchpath[context] = (char *) 0;
dircontext[context] = 0;
}
static open_file(char* fn){
/* this routine initializes a rab and fab required to get the
correct definition of the external data file used by mail */
struct FAB * fab;
rab = (struct RAB*) e_malloc(sizeof(struct RAB));
fab = (struct FAB*) e_malloc(sizeof(struct FAB));
*rab = cc$rms_rab; /* initialize RAB*/
rab->rab$l_fab = fab;
*fab = cc$rms_fab; /* initialize FAB*/
fab->fab$l_fna = fn;
fab->fab$b_fns = strlen(fn);
fab->fab$w_mrs = 512;
fab->fab$b_fac = FAB$M_BIO | FAB$M_GET;
fab->fab$b_org = FAB$C_SEQ;
fab->fab$b_rfm = FAB$C_FIX;
fab->fab$l_xab = (char*) 0;
rms_status = sys$open(rab->rab$l_fab);
if(rms_status != RMS$_NORMAL && rms_status != RMS$_CREATED)
error_exit("$OPEN");
rms_status = sys$connect(rab);
if(rms_status != RMS$_NORMAL)
error_exit("$CONNECT");
return 1;
}
static close_file(struct RAB * prab){
rms_status = sys$close(prab->rab$l_fab);
free(prab->rab$l_fab);
free(prab);
if(rms_status != RMS$_NORMAL)
error_exit("$CLOSE");
}
#define NSECT 16
extern unsigned int last_extent_written;
int vms_write_one_file(char * filename, int size, FILE * outfile){
int status, i;
char buffer[SECTOR_SIZE * NSECT];
int count;
int use;
int remain;
open_file(filename);
remain = size;
while(remain > 0){
use = (remain > SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain);
use = ROUND_UP(use); /* Round up to nearest sector boundary */
memset(buffer, 0, use);
rab->rab$l_ubf = buffer;
rab->rab$w_usz = sizeof(buffer);
status = sys$read(rab);
fwrite(buffer, 1, use, outfile);
last_extent_written += use/SECTOR_SIZE;
if((last_extent_written % 1000) < use/SECTOR_SIZE) fprintf(stderr,"%d..", last_extent_written);
remain -= use;
};
close_file(rab);
}
#endif

19
gnu/usr.bin/mkisofs/vms.h Normal file
View File

@ -0,0 +1,19 @@
/*
* Header file mkisofs.h - assorted structure definitions and typecasts.
Written by Eric Youngdale (1993).
*/
#ifdef VMS
#define stat(X,Y) VMS_stat(X,Y)
#define lstat VMS_stat
/* gmtime not available under VMS - make it look like we are in Greenwich */
#define gmtime localtime
#define S_ISBLK(X) (0)
#define S_ISCHR(X) (0)
#define S_ISREG(X) (((X) & S_IFMT) == S_IFREG)
#define S_ISDIR(X) (((X) & S_IFMT) == S_IFDIR)
#endif

781
gnu/usr.bin/mkisofs/write.c Normal file
View File

@ -0,0 +1,781 @@
/*
* Program write.c - dump memory structures to file for iso9660 filesystem.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <string.h>
#include <stdlib.h>
#include "mkisofs.h"
#include "iso9660.h"
#include <time.h>
#include <errno.h>
#ifdef __svr4__
extern char * strdup(const char *);
#endif
#ifdef VMS
extern char * strdup(const char *);
#endif
/* Max number of sectors we will write at one time */
#define NSECT 16
/* Counters for statistics */
static int table_size = 0;
static int total_dir_size = 0;
static int rockridge_size = 0;
static struct directory ** pathlist;
static next_path_index = 1;
/* Used to fill in some of the information in the volume descriptor. */
static struct tm *local;
/* Routines to actually write the disc. We write sequentially so that
we could write a tape, or write the disc directly */
#define FILL_SPACE(X) memset(vol_desc.X, ' ', sizeof(vol_desc.X))
void FDECL2(set_721, char *, pnt, unsigned int, i){
pnt[0] = i & 0xff;
pnt[1] = (i >> 8) & 0xff;
}
void FDECL2(set_722, char *, pnt, unsigned int, i){
pnt[0] = (i >> 8) & 0xff;
pnt[1] = i & 0xff;
}
void FDECL2(set_723, char *, pnt, unsigned int, i){
pnt[3] = pnt[0] = i & 0xff;
pnt[2] = pnt[1] = (i >> 8) & 0xff;
}
void FDECL2(set_731, char *, pnt, unsigned int, i){
pnt[0] = i & 0xff;
pnt[1] = (i >> 8) & 0xff;
pnt[2] = (i >> 16) & 0xff;
pnt[3] = (i >> 24) & 0xff;
}
void FDECL2(set_732, char *, pnt, unsigned int, i){
pnt[3] = i & 0xff;
pnt[2] = (i >> 8) & 0xff;
pnt[1] = (i >> 16) & 0xff;
pnt[0] = (i >> 24) & 0xff;
}
int FDECL1(get_733, char *, p){
return ((p[0] & 0xff)
| ((p[1] & 0xff) << 8)
| ((p[2] & 0xff) << 16)
| ((p[3] & 0xff) << 24));
}
void FDECL2(set_733, char *, pnt, unsigned int, i){
pnt[7] = pnt[0] = i & 0xff;
pnt[6] = pnt[1] = (i >> 8) & 0xff;
pnt[5] = pnt[2] = (i >> 16) & 0xff;
pnt[4] = pnt[3] = (i >> 24) & 0xff;
}
static FDECL4(xfwrite, void *, buffer, int, count, int, size, FILE *, file)
{
while(count) {
int got=fwrite(buffer,size,count,file);
if(got<=0) fprintf(stderr,"cannot fwrite %d*%d\n",size,count),exit(1);
count-=got,*(char**)&buffer+=size*got;
}
}
struct deferred_write{
struct deferred_write * next;
char * table;
unsigned int extent;
unsigned int size;
char * name;
};
static struct deferred_write * dw_head = NULL, * dw_tail = NULL;
static struct directory_entry * sort_dir;
unsigned int last_extent_written =0;
static struct iso_primary_descriptor vol_desc;
static path_table_index;
/* We recursively walk through all of the directories and assign extent
numbers to them. We have already assigned extent numbers to everything that
goes in front of them */
void FDECL1(assign_directory_addresses, struct directory *, node){
struct directory * dpnt;
int dir_size;
dpnt = node;
while (dpnt){
dpnt->extent = last_extent;
dpnt->path_index = next_path_index++;
dir_size = (dpnt->size + (SECTOR_SIZE - 1)) >> 11;
last_extent += dir_size;
/* Leave room for the CE entries for this directory. Keep them
close to the reference directory so that access will be quick. */
if(dpnt->ce_bytes)
last_extent += ROUND_UP(dpnt->ce_bytes) >> 11;
if(dpnt->subdir) assign_directory_addresses(dpnt->subdir);
dpnt = dpnt->next;
};
}
static void FDECL3(write_one_file, char *, filename, unsigned int, size, FILE *, outfile){
FILE * infile;
char buffer[SECTOR_SIZE * NSECT];
int use;
int remain;
if ((infile = fopen(filename, "rb")) == NULL) {
#ifdef sun
fprintf(stderr, "cannot open %s: (%d)\n", filename, errno);
#else
fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
#endif
exit(1);
}
remain = size;
while(remain > 0){
use = (remain > SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain);
use = ROUND_UP(use); /* Round up to nearest sector boundary */
memset(buffer, 0, use);
if (fread(buffer, 1, use, infile) == 0) {
fprintf(stderr,"cannot read from %s\n",filename);
exit(1);
}
xfwrite(buffer, 1, use, outfile);
last_extent_written += use/SECTOR_SIZE;
if((last_extent_written % 1000) < use/SECTOR_SIZE) fprintf(stderr,"%d..", last_extent_written);
remain -= use;
};
fclose(infile);
}
static void FDECL1(write_files, FILE *, outfile){
struct deferred_write * dwpnt, *dwnext;
dwpnt = dw_head;
while(dwpnt){
if(dwpnt->table) {
xfwrite(dwpnt->table, 1, ROUND_UP(dwpnt->size), outfile);
last_extent_written += ROUND_UP(dwpnt->size) / SECTOR_SIZE;
table_size += dwpnt->size;
/* fprintf(stderr,"Size %d ", dwpnt->size); */
free(dwpnt->table);
} else {
#ifdef VMS
vms_write_one_file(dwpnt->name, dwpnt->size, outfile);
#else
write_one_file(dwpnt->name, dwpnt->size, outfile);
#endif
free(dwpnt->name);
};
dwnext = dwpnt;
dwpnt = dwpnt->next;
free(dwnext);
};
}
#if 0
static void dump_filelist(){
struct deferred_write * dwpnt;
dwpnt = dw_head;
while(dwpnt){
fprintf(stderr, "File %s\n",dwpnt->name);
dwpnt = dwpnt->next;
};
fprintf(stderr,"\n");
};
#endif
int FDECL2(compare_dirs, const struct directory_entry **, r, const struct directory_entry **, l) {
char * rpnt, *lpnt;
rpnt = (*r)->isorec.name;
lpnt = (*l)->isorec.name;
while(*rpnt && *lpnt) {
if(*rpnt == ';' && *lpnt != ';') return -1;
if(*rpnt != ';' && *lpnt == ';') return 1;
if(*rpnt == ';' && *lpnt == ';') return 0;
if(*rpnt < *lpnt) return -1;
if(*rpnt > *lpnt) return 1;
rpnt++; lpnt++;
}
if(*rpnt) return 1;
if(*lpnt) return -1;
return 0;
}
void FDECL1(sort_directory, struct directory_entry **, sort_dir){
int dcount = 0;
int i, len;
struct directory_entry * s_entry;
struct directory_entry ** sortlist;
s_entry = *sort_dir;
while(s_entry){
dcount++;
s_entry = s_entry->next;
};
/* OK, now we know how many there are. Build a vector for sorting. */
sortlist = (struct directory_entry **)
e_malloc(sizeof(struct directory_entry *) * dcount);
dcount = 0;
s_entry = *sort_dir;
while(s_entry){
sortlist[dcount] = s_entry;
len = s_entry->isorec.name_len[0];
s_entry->isorec.name[len] = 0;
dcount++;
s_entry = s_entry->next;
};
qsort(sortlist, dcount, sizeof(struct directory_entry *), compare_dirs);
/* Now reassemble the linked list in the proper sorted order */
for(i=0; i<dcount-1; i++)
sortlist[i]->next = sortlist[i+1];
sortlist[dcount-1]->next = NULL;
*sort_dir = sortlist[0];
free(sortlist);
}
void generate_root_record(){
time_t ctime;
time (&ctime);
local = localtime(&ctime);
root_record.length[0] = 1 + sizeof(struct iso_directory_record);
root_record.ext_attr_length[0] = 0;
set_733(root_record.extent, root->extent);
set_733(root_record.size, ROUND_UP(root->size));
iso9660_date(root_record.date, ctime);
root_record.flags[0] = 2;
root_record.file_unit_size[0] = 0;
root_record.interleave[0] = 0;
set_723(root_record.volume_sequence_number, 1);
root_record.name_len[0] = 1;
}
static void FDECL1(assign_file_addresses, struct directory *, dpnt){
struct directory * finddir;
struct directory_entry * s_entry;
struct file_hash *s_hash;
struct deferred_write * dwpnt;
char whole_path[1024];
while (dpnt){
s_entry = dpnt->contents;
for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next){
/* This saves some space if there are symlinks present */
s_hash = find_hash(s_entry->dev, s_entry->inode);
if(s_hash){
if(verbose)
fprintf(stderr, "Cache hit for %s%s%s\n",s_entry->filedir->de_name,
SPATH_SEPARATOR, s_entry->name);
set_733(s_entry->isorec.extent, s_hash->starting_block);
set_733(s_entry->isorec.size, s_hash->size);
continue;
};
if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..") &&
s_entry->isorec.flags[0] == 2){
finddir = dpnt->subdir;
while(1==1){
if(finddir->self == s_entry) break;
finddir = finddir->next;
if(!finddir) {fprintf(stderr,"Fatal goof\n"); exit(1);};
};
set_733(s_entry->isorec.extent, finddir->extent);
s_entry->starting_block = finddir->extent;
s_entry->size = ROUND_UP(finddir->size);
total_dir_size += s_entry->size;
add_hash(s_entry);
set_733(s_entry->isorec.size, ROUND_UP(finddir->size));
} else {
if(strcmp(s_entry->name,".") ==0 || strcmp(s_entry->name,"..") == 0) {
if(strcmp(s_entry->name,".") == 0) {
set_733(s_entry->isorec.extent, dpnt->extent);
/* Set these so that the hash table has the correct information */
s_entry->starting_block = dpnt->extent;
s_entry->size = ROUND_UP(dpnt->size);
add_hash(s_entry);
s_entry->starting_block = dpnt->extent;
set_733(s_entry->isorec.size, ROUND_UP(dpnt->size));
} else {
if(dpnt == root) total_dir_size += root->size;
set_733(s_entry->isorec.extent, dpnt->parent->extent);
/* Set these so that the hash table has the correct information */
s_entry->starting_block = dpnt->parent->extent;
s_entry->size = ROUND_UP(dpnt->parent->size);
add_hash(s_entry);
s_entry->starting_block = dpnt->parent->extent;
set_733(s_entry->isorec.size, ROUND_UP(dpnt->parent->size));
};
} else {
/* Now we schedule the file to be written. This is all quite
straightforward, just make a list and assign extents as we go.
Once we get through writing all of the directories, we should
be ready write out these files */
if(s_entry->size) {
dwpnt = (struct deferred_write *)
e_malloc(sizeof(struct deferred_write));
if(dw_tail){
dw_tail->next = dwpnt;
dw_tail = dwpnt;
} else {
dw_head = dwpnt;
dw_tail = dwpnt;
};
if(s_entry->inode == TABLE_INODE) {
dwpnt->table = s_entry->table;
dwpnt->name = NULL;
} else {
dwpnt->table = NULL;
strcpy(whole_path, s_entry->filedir->whole_name);
#ifndef VMS
if(strlen(whole_path)) strcat(whole_path, "/");
#endif
strcat(whole_path, s_entry->name);
dwpnt->name = strdup(whole_path);
};
dwpnt->next = NULL;
dwpnt->size = s_entry->size;
dwpnt->extent = last_extent;
set_733(s_entry->isorec.extent, last_extent);
s_entry->starting_block = last_extent;
add_hash(s_entry);
last_extent += ROUND_UP(s_entry->size) >> 11;
if(verbose)
fprintf(stderr,"%d %d %s\n", s_entry->starting_block,
last_extent-1, whole_path);
#ifdef DBG_ISO
if((ROUND_UP(s_entry->size) >> 11) > 500){
fprintf(stderr,"Warning: large file %s\n", whole_path);
fprintf(stderr,"Starting block is %d\n", s_entry->starting_block);
fprintf(stderr,"Reported file size is %d extents\n", s_entry->size);
};
#endif
if(last_extent > (700000000 >> 11)) { /* More than 700Mb? Punt */
fprintf(stderr,"Extent overflow processing file %s\n", whole_path);
fprintf(stderr,"Starting block is %d\n", s_entry->starting_block);
fprintf(stderr,"Reported file size is %d extents\n", s_entry->size);
exit(1);
};
} else
set_733(s_entry->isorec.extent, 0);
};
};
};
if(dpnt->subdir) assign_file_addresses(dpnt->subdir);
dpnt = dpnt->next;
};
}
void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile){
unsigned int total_size, ce_size;
char * directory_buffer;
char * ce_buffer;
unsigned int ce_address;
struct directory_entry * s_entry, *s_entry_d;
int new_reclen;
unsigned int dir_index, ce_index;
total_size = (dpnt->size + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1);
directory_buffer = (char *) e_malloc(total_size);
memset(directory_buffer, 0, total_size);
dir_index = 0;
ce_size = (dpnt->ce_bytes + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1);
ce_buffer = NULL;
if(ce_size) {
ce_buffer = (char *) e_malloc(ce_size);
memset(ce_buffer, 0, ce_size);
ce_index = 0;
/* Absolute byte address of CE entries for this directory */
ce_address = last_extent_written + (total_size >> 11);
ce_address = ce_address << 11;
}
s_entry = dpnt->contents;
while(s_entry) {
/* We do not allow directory entries to cross sector boundaries. Simply
pad, and then start the next entry at the next sector */
new_reclen = s_entry->isorec.length[0];
if ((dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE)
dir_index = (dir_index + (SECTOR_SIZE - 1)) &
~(SECTOR_SIZE - 1);
memcpy(directory_buffer + dir_index, &s_entry->isorec,
sizeof(struct iso_directory_record) -
sizeof(s_entry->isorec.name) + s_entry->isorec.name_len[0]);
dir_index += sizeof(struct iso_directory_record) -
sizeof (s_entry->isorec.name)+ s_entry->isorec.name_len[0];
/* Add the Rock Ridge attributes, if present */
if(s_entry->rr_attr_size){
if(dir_index & 1)
directory_buffer[dir_index++] = 0;
/* If the RR attributes were too long, then write the CE records,
as required. */
if(s_entry->rr_attr_size != s_entry->total_rr_attr_size) {
unsigned char * pnt;
int len, nbytes;
/* Go through the entire record and fix up the CE entries
so that the extent and offset are correct */
pnt = s_entry->rr_attributes;
len = s_entry->total_rr_attr_size;
while(len > 3){
if(pnt[0] == 'C' && pnt[1] == 'E') {
nbytes = get_733(pnt+20);
if((ce_index & (SECTOR_SIZE - 1)) + nbytes >=
SECTOR_SIZE) ce_index = ROUND_UP(ce_index);
set_733(pnt+4, (ce_address + ce_index) >> 11);
set_733(pnt+12, (ce_address + ce_index) & (SECTOR_SIZE - 1));
/* Now store the block in the ce buffer */
memcpy(ce_buffer + ce_index,
pnt + pnt[2], nbytes);
ce_index += nbytes;
if(ce_index & 1) ce_index++;
};
len -= pnt[2];
pnt += pnt[2];
};
}
rockridge_size += s_entry->total_rr_attr_size;
memcpy(directory_buffer + dir_index, s_entry->rr_attributes,
s_entry->rr_attr_size);
dir_index += s_entry->rr_attr_size;
};
if(dir_index & 1)
directory_buffer[dir_index++] = 0;
s_entry_d = s_entry;
s_entry = s_entry->next;
if (s_entry_d->rr_attributes) free(s_entry_d->rr_attributes);
free (s_entry_d->name);
free (s_entry_d);
};
sort_dir = NULL;
if(dpnt->size != dir_index)
fprintf(stderr,"Unexpected directory length %d %d %s\n",dpnt->size,
dir_index, dpnt->de_name);
xfwrite(directory_buffer, 1, total_size, outfile);
last_extent_written += total_size >> 11;
free(directory_buffer);
if(ce_size){
if(ce_index != dpnt->ce_bytes)
fprintf(stderr,"Continuation entry record length mismatch (%d %d).\n",
ce_index, dpnt->ce_bytes);
xfwrite(ce_buffer, 1, ce_size, outfile);
last_extent_written += ce_size >> 11;
free(ce_buffer);
}
}
static void FDECL1(build_pathlist, struct directory *, node){
struct directory * dpnt;
dpnt = node;
while (dpnt){
pathlist[dpnt->path_index] = dpnt;
if(dpnt->subdir) build_pathlist(dpnt->subdir);
dpnt = dpnt->next;
};
}
int FDECL2(compare_paths, const struct directory **, r, const struct directory **, l) {
if((*r)->parent->path_index < (*l)->parent->path_index) return -1;
if((*r)->parent->path_index > (*l)->parent->path_index) return 1;
return strcmp((*r)->self->isorec.name, (*l)->self->isorec.name);
}
void generate_path_tables(){
struct directory * dpnt;
char * npnt, *npnt1;
int namelen;
struct directory_entry * de;
int fix;
int tablesize;
int i,j;
/* First allocate memory for the tables and initialize the memory */
tablesize = path_blocks << 11;
path_table_m = (char *) e_malloc(tablesize);
path_table_l = (char *) e_malloc(tablesize);
memset(path_table_l, 0, tablesize);
memset(path_table_m, 0, tablesize);
/* Now start filling in the path tables. Start with root directory */
path_table_index = 0;
pathlist = (struct directory **) e_malloc(sizeof(struct directory *) * next_path_index);
memset(pathlist, 0, sizeof(struct directory *) * next_path_index);
build_pathlist(root);
do{
fix = 0;
qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *), compare_paths);
for(j=1; j<next_path_index; j++)
if(pathlist[j]->path_index != j){
pathlist[j]->path_index = j;
fix++;
};
} while(fix);
for(j=1; j<next_path_index; j++){
dpnt = pathlist[j];
if(!dpnt){
fprintf(stderr,"Entry %d not in path tables\n", j);
exit(1);
};
npnt = dpnt->de_name;
if(*npnt == 0 || dpnt == root) npnt = "."; /* So the root comes out OK */
npnt1 = strrchr(npnt, PATH_SEPARATOR);
if(npnt1) npnt = npnt1 + 1;
de = dpnt->self;
if(!de) {fprintf(stderr,"Fatal goof\n"); exit(1);};
namelen = de->isorec.name_len[0];
path_table_l[path_table_index] = namelen;
path_table_m[path_table_index] = namelen;
path_table_index += 2;
set_731(path_table_l + path_table_index, dpnt->extent);
set_732(path_table_m + path_table_index, dpnt->extent);
path_table_index += 4;
set_721(path_table_l + path_table_index, dpnt->parent->path_index);
set_722(path_table_m + path_table_index, dpnt->parent->path_index);
path_table_index += 2;
for(i =0; i<namelen; i++){
path_table_l[path_table_index] = de->isorec.name[i];
path_table_m[path_table_index] = de->isorec.name[i];
path_table_index++;
};
if(path_table_index & 1) path_table_index++; /* For odd lengths we pad */
};
free(pathlist);
if(path_table_index != path_table_size)
fprintf(stderr,"Path table lengths do not match %d %d\n",path_table_index,
path_table_size);
}
int FDECL1(iso_write, FILE *, outfile){
char buffer[2048];
char iso_time[17];
int should_write;
int i;
assign_file_addresses(root);
memset(buffer, 0, sizeof(buffer));
/* This will break in the year 2000, I supose, but there is no good way
to get the top two digits of the year. */
sprintf(iso_time, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00", 1900 + local->tm_year,
local->tm_mon+1, local->tm_mday,
local->tm_hour, local->tm_min, local->tm_sec);
/* First, we output 16 sectors of all zero */
for(i=0; i<16; i++)
xfwrite(buffer, 1, sizeof(buffer), outfile);
last_extent_written += 16;
/* Next we write out the primary descriptor for the disc */
memset(&vol_desc, 0, sizeof(vol_desc));
vol_desc.type[0] = ISO_VD_PRIMARY;
memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
vol_desc.version[0] = 1;
memset(vol_desc.system_id, ' ', sizeof(vol_desc.system_id));
memcpy(vol_desc.system_id, system_id, strlen(system_id));
memset(vol_desc.volume_id, ' ', sizeof(vol_desc.volume_id));
memcpy(vol_desc.volume_id, volume_id, strlen(volume_id));
should_write = last_extent;
set_733(vol_desc.volume_space_size, last_extent);
set_723(vol_desc.volume_set_size, 1);
set_723(vol_desc.volume_sequence_number, 1);
set_723(vol_desc.logical_block_size, 2048);
/* The path tables are used by DOS based machines to cache directory
locations */
set_733(vol_desc.path_table_size, path_table_size);
set_731(vol_desc.type_l_path_table, path_table[0]);
set_731(vol_desc.opt_type_l_path_table, path_table[1]);
set_732(vol_desc.type_m_path_table, path_table[2]);
set_732(vol_desc.opt_type_m_path_table, path_table[3]);
/* Now we copy the actual root directory record */
memcpy(vol_desc.root_directory_record, &root_record,
sizeof(struct iso_directory_record) + 1);
/* The rest is just fluff. It looks nice to fill in many of these fields,
though */
FILL_SPACE(volume_set_id);
if(volset_id) memcpy(vol_desc.volume_set_id, volset_id, strlen(volset_id));
FILL_SPACE(publisher_id);
if(publisher) memcpy(vol_desc.publisher_id, publisher, strlen(publisher));
FILL_SPACE(preparer_id);
if(preparer) memcpy(vol_desc.preparer_id, preparer, strlen(preparer));
FILL_SPACE(application_id);
if(appid) memcpy(vol_desc.application_id, appid, strlen(appid));
FILL_SPACE(copyright_file_id);
if(appid) memcpy(vol_desc.copyright_file_id, appid, strlen(appid));
FILL_SPACE(abstract_file_id);
if(appid) memcpy(vol_desc.abstract_file_id, appid, strlen(appid));
FILL_SPACE(bibliographic_file_id);
if(appid) memcpy(vol_desc.bibliographic_file_id, appid, strlen(appid));
FILL_SPACE(creation_date);
FILL_SPACE(modification_date);
FILL_SPACE(expiration_date);
FILL_SPACE(effective_date);
vol_desc.file_structure_version[0] = 1;
FILL_SPACE(application_data);
memcpy(vol_desc.creation_date, iso_time, 16);
memcpy(vol_desc.modification_date, iso_time, 16);
memcpy(vol_desc.expiration_date, "0000000000000000", 16);
memcpy(vol_desc.effective_date, iso_time, 16);
/* For some reason, Young Minds writes this twice. Aw, what the heck */
xfwrite(&vol_desc, 1, 2048, outfile);
xfwrite(&vol_desc, 1, 2048, outfile);
last_extent_written += 2;
/* Now write the end volume descriptor. Much simpler than the other one */
memset(&vol_desc, 0, sizeof(vol_desc));
vol_desc.type[0] = ISO_VD_END;
memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
vol_desc.version[0] = 1;
xfwrite(&vol_desc, 1, 2048, outfile);
xfwrite(&vol_desc, 1, 2048, outfile);
last_extent_written += 2;
/* Next we write the path tables */
xfwrite(path_table_l, 1, path_blocks << 11, outfile);
xfwrite(path_table_l, 1, path_blocks << 11, outfile);
xfwrite(path_table_m, 1, path_blocks << 11, outfile);
xfwrite(path_table_m, 1, path_blocks << 11, outfile);
last_extent_written += 4*path_blocks;
free(path_table_l);
free(path_table_m);
path_table_l = NULL;
path_table_m = NULL;
/* OK, all done with that crap. Now write out the directories.
This is where the fur starts to fly, because we need to keep track of
each file as we find it and keep track of where we put it. */
#ifdef DBG_ISO
fprintf(stderr,"Total directory extents being written = %d\n", last_extent);
#endif
#if 0
generate_one_directory(root, outfile);
#endif
generate_iso9660_directories(root, outfile);
if(extension_record) {
xfwrite(extension_record, 1, SECTOR_SIZE, outfile);
last_extent_written++;
}
/* Now write all of the files that we need. */
fprintf(stderr,"Total extents scheduled to be written = %d\n", last_extent);
write_files(outfile);
fprintf(stderr,"Total extents actually written = %d\n", last_extent_written);
/* Hard links throw us off here */
if(should_write != last_extent){
fprintf(stderr,"Number of extents written not what was predicted. Please fix.\n");
fprintf(stderr,"Predicted = %d, written = %d\n", should_write, last_extent);
};
fprintf(stderr,"Total translation table size: %d\n", table_size);
fprintf(stderr,"Total rockridge attributes bytes: %d\n", rockridge_size);
fprintf(stderr,"Total directory bytes: %d\n", total_dir_size);
fprintf(stderr,"Path table size(bytes): %d\n", path_table_size);
#ifdef DEBUG
fprintf(stderr, "next extent, last_extent, last_extent_written %d %d %d\n",
next_extent, last_extent, last_extent_written);
#endif
return 0;
}