Import mkhybrid from OpenBSD 7.3 to create ISO9660/HFS hybrid ISO images.
- files in libfile except proto.h prepared by OpenBSD are not imported due to non-standard license (newer BSD Licensed versions will be imported later) - unnecessary files for tools build are not imported - RCSId strings are trimmed to avoid unintended substitutions Proposed on tech-toolchain@: https://mail-index.netbsd.org/tech-toolchain/2024/05/25/msg004355.html
This commit is contained in:
parent
942f913628
commit
ddaa4e7dfc
|
@ -0,0 +1,23 @@
|
|||
# $OpenBSD: Makefile,v 1.8 2022/07/11 03:11:49 daniel Exp $
|
||||
|
||||
# NOTE: The mkhybrid distrib also makes an "mkisofs" which is the same binary
|
||||
# linked. When we know mkhybrid makes distrib CDs ok we should modify this
|
||||
# to make mkisofs as a link to this, rather than the (earlier) version in
|
||||
# the tree.
|
||||
|
||||
PROG= mkhybrid
|
||||
MAN= mkhybrid.8
|
||||
BINDIR= /usr/sbin
|
||||
.PATH: ${.CURDIR}/../src ${.CURDIR}/../src/libhfs_iso ${.CURDIR}/../src/libfile
|
||||
|
||||
SRCS= data.c block.c low.c lfile.c btree.c node.c record.c lvolume.c \
|
||||
hfs.c file.c apprentice.c softmagic.c mkisofs.c tree.c write.c \
|
||||
hash.c rock.c multi.c joliet.c match.c name.c eltorito.c \
|
||||
apple.c volume.c desktop.c mac_label.c
|
||||
|
||||
CFLAGS+=-DSYSTEM_ID_DEFAULT=\"OpenBSD\" -DAPPLE_HYB -DVANILLA_AUTOCONF \
|
||||
-I${.CURDIR}/../src -I${.CURDIR}/../src/include \
|
||||
-I${.CURDIR}/../src/libhfs_iso \
|
||||
-I${.CURDIR}/../src/libfile
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,349 @@
|
|||
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.
|
||||
HFS hybrid code Copyright (C) James Pearson 1997, 1998, 1999.
|
||||
libhfs code Copyright (C) 1996, 1997 Robert Leslie
|
||||
libfile code Copyright (c) Ian F. Darwin 1986, 1987, 1989, 1990, 1991,
|
||||
1992, 1994, 1995.)
|
||||
|
||||
----------------------------------------
|
||||
|
||||
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.
|
|
@ -0,0 +1,863 @@
|
|||
Wed Nov 5 10:46:29 1997 Andreas Buschmann US/EC4 60/1F/110 #40409 <buschman@lts.sel.alcatel.de>
|
||||
|
||||
Circumvent a bug in the SunOS / Solaris CD-ROM driver (and maybe HP/UX, too).
|
||||
|
||||
* mkisofs.8 (-S): Document switch.
|
||||
* mkisofs.c (split_SL_field): new Variable, new switch -S.
|
||||
* mkisofs.h (split_SL_field): new Variable.
|
||||
* rock.c (generate_rock_ridge_attributes): only split SL field,
|
||||
when split_SL_field is set.
|
||||
|
||||
Tue Jun 3 15:32:21 1997 Andreas Buschmann <buschman@lts.sel.alcatel.de>
|
||||
|
||||
Circumvent a bug in the SunOS CD-ROM driver (and maybee HP/UX, too).
|
||||
|
||||
* mkisofs.8 (-s): Document switch.
|
||||
* mkisofs.c (split_SL_component): new Variable, new switch -s.
|
||||
* mkisofs.h (split_SL_component): new Variable.
|
||||
* rock.c (generate_rock_ridge_attributes): only split SL
|
||||
components, when split_SL_component is set.
|
||||
|
||||
* defaults.h: Added SunOS string.
|
||||
|
||||
|
||||
Wed Mar 19 16:50:17 1997 Fred Fish <fnf@ninemoons.com>
|
||||
|
||||
* Makefile.in (CFLAGS): Let configure set basic flags. Move
|
||||
compilation option -c to actual CC commands.
|
||||
(LDFLAGS): Let configure set basic flags.
|
||||
(Makefile): Depends upon config.status, not configure.
|
||||
Regenerate if necessary from Makefile.in using config.status.
|
||||
(configure): Cd to srcdir before running autoconf.
|
||||
* acconfig.h: New file to hold nonstandard entries used in
|
||||
config.h.in. Used by autoheader to generate config.h.in.
|
||||
* config.h.in: Regenerated with autoheader.
|
||||
* configure.in: Check for existance of sbrk() function.
|
||||
* configure: Regenerated with autoconf 2.12.
|
||||
* fnmatch.c (FMN_FILE_NAME): Define if not already defined.
|
||||
(FNM_LEADING_DIR): Ditto.
|
||||
(FNM_CASEFOLD): Ditto.
|
||||
* mkisofs.c (main): Only use sbrk() if system supports it.
|
||||
|
||||
Fri Mar 14 21:54:37 1997 Eric Youngdale <eric@andante.jic.com>
|
||||
|
||||
* Bump version number to 1.10, public release.
|
||||
|
||||
* Put entire thing under RCS. History is buried there now.
|
||||
|
||||
* Fix bug involving empty directories, translation tables and
|
||||
malloc(0).
|
||||
|
||||
Mon Feb 17 12:44:03 1997 Eric Youngdale <eric@andante.jic.com>
|
||||
|
||||
* Bump version number to 1.10b7.
|
||||
|
||||
* Makefile.in, configure.in, config.in: Change to use GNU autoconf.
|
||||
|
||||
* Configure: Delete old configuration script.
|
||||
|
||||
* tree.c: Fix bug where we had a rename limit of 1000 files
|
||||
instead of 0x1000.
|
||||
|
||||
* mkisofs.c: Fix sign of timezone offset. Linux iso filesystem
|
||||
also need to be fixed, unfortunately.
|
||||
|
||||
Tue Dec 3 22:21:21 1996 Eric Youngdale <eric@sub2317.jic.com>
|
||||
|
||||
Fixed a couple of multi-session bugs. Discs now seem to
|
||||
work on both Solaris and Windows-NT.
|
||||
|
||||
* Bump version number to 1.10b6.
|
||||
|
||||
Tue Dec 3 22:21:21 1996 Eric Youngdale <eric@sub2317.jic.com>
|
||||
|
||||
Multi-session stuff *almost* there. Discs seem to work
|
||||
under Linux without any problem, but under DOS only
|
||||
the first session is seen. The patch to write.c
|
||||
inspired by disc written by Windows generated multi-session
|
||||
disc, which will hopefully make the discs usable under
|
||||
DOS as well.
|
||||
|
||||
* Bump version number to 1.10b5.
|
||||
|
||||
* write.c: use size of new session, not total of all sessions
|
||||
in volume_space_size field.
|
||||
|
||||
* mkisofs.8: Update with current location of cdwrite.
|
||||
|
||||
Mon Nov 4 23:45:01 1996 Eric Youngdale <eric@sub2317.jic.com>
|
||||
|
||||
* Bump version number to 1.10b4.
|
||||
|
||||
* Add cdwrite.c.diff file, which provides a very crude, minimal
|
||||
interface between mkisofs and cdwrite. It should be enough to
|
||||
generate a multi-session disc, but it hasn't been tested yet.
|
||||
|
||||
Thu Oct 17 00:39:52 1996 Eric Youngdale <eric@sub2317.jic.com>
|
||||
|
||||
* Bump version number to 1.10b3.
|
||||
|
||||
Wed Oct 16 23:40:44 1996 Michael Fulbright <msf@redhat.com>
|
||||
|
||||
Add support for 'El Torito' specification which allows for bootable
|
||||
cdroms.
|
||||
|
||||
* Makefile.in: Add eltorito.[c,o].
|
||||
|
||||
* defaults.h: Add default settings for El Torito related things.
|
||||
|
||||
* iso9660.h: Add structure definitions for El Torito.
|
||||
|
||||
* mkisofs.8: Document new options.
|
||||
|
||||
* mkisofs.c: Add support for new options related to El Torito.
|
||||
|
||||
* mkisofs.h: Add definitions, prototypes as required.
|
||||
|
||||
* tree.c: Add search_tree_file function to search for a specified
|
||||
file.
|
||||
|
||||
* write.c: Add support for writing special records for El Torito.
|
||||
|
||||
* eltorito.c: New file.
|
||||
|
||||
|
||||
Wed Oct 16 23:40:44 1996 Eric Youngdale <eric@sub2317.jic.com>
|
||||
|
||||
* rock.c: Fix bug whereby we made assumptions about how
|
||||
dev_t was split into major/minor. Use major() and minor()
|
||||
macros to do this for us, since each system should
|
||||
do this correctly.
|
||||
|
||||
* write.c: Fix bug whereby abstract, copyright and appid
|
||||
strings were not properly filled if application ID weren't
|
||||
in use.
|
||||
|
||||
Sun Sep 29 10:05:10 1996 Eric Youngdale <eric@sub2317.jic.com>
|
||||
|
||||
* Bump version number to 1.10b2. Minor bug fixes here
|
||||
and there.
|
||||
|
||||
Sun Sep 15 18:54:05 1996 Eric Youngdale <eric@sub2317.jic.com>
|
||||
|
||||
* Bump version number to 1.10b1. Major new functionality is
|
||||
support for multi-session. Still a bit preliminary, but
|
||||
most of the pieces are there now.
|
||||
|
||||
Wed Dec 20 16:44:44 1995 Eric Youngdale (eric@andante.aib.com)
|
||||
|
||||
* mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.05.
|
||||
|
||||
* rock.c: Bugfix for cases where sizeof(int) == 4 and
|
||||
sizeof(dev_t) > 4.
|
||||
|
||||
* rock.c: Bugfix for long symbolic links ('/' characters were
|
||||
being dropped).
|
||||
|
||||
Patches from Peter Miller <pmiller@agso.gov.au>:
|
||||
|
||||
* mkisofs.8: Documentation fix (some versions of nroff don't
|
||||
like '.' in column 1 if it is not a nroff command).
|
||||
|
||||
* mkisofs.c: Add support for 'rationalize' option.
|
||||
Similar to rock ridge, except echos of development environment
|
||||
are removed.
|
||||
|
||||
* write.c Status indicator now indicates percent finished, and
|
||||
estimated time of completion.
|
||||
|
||||
Sun Feb 26 01:52:06 1995 Eric Youngdale (eric@largo)
|
||||
|
||||
* Add patches from Ross Biro to allow you to merge arbitrary
|
||||
trees into the image. This is not compiled in by default but
|
||||
you need to add -DADD_FILES when compiling.
|
||||
|
||||
Fri Feb 17 02:29:03 1995 Paul Eggert <eggert@twinsun.com>
|
||||
|
||||
* tree.c: Port to Solaris 2.4. Prefer <sys/mkdev.h> if
|
||||
HASMKDEV. Cast unknown integer types to unsigned long and
|
||||
print them with %lu or %lx.
|
||||
|
||||
Thu Jan 26 15:25:00 1995 H. Peter Anvin (hpa@yggdrasil.com)
|
||||
|
||||
* mkisofs.c: Substitute underscore for leading dot in non-Rock
|
||||
Ridge filenames, since MS-DOS cannot read files whose names
|
||||
begin with a period.
|
||||
|
||||
Mon Jan 16 18:31:41 1995 Eric Youngdale (eric@aib.com)
|
||||
|
||||
* rock.c (generate_rock_ridge_attributes): Only use ROOT
|
||||
record for symlinks if we are at the start of the symlink.
|
||||
Otherwise just generate an empty entry.
|
||||
|
||||
Mon Jan 16 16:19:50 1995 Eric Youngdale (eric@aib.com)
|
||||
|
||||
* diag/isodump.c: Use isonum_733 instead of trying to dereference
|
||||
pointers when trying to decode 733 numbers in the iso9660 image.
|
||||
|
||||
* diag/isovfy.c: Likewise.
|
||||
|
||||
* write.c: Always assign an extent number, even for zero length
|
||||
files. A zero length file with a NULL extent is apparently dropped
|
||||
by many readers.
|
||||
|
||||
Wed Jan 11 13:46:50 1995 Eric Youngdale (eric@aib.com)
|
||||
|
||||
* mkisofs.c: Modify extension record to conform to IEEE P1282
|
||||
specifications. This is commented out right now, but a trivial
|
||||
change to a #define enables this. I need to see the specs
|
||||
to see whether anything else changed before this becomes final.
|
||||
|
||||
* write.c (FDECL4): Fix so that we properly determine error
|
||||
conditions.
|
||||
|
||||
* mkisofs.h: Change rr_attributes to unsigned.
|
||||
|
||||
* tree.c(increment_nlink): Change pnt since rr_attributes is now
|
||||
unsigned.
|
||||
|
||||
Ultrix patches from petav@argon.e20.physik.tu-muenchen.de (Peter Averkamp)
|
||||
|
||||
* rock.c: Fix for ultrix systems, we have 64 bit device numbers.
|
||||
Type cast when generating file size. Change rr_attributes to
|
||||
unsigned.
|
||||
|
||||
* mkisofs.c: For ultrix systems, define our own function
|
||||
for strdup.
|
||||
|
||||
* mkisofs.c: Fix usage() since some compilers do not concatenate
|
||||
strings properly (i.e. ultrix).
|
||||
|
||||
Bugs found with Sentinel II:
|
||||
|
||||
* write.c: Fix a couple of memory leaks.
|
||||
|
||||
* mkisofs.c: Bugfix - always put a zero byte at end of name
|
||||
for ".." entry.
|
||||
|
||||
* tree.c: Set isorec.date from fstatbuf.st_ctime, not current_time,
|
||||
since current_time might not be set.
|
||||
|
||||
Sat Dec 3 14:55:42 1994 Eric Youngdale (eric@andante)
|
||||
|
||||
* mkisofs.c: When returning entry for ".." file, set second byte
|
||||
to 0.
|
||||
|
||||
* write.c: Free name and rr_attributes fields when writing.
|
||||
|
||||
Mon Nov 28 13:36:27 1994 Eric Youngdale (eric@andante)
|
||||
|
||||
* mkisofs.h: Change rr_attributes to unsigned.
|
||||
|
||||
* rock.c: Ditto. Work around >>32 bug in ultrix for 64 bit data types.
|
||||
|
||||
* mkisofs.c (usage): Fix for ultrix - use continuation lines
|
||||
instead of assuming that strings are catenated by the compiler.
|
||||
|
||||
Mon Jun 20 20:25:26 1994 Eric Youngdale (eric@esp22)
|
||||
|
||||
* mkisofs.c, mkisofs.8, Makefile (version_string): Bump to pre-1.02.
|
||||
|
||||
* mkisofs.h: Fix declaration of e_malloc to use DECL macros.
|
||||
|
||||
* tree.c: Fix bug in previous change.
|
||||
|
||||
* diag/*.c: Add appropriate copyright notices.
|
||||
|
||||
Sat Apr 9 13:30:46 1994 Eric Youngdale (ericy@cais.com)
|
||||
|
||||
* Configure: New file - shell script that determines a bunch of
|
||||
things to properly build mkisofs.
|
||||
|
||||
* Makefile.in: New file - copy of Makefile, but Configure sets a
|
||||
few things up for it.
|
||||
|
||||
* tree.c: Do not depend upon opendir to return NULL if we cannot
|
||||
open a directory - actually try and read the first entry. The
|
||||
foibles of NFS seem to require this.
|
||||
|
||||
* write.c: Fix definition of xfwrite (Use FDECL4)
|
||||
|
||||
Add some changes to allow more configurability of some of the
|
||||
volume header fields:
|
||||
|
||||
* mkisofs.8: Document new configuration options.
|
||||
|
||||
* mkisofs.c: Add variables to hold new fields. Add function to
|
||||
read .mkisofsrc files.
|
||||
|
||||
* defaults.h: Another way of configuring the same things.
|
||||
|
||||
Add some changes from Leo Weppelman leo@ahwau.ahold.nl.
|
||||
|
||||
* mkisofs.c: Allow -A to specify application ID. Fix usage(),
|
||||
getopt and add case switch.
|
||||
|
||||
* rock.c: Fix handling of device numbers (dev_t high should only
|
||||
be used when sizeof(dev_t) > 32 bits).
|
||||
|
||||
Add a bunch of changes from Manuel Bouyer.
|
||||
|
||||
* diag/Makefile: New file.
|
||||
|
||||
* diag/dump.c, diag/isodump.c: Use termios if system supports it.
|
||||
|
||||
* (throughout): Replace all occurences of "malloc" with e_malloc.
|
||||
|
||||
* mkisofs.c: For NetBSD, attempt to increase the rlimit for
|
||||
the size of the data segment to about 33 Mb.
|
||||
|
||||
* mkisofs.c (e_malloc): New function. Calls malloc, and prints
|
||||
nice error message and exits if NULL is returned.
|
||||
|
||||
Sun Jan 23 19:23:57 1994 Eric Youngdale (eric@esp22)
|
||||
|
||||
* mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.01.
|
||||
|
||||
Add a bunch of stuff so that mkisofs will work on a VMS system.
|
||||
|
||||
* (ALL): Change any direct use of the "st_ino" field from
|
||||
the statbuf to use a macro.
|
||||
|
||||
* mkisofs.h: Define appropriate macros for both VMS and unix.
|
||||
|
||||
* (ALL): Add type casts whenever we use the UNCACHED_DEV macro.
|
||||
|
||||
* rock.c: Wrap a #ifndef VMS around block and character device
|
||||
stuff.
|
||||
|
||||
* write.c: Add prototype for strdup if VMS is defined.
|
||||
|
||||
* make.com: Script for building mkisofs on a VMS system.
|
||||
|
||||
* Makefile: Include make.com in the distribution.
|
||||
|
||||
* mkisofs.c: Include <sys/type.h> on VMS systems.
|
||||
|
||||
* tree.c: Include <sys/file.h> and "vms.h" on VMS systems.
|
||||
|
||||
* mkisofs.h (PATH_SEPARATOR, SPATH_SEPARATOR): New macros
|
||||
that define the ascii character that separates the last directory
|
||||
component from the filename.
|
||||
|
||||
* tree.c, mkisofs.c: Use them.
|
||||
|
||||
* vms.c: New file. Contains version of getopt, strdup, opendir,
|
||||
readdir and closedir.
|
||||
|
||||
* vms.h: New file. Defines S_IS* macros. Define gmtime as
|
||||
localtime, since gmtime under VMS returns NULL.
|
||||
|
||||
Sat Jan 15 13:57:42 1994 Eric Youngdale (eric@esp22)
|
||||
|
||||
* mkisofs.h (transparent_compression): New prototype.
|
||||
|
||||
* mkisofs.c (transparent_compression): Declare, use
|
||||
'-z' option to turn on.
|
||||
|
||||
* tree.c: Change TRANS.TBL;1 to TRANS.TBL (version gets
|
||||
added later, if required).
|
||||
|
||||
* rock.c: If transparent compression requested, verify
|
||||
file is really suitable (check magic numbers), and extract
|
||||
correct file length to store in SUSP record.
|
||||
|
||||
Sat Jan 15 01:57:42 1994 Eric Youngdale (eric@esp22)
|
||||
|
||||
* write.c (compare_dirs): Bugfix for patch from Jan 6.
|
||||
|
||||
* mkisofs.h (struct directory_entry): Add element total_rr_attr_size.
|
||||
(struct file_hash): Add element ce_bytes.
|
||||
|
||||
* write.c (iso_write): Update last_extent_written, as required,
|
||||
and check it against last_extent as a sanity check.
|
||||
(generate_one_directory): If ce_bytes is non-zero, allocate
|
||||
a buffer and fill it with the CE records. Also, update
|
||||
the extent and offset entries in the CE SUSP field and
|
||||
output after directory is written.
|
||||
(assign_directory_addresses): Allow for CE sectors after each
|
||||
directory.
|
||||
|
||||
* tree.c (sort_n_finish): Set field ce_bytes by summing
|
||||
the sizes of all CE blocks in each files RR attributes.
|
||||
Do not count these bytes for main directory.
|
||||
|
||||
* rock.c (generate_rock_ridge_attributes): Generate
|
||||
CE entries to break up large records into manageable sizes.
|
||||
Allow long names to be split, and allow long symlinks to be split.
|
||||
Allow splitting before each SUSP field as well, to make
|
||||
sure we do not screw outselves.
|
||||
|
||||
Thu Jan 6 21:47:43 1994 Eric Youngdale (eric@esp22)
|
||||
|
||||
Bugfix.
|
||||
|
||||
* write.c (compare_dirs): Only compare directory names up to
|
||||
the ';' for the version number.
|
||||
|
||||
Add four new options: (1) Full 31 character filenames,
|
||||
(2) Omit version number, (3) Omit trailing period from filenames,
|
||||
(4) Skip deep directory relocation.
|
||||
|
||||
* iso9660.h: Allow 34 characters for filename.
|
||||
|
||||
* mkisofs.8: Update for new options.
|
||||
|
||||
* mkisofs.c: Add flag variables for new options.
|
||||
Mention new options in usage(), tell getopt about
|
||||
new options, and set appropriate flags when
|
||||
new options are specified.
|
||||
|
||||
* mkisofs.c (iso9660_file_length): Implement new options.
|
||||
|
||||
* mkisofs.h: Declare flag variables for new options.
|
||||
|
||||
* tree.c (sort_n_finish): Increase declaration of newname and
|
||||
rootname to 34 characters. If full_iso9660_filenames in effect,
|
||||
use different rules for making unique names.
|
||||
|
||||
* tree.c (scan_directory_tree): Use RR_relocation_depth instead of
|
||||
constant for threshold for starting deep directory relocation.
|
||||
|
||||
Wed Jan 5 01:32:34 1994 John Brezak (brezak@ch.hp.com)
|
||||
|
||||
* Makefile.bsd: New file. For NetBSD.
|
||||
|
||||
* rock.c, tree.c: Do not include sys/sysmacros.h for NetBSD.
|
||||
|
||||
Fri Dec 31 13:22:52 1993 Eric Youngdale (eric@esp22)
|
||||
|
||||
* mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.00.
|
||||
|
||||
* tree.c (scan_directory_tree): Handle case where we do not
|
||||
have permissions to open a directory.
|
||||
|
||||
* write.c (xfwrite): New function - wrapper for fwrite,
|
||||
except that we print message and punt if write fails.
|
||||
|
||||
* write.c: Move include of mkisofs.h and iso9660.h until after
|
||||
string.h and stdlib.h is included.
|
||||
|
||||
* write.c: Do not attempt to use strerror on sun systems.
|
||||
|
||||
Thu Dec 9 13:17:28 1993 R.-D. Marzusch (marzusch@odiehh.hanse.de)
|
||||
|
||||
* exclude.c, exclude.h: New files. Contains list of files to
|
||||
exclude from consideration.
|
||||
|
||||
* Makefile: Compile exclude.c, add dependencies to other files.
|
||||
|
||||
* mkisofs.8: Describe -x option.
|
||||
|
||||
* mkisofs.c: Include exclude.h, handle -x option.
|
||||
|
||||
|
||||
Fri Dec 10 01:07:43 1993 Peter van der Veen (peterv@qnx.com)
|
||||
|
||||
* mkisofs.c, mkisofs.h: Moved declaration of root_record.
|
||||
|
||||
* mkisofs.h: Added prototype for get_733().
|
||||
|
||||
* write.c(iso_write), tree.c, rock.c(generate_rock_ridge_attributes):
|
||||
Added defines for QNX operation system
|
||||
|
||||
* rock.c(generate_rock_ridge_attributes): symbolic links should
|
||||
not have CONTINUE component flag set unless there are multiple
|
||||
component records, and mkisofs does not generate these.
|
||||
st_ctime was stored as the creation time, changed to attribute time.
|
||||
QNX has a creation time, so that is stored as well under QNX.
|
||||
|
||||
Thu Oct 28 19:54:38 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.99.
|
||||
|
||||
* write.c(iso_write): Put hour, minute, second into date fields in
|
||||
volume descriptor.
|
||||
|
||||
* write.c (iso_write): Set file_structure_version to 1, instead of
|
||||
' ' (Seems to screw up Macs).
|
||||
|
||||
Sun Oct 17 01:13:36 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.98.
|
||||
|
||||
Increment nlink in root directory when rr_moved directory is present.
|
||||
|
||||
* tree.c (increment_nlink): New function.
|
||||
|
||||
* tree.c (finish_cl_pl_entries): Call increment_nlink for all
|
||||
references to the root directory.
|
||||
|
||||
* tree.c (root_statbuf): New variable.
|
||||
|
||||
* tree.c (scan_directory_tree): Initialize root_statbuf when we
|
||||
stat the root directory.
|
||||
|
||||
* tree.c (generate_reloc_directory): Use root_statbuf when
|
||||
generating the Rock Ridge stuff for the ".." entry in the
|
||||
reloc_dir.
|
||||
|
||||
* tree.c (scan_directory_tree): Use root_statbuf when generating
|
||||
the ".." entry in the root directory.
|
||||
|
||||
Sat Oct 16 10:28:30 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
Fix path tables so that they are sorted.
|
||||
|
||||
* tree.c (assign_directory_addresses): Move to write.c
|
||||
|
||||
* write.c (generate_path_tables): Create an array of pointers to
|
||||
the individual directories, and sort it based upon the name and
|
||||
the parent path table index. Then update all of the indexes and
|
||||
repeat the sort until the path table indexes no longer need to be
|
||||
changed, and then write the path table.
|
||||
|
||||
Fix problem where hard links were throwing off the total extent count.
|
||||
|
||||
* write.c (iso_write): Call assign_file_addresses, and then
|
||||
use last_extent to determine how big the volume is.
|
||||
|
||||
* write.c (generate_one_directory): Decrement n_data_extents
|
||||
for hard links to non-directories so that the expected number
|
||||
of extents is written correctly.
|
||||
|
||||
* write.c(assign_file_addresses): New function.
|
||||
|
||||
Fri Oct 15 22:35:43 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
The standard says we should do these things:
|
||||
|
||||
* tree.c (generate_reloc_directory): Add RR attributes to
|
||||
the rr_moved directory.
|
||||
|
||||
* mkisofs.c(main): Change ER text strings back to recommended
|
||||
values.
|
||||
|
||||
Tue Oct 12 21:07:38 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.97.
|
||||
|
||||
* tree.c (scan_directory_tree): Do not insert PL entry into
|
||||
root directory record (i.e. !parent)
|
||||
|
||||
* tree.c (finish_cl_pl_entries): Do not rely upon name
|
||||
comparison to locate parent - use d_entry->self instead,
|
||||
which is guaranteed to be correct.
|
||||
|
||||
* mkisofs.h: New variable n_data_extents.
|
||||
|
||||
* tree.c: Declare and initialize n_data_extents to 0.
|
||||
(scan_directory_tree) for non-directories, add
|
||||
ROUND_UP(statbuf.st_size) to n_data_extents.
|
||||
(sort_n_finish): Increment n_data_extents for translation tables,
|
||||
as appropriate.
|
||||
|
||||
* write.c(iso_write): Add n_data_extents to the
|
||||
volume_space_size field.
|
||||
|
||||
* hash.c(add_hash): If size != 0 and extent == 0, or
|
||||
if size == 0 and extent != 0, then complain about
|
||||
inserting this into the hash table. Kind of a sanity check.
|
||||
|
||||
Sat Oct 9 16:39:15 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.96.
|
||||
|
||||
Numerous bugfixes, thanks to a one-off disc from rab@cdrom.com.
|
||||
|
||||
* write.c(generate_one_directory): Wait until after we have
|
||||
filled in the starting_extent field to s_entry before calling
|
||||
add_hash. This fixes a problem where the hash table gets an
|
||||
extent of 0 for all regular files, and this turns up when you have
|
||||
hard links on the disc. (The hash table allows us to have each
|
||||
hard link point to the same extent on the cdrom, thereby saving
|
||||
some space).
|
||||
|
||||
* tree.c(scan_directory_tree): Set statbuf.st_dev and
|
||||
statbuf.st_ino to the UNCACHED numbers for symlinks that we
|
||||
are not following. This prevents the function find_hash from
|
||||
returning an inode that cooresponds to the file the symlink points
|
||||
to, which in turn prevents generate_one_directory from filling in
|
||||
a bogus file length (should be zero for symlinks).
|
||||
|
||||
* tree.c(scan_directory_tree): Always call lstat for the file
|
||||
so that non-RockRidge discs get correct treatment of symlinks.
|
||||
Improve error message when we ignore a symlink on a non-RR disc.
|
||||
|
||||
* write.c(generate_one_directory): Set fields for starting_extent
|
||||
and size in the "." and ".." entries before we add them to the
|
||||
file hash. Fixes problems with incorrect backlinks for second
|
||||
level directories.
|
||||
|
||||
Wed Oct 6 19:53:40 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* write.c (write_one_file): Print message and punt if we are
|
||||
unable to open the file.
|
||||
|
||||
* tree.c(scan_directory_tree): For regular files, use the access
|
||||
function to verify that the file is readable in the first place.
|
||||
If not, issue a warning and skip it. For directories, it probably
|
||||
does not matter, since we would not be able to descend into them
|
||||
in the first place.
|
||||
|
||||
Wed Sep 29 00:02:47 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.95.
|
||||
|
||||
* write.c, tree.c: Cosmetic changes to printed information.
|
||||
|
||||
* tree.c(scan_directory_tree): Set size to zero for
|
||||
special stub entries that correspond to the
|
||||
relocated directories. Hopefully last big bug.
|
||||
|
||||
* mkisofs.h: Change TABLE_INODE, UNCACHED_* macros
|
||||
to be 0x7fff... to be compatible with signed datatypes.
|
||||
|
||||
Mon Sep 27 20:14:49 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.94.
|
||||
|
||||
* write.c (write_path_tables): Actually search the
|
||||
directory for the matching entry in case we renamed
|
||||
the directory because of a name conflict.
|
||||
|
||||
* tree.c(scan_directory_tree): Take directory_entry pointer
|
||||
as second argument so that we can create a backpointer
|
||||
in the directory structure that points back to the original
|
||||
dir.
|
||||
|
||||
* mkisofs.c: Fix call to scan_directory_tree to use new calling
|
||||
sequence.
|
||||
|
||||
* write.c(generate_one_directory): Punt if the last_extent counter
|
||||
ever exceeds 700Mb/2048. Print name of responsible file,
|
||||
extent counter, and starting extent. Perhaps we can catch it in
|
||||
the act.
|
||||
|
||||
Sun Sep 26 20:58:05 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.93.
|
||||
|
||||
* tree.c(scan_directory_tree): Handle symlinks better. Either
|
||||
leave them as symlinks, or erase any trace that they were a
|
||||
symlink but do not do it 1/2 way as before. Also, watch for
|
||||
directory loops created with symlinks.
|
||||
|
||||
* mkisofs.h: Add new flag follow_links.
|
||||
|
||||
* mkisofs.c: Add command line switch "-f" to toggle follow_links.
|
||||
|
||||
* mkisofs.8: Document new switch.
|
||||
|
||||
* tree.c: Add code to handle symlinks using new flag.
|
||||
|
||||
* hash.c: Add add_directory_hash, find_directory_hash functions.
|
||||
|
||||
* mkisofs.h: Add prototypes.
|
||||
|
||||
Sat Sep 25 14:26:31 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.92.
|
||||
|
||||
* mkisofs.c: Make sure path is an actual directory before trying
|
||||
to scan it.
|
||||
|
||||
* mkisofs.h: Add DECL and FDECL? macros for sparc like systems.
|
||||
Do proper define of optind and optarg under SVr4.
|
||||
|
||||
* tree.c: Change translation table name from YMTRANS.TBL to TRANS.TBL.
|
||||
|
||||
* mkisofs.c: Neaten up message in extension record when RRIP is
|
||||
in use.
|
||||
|
||||
* Throughout - change all function declarations so that
|
||||
traditional C compilers (i.e. sparc) will work.
|
||||
|
||||
* Makefile: Change to use system default C compiler.
|
||||
|
||||
* mkisofs.c: Add some stuff so that this will compile under VMS.
|
||||
Many things missing for VMS still.
|
||||
|
||||
* iso9660.h: Do not use zero length array in struct definition.
|
||||
|
||||
* tree.c (sort_n_finish): Account for this.
|
||||
|
||||
* Change copyright notice.
|
||||
|
||||
|
||||
Wed Aug 25 08:06:51 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.91.
|
||||
|
||||
* mkisofs.h: Only include sys/dir.h for linux. Other systems
|
||||
will need other things.
|
||||
|
||||
* mkisofs.c, tree.c: Include unistd.h.
|
||||
|
||||
* Makefile: Use OBJS to define list of object files.
|
||||
|
||||
Sun Aug 22 20:55:17 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.9.
|
||||
|
||||
* write.c (iso_7*): Fix so that they work properly on Motorola
|
||||
systems.
|
||||
|
||||
Fri Aug 20 00:14:36 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.8.
|
||||
|
||||
* rock.c: Do not mask off write permissions from posix file modes.
|
||||
|
||||
Wed Aug 18 09:02:12 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.7.
|
||||
|
||||
* rock.c: Do not write NM field for . and .. (redundant and a
|
||||
waste of space).
|
||||
|
||||
* mkisofs.c: Take -P and -p options for publisher and preparer id
|
||||
fields.
|
||||
|
||||
* write.c: Store publisher and preparer id in volume
|
||||
descriptor.
|
||||
|
||||
* rock.c: Write optional SP field to identify SUSP. Write
|
||||
optional CE field to point to the extension header.
|
||||
|
||||
* tree.c: Request SP and CE fields be added to root directory.
|
||||
|
||||
* tree.c: Fix bug in name conflict resolution.
|
||||
|
||||
* write.c: Fill in date fields in the colume descriptor.
|
||||
|
||||
* write.c (write_one_file): If the file is large enough, write in
|
||||
chunks of 16 sectors to improve performance.
|
||||
|
||||
* hash.c (add_hash, find_hash, etc): Do not hash s_entry, instead
|
||||
store relevant info in hash structure (we free s_entry structs as
|
||||
we write files, and we need to have access to the hash table the
|
||||
whole way through.
|
||||
|
||||
* write.c: Add a few statistics about directory sizes, RR sizes,
|
||||
translation table sizes, etc.
|
||||
|
||||
* tree.c: Use major, not MAJOR. Same for minor. Define S_ISSOCK
|
||||
and S_ISLNK if not defined.
|
||||
|
||||
* rock.c: Define S_ISLNK if not defined.
|
||||
|
||||
* mkisofs.c: Print out max memory usage. Fix bug in call to getopt.
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.6.
|
||||
|
||||
* tree.c: Simplify the calculation of isorec.len, isorec.name_len
|
||||
and the calculation of the path table sizes by doing it all at
|
||||
one point after conflict resolution is done.
|
||||
|
||||
* tree.c: scan_directory_tree is now responsible for generating
|
||||
the line that goes into the YMTRANS.TBL file. These lines are
|
||||
collected later on into something that will be dumped to the
|
||||
file. Correctly handle all of the special file types.
|
||||
|
||||
Mon Aug 16 21:59:47 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.5.
|
||||
|
||||
* mkisofs.c: Add -a option (to force all files to be
|
||||
transferred). Remove find_file_hash stuff.
|
||||
|
||||
* write.c: Pad length even if Rock Ridge is not in use.
|
||||
|
||||
* hash.c: Rewrite hash_file_* stuff so that it can be used to
|
||||
easily detect (and look up) filenames that have been accepted
|
||||
for use in this directory. Used for name collision detection.
|
||||
|
||||
* tree.c (sort_n_finish): If two names collide, generate a unique
|
||||
one (verified with the hash routines). Change the lower priority
|
||||
name if there is a difference.
|
||||
|
||||
|
||||
|
||||
Sat Aug 14 13:18:21 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.4.
|
||||
|
||||
* tree.c (load_translation_table): New function - read
|
||||
YMTRANS.TBL. (scan_directory_tree) Call it.
|
||||
|
||||
* mkisofs.c (iso9660_file_length): Call find_file_hash to see
|
||||
if translated name is specified. If so, use it.
|
||||
|
||||
* hash.c (name_hash, add_file_hash, find_file_hash,
|
||||
flush_file_hash): New functions for hashing stuff from
|
||||
YMTRANS.TBL.
|
||||
|
||||
* mkisofs.h: Add a bunch of prototypes for the new functions.
|
||||
|
||||
* mkisofs.8: Update.
|
||||
|
||||
* mkisofs.c, Makefile (version_string): Bump to 0.3.
|
||||
|
||||
* Makefile: Add version number to tar file in dist target.
|
||||
|
||||
* mkisofs.c: Call finish_cl_pl_entries() after directories have
|
||||
been generated, and extent numbers assigned.
|
||||
|
||||
* write.c (generate_one_directory): Update s_entry->size for
|
||||
directories (as well as isorec.size).
|
||||
|
||||
* rock.c: Add code to generate CL, PL, and RE entries. The
|
||||
extent numbers for the CL and PL entries are NULL, and these
|
||||
are filled in later once we know where they actually belong.
|
||||
|
||||
* mkisofs.h: Add parent_rec to directory_entry. Used to fix CL/PL
|
||||
stuff.
|
||||
|
||||
* tree.c (scan_directory_tree): Set flag to generate CL/PL/RE
|
||||
entries as required, update sizes as well.
|
||||
|
||||
Fri Aug 13 19:49:30 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c (version_string): Bump to 0.2.
|
||||
|
||||
* hash.c: Do not use entries with inode == 0xffffffff or dev ==
|
||||
0xffff.
|
||||
|
||||
* write.c (write_path_tables): Strip leading directory specifications.
|
||||
|
||||
* mkisofs.h: Add definition for reloc_dir symbol. Add prototype
|
||||
for sort_n_finish, add third parameter to scan_directory_tree
|
||||
(for true parent, when directories are relocated).
|
||||
|
||||
* mkisofs.c (main): Modify call to scan_directory_tree. Call
|
||||
sort_n_finish for reloc_dir.
|
||||
|
||||
* tree.c (sort_n_finish): New function - moved code from
|
||||
scan_directory_tree.
|
||||
|
||||
* tree.c (generate_reloc_directory): New function. Generate
|
||||
directory to hold relocated directories.
|
||||
|
||||
* tree.c (scan_directory_tree): Strip leading directories when
|
||||
generating this_dir->name. If depth is too great, then move
|
||||
directory to reloc_dir (creating if it does not exist, and leave
|
||||
a dummy (non-directory) entry in the regular directory so that
|
||||
we can eventually add the required Rock Ridge record.
|
||||
|
||||
* tree.c (scan_directory_tree): Use s_entry instead of sort_dir,
|
||||
assign to this_dir->contents sooner.
|
||||
|
||||
Thu Aug 12 22:38:17 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs.c (usage): Fix syntax.
|
||||
|
||||
* mkisofs.c (main): Add new argument to scan_directory_tree
|
||||
|
||||
* tree.c (scan_directory_tree): If directory is at depth 8 or
|
||||
more, create rr_moved directory in main directory.
|
||||
|
||||
Mon Jul 26 19:45:47 1993 Eric Youngdale (eric@kafka)
|
||||
|
||||
* mkisofs v 0.1 released.
|
||||
|
|
@ -0,0 +1,369 @@
|
|||
Thu Apr 7 20:29:04 BST 1999 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12b5.1
|
||||
|
||||
Fixed bugs with MacBinary names and symbolic links to HFS files
|
||||
when using the -f option
|
||||
|
||||
Re-introduced some minor changes "lost" from v1.12b4.8
|
||||
|
||||
Forgot to add -hide-hfs-list option in previous version ...
|
||||
|
||||
Tue Mar 30 08:31:13 BST 1999 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12b5.0
|
||||
|
||||
Now based on mkisofs v1.12b5
|
||||
|
||||
Option -mac-name now only uses the HFS name if the file is one
|
||||
of the known HFS file types
|
||||
|
||||
Added -hide-list, -hide-joliet-list, -hide-hfs-list, -exclude-list
|
||||
and -path-list options. Allows a list of filenames to be excluded or
|
||||
hidden to be given in a file instead of on the command line.
|
||||
|
||||
Added option -hfs-volid to give the HFS volume its own name (not
|
||||
using the ISO9660 volume name).
|
||||
|
||||
|
||||
Tue Jan 5 15:44:24 GMT 1999 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12b4.8
|
||||
|
||||
Fixed an AppleDouble bug and added better support for more Unix
|
||||
flavours.
|
||||
|
||||
Fixed -hide-hfs bug that corrupted some HFS hidden files
|
||||
|
||||
Made the verbose output less verbose.
|
||||
|
||||
Added initial support for the AutoStart feature.
|
||||
|
||||
HFS partition maps can now be added without having to create
|
||||
a bootable HFS CD (as pre-v1.12a4.7).
|
||||
|
||||
Added option to specify the PC Exchange "cluster size".
|
||||
|
||||
Mon Aug 24 23:18:38 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a4.7
|
||||
|
||||
Fixed SGI/XINET and PC Exchange bugs
|
||||
|
||||
By default, the output image no longer has an HFS partition map
|
||||
(as pre-v1.12a3.4). Partition maps are only added if making a
|
||||
bootable HFS CD
|
||||
|
||||
Fixed possible bug with odd-length structure alignment with gcc on
|
||||
some architectures
|
||||
|
||||
Tue Aug 4 23:09:17 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a4.6
|
||||
|
||||
Made a couple of Netatalk changes
|
||||
|
||||
Altered way Apple/Unix associated files are excluded - e.g.
|
||||
if just --cap is selected, then files associated with the other
|
||||
Apple/Unix encodings are processed as normal files. Previously they
|
||||
would have been ignored
|
||||
|
||||
Added option (-no-desktop) to prevent the (empty) HFS desktop files
|
||||
being created. These will be created when the CD is used on a
|
||||
Macintosh (and stored in the System Folder).
|
||||
|
||||
Sun Jul 26 09:44:50 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a4.5
|
||||
|
||||
Fixed serious bug that could cause corrupt output when used with
|
||||
the -J option
|
||||
|
||||
Tue Jul 21 14:33:20 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a4.4
|
||||
|
||||
HFS file/directory names that share the first 31 characters have
|
||||
'_N' (N == decimal number) substituted for the last few characters
|
||||
to generate unique names.
|
||||
|
||||
1 year since the first release ...
|
||||
|
||||
Sat Jul 11 12:57:04 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a4.3
|
||||
|
||||
Added options to "hide" (options -hide and -hide-joliet) files
|
||||
or directories from the ISO9660/RockRidge and/or Joliet directory
|
||||
trees.
|
||||
|
||||
Renamed the -hfs-exclude option to -hide-hfs to be compatible
|
||||
with the above options.
|
||||
|
||||
Fixed a bug with the -hide-hfs option (very rare case ...)
|
||||
|
||||
Thu Jun 25 20:02:20 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a4.2
|
||||
|
||||
Fixed an HFS bug introduced with v1.12a3.4 that created some
|
||||
corrupt HFS volumes over about 400Mb
|
||||
|
||||
Tighten up checking for MacBinary files to prevent false matches
|
||||
|
||||
Sun Jun 21 11:55:09 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a4.1
|
||||
|
||||
Default TYPE and CREATOR can now be set via the .mkisofsrc file
|
||||
|
||||
Order of magic and mapping file on the command line is now
|
||||
important. This defines the order in which TYPE and CREATOR are set.
|
||||
|
||||
Apple/Unix file types found are logged as part of the verbose output
|
||||
(need to give -v twice)
|
||||
|
||||
Added option (-log-file) to redirect stderr messages
|
||||
|
||||
Added option (-hfs-exclude) to exclude files/directories from
|
||||
the HFS part of the CD.
|
||||
|
||||
Fixed a couple of MacBinary/AppleSingle bugs.
|
||||
|
||||
Thu Jun 8 23:40:56 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a4.0
|
||||
|
||||
Resource fork file names not added to TRANS.TBL
|
||||
|
||||
Re-enabled support of non-regular Win32 files. GNU-Win32 can
|
||||
create symbolic links etc. These are now recognised.
|
||||
|
||||
mkhybrid man page added.
|
||||
|
||||
Based on mkisofs v1.12b4
|
||||
|
||||
Wed May 20 12:54:36 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a3.5
|
||||
|
||||
Added support for using a "magic" file to set CREATOR/TYPE for
|
||||
a file - see README.hfs_magic for details.
|
||||
|
||||
Mon May 18 16:22:32 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a3.4
|
||||
|
||||
Added possible support for bootable Mac CDs - see README.hfs_boot
|
||||
or details.
|
||||
|
||||
Fixed -x bug (mkisofs v1.12 bug)
|
||||
|
||||
Mon May 4 14:23:46 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a3.3
|
||||
|
||||
Added support for UShare Mac/Unix files
|
||||
|
||||
Individual Mac/Unix file types can now be selected instead
|
||||
of searching for all possible types. See README.mkhybrid for
|
||||
details.
|
||||
|
||||
Fri May 1 10:34:29 BST 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a3.2
|
||||
|
||||
Various bug fixes to Mac file names
|
||||
|
||||
Tue Mar 10 14:42:03 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a3.1
|
||||
|
||||
Added -no-hfs-files option that assumes there are no Unix/Mac
|
||||
files (CAP, Netatalk, etc) - speeds up processing in these cases
|
||||
|
||||
Case insensitive HFS file/folder names that are the same are now
|
||||
allowed - one or more '_' characters are added to one or more of
|
||||
the filenames.
|
||||
|
||||
(Changed -macname option to -mac-name option)
|
||||
|
||||
Mon Feb 23 16:09:27 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a3.0
|
||||
|
||||
Based on mkisofs v1.12b3
|
||||
|
||||
Fixed serious HFS bug that crept in from v1.11 -> v1.12
|
||||
|
||||
Tue Feb 17 16:20:12 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a2.0
|
||||
|
||||
Based on mkisofs v1.12b2
|
||||
|
||||
Improved Win32 support: using -r now makes all files executable
|
||||
when run under Win95/NT4
|
||||
|
||||
Tue Feb 3 10:30:18 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a1.2
|
||||
|
||||
Fixed memory bug when used without any HFS options
|
||||
|
||||
Improved PC Exchange support (although still needs testing)
|
||||
|
||||
Tue Jan 27 10:32:26 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a1.1
|
||||
|
||||
Can now handle multiple hard linked source files with the -hfs option
|
||||
(multiple hard linked source files are handled as separate files)
|
||||
|
||||
configure script changed to check for ranlib
|
||||
|
||||
Fixed a couple of AppleSingle bugs.
|
||||
|
||||
Added option to use Mac names as starting point for ISO9660, Joliet
|
||||
and RockRidge names
|
||||
|
||||
Wed Jan 21 14:00:56 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.12a1
|
||||
|
||||
See README.mkhybrid for details
|
||||
|
||||
Fri Jan 16 17:09:48 GMT 1998 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 1.11
|
||||
|
||||
Changed version numbering to be the same as mkisofs
|
||||
|
||||
Code no longer considered beta level
|
||||
|
||||
Minor changes to allow the code to be complied and run
|
||||
on Win95/NT using Cygnus' GNU-Win32 (available from
|
||||
http://www.cygnus.com/misc/gnu-win32/)
|
||||
|
||||
Thu Dec 4 17:17:45 GMT 1997 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 0.49b
|
||||
|
||||
Fixed an HFS bug that caused a failure with directory names that
|
||||
had special AUFS characters
|
||||
|
||||
Fixed mkisofs bug in eltorito.c that wrote warning messages
|
||||
to stdout not stderr
|
||||
|
||||
Code no longer considered alpha level
|
||||
|
||||
Thu Nov 27 19:00:02 GMT 1997 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 0.48a
|
||||
|
||||
Added Apple's extensions to ISO9660 that can be used instead of
|
||||
the HFS options (see README.mkhybrid for more details).
|
||||
|
||||
Added more verbose HFS error messages.
|
||||
|
||||
Changed the Joliet option flag to -J (-j still works) to be
|
||||
compatible the with next release of mkisofs (v1.12)
|
||||
|
||||
Wed Oct 15 11:16:21 BST 1997 James Pearson <j.pearson@ge.ucl.ac.uk>
|
||||
|
||||
Version 0.47a
|
||||
|
||||
Fixed bug that prevented volume_space_size not being set in the
|
||||
PVD (or SVD)
|
||||
|
||||
Mon Oct 6 15:46:24 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk>
|
||||
|
||||
Version 0.46a
|
||||
|
||||
Small Joliet bug fix - source directories that are not readable
|
||||
are set to empty ordinary files in the ISO9660 filesystem - this
|
||||
is now true for the Joliet directory (partially responsible
|
||||
for NT4 having problems with CDs where this happened)
|
||||
|
||||
Minor documentation updates.
|
||||
|
||||
Mon Sep 15 14:15:11 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk>
|
||||
|
||||
Version 0.45a
|
||||
|
||||
Attempt to prevent the HFS Catalog file growing (see
|
||||
"Implementation" in README.mkhybrid for more details)
|
||||
This is only likely to be a problem where folders have lots
|
||||
of small files.
|
||||
|
||||
Mon Aug 18 12:00:24 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk>
|
||||
|
||||
Version 0.44a
|
||||
|
||||
If the directories were deeper than 8 and the -D flag was not
|
||||
used, then the "rr_moved" directory was not added to the Joliet
|
||||
directory tree. This has now been fixed - but one day, the deep
|
||||
Joliet directories may not have to be relocated ...
|
||||
|
||||
Fixed memcmp problem with possible uninitialised memory in
|
||||
j_compare_paths(), which *might* cause incorrect Joliet directory
|
||||
sort order
|
||||
|
||||
Wed Aug 13 14:58:56 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk>
|
||||
|
||||
Version 0.43a
|
||||
|
||||
Fixed bug for incorrect Joliet path table size
|
||||
|
||||
Fixed some old minor mkisofs bugs (TRANS.TBL not having a
|
||||
version number by default and incorrect date in the PVD).
|
||||
|
||||
Mon Aug 11 17:17:07 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk>
|
||||
|
||||
Version 0.42a
|
||||
|
||||
Now will not try to create the HFS "Desktop DB" and "Desktop DF"
|
||||
if they already exist when used with the HFS options.
|
||||
|
||||
Fixed a serious bug in the hfs code that truncated some files.
|
||||
|
||||
"TRANS.TBL" was missed out of the Joliet directory if the -T
|
||||
option was given (previously an empty file with no name was used
|
||||
which could cause problems on NT 4)
|
||||
|
||||
Fri Aug 8 10:19:46 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk>
|
||||
|
||||
Version 0.41a
|
||||
|
||||
Fixed bug which created invalid HFS/ISO9660 volumes if the -j (Joliet)
|
||||
option was not used
|
||||
|
||||
Mon Aug 4 15:08:43 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk>
|
||||
|
||||
Version 0.4a
|
||||
|
||||
Added (partial?) Joliet support.
|
||||
|
||||
Now based on mkisofs v1.11
|
||||
|
||||
Tue Jul 29 11:57:14 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk>
|
||||
|
||||
Version 0.32a
|
||||
|
||||
Allocation sizes improved to cut down on wasted space. Now uses
|
||||
the HFS "allocation" size rounded up to the nearest 2048 bytes.
|
||||
Savings can be significant with a large volume containing lots
|
||||
of smallish files.
|
||||
|
||||
Wed Jul 23 15:36:08 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk>
|
||||
|
||||
Version 0.31a
|
||||
|
||||
Deep directories (greater than RR_relocation_depth) cause core
|
||||
dump in "copy_to_mac_volume" as the relocated directory was not
|
||||
marked as an HFS folder. Fixed by putting deep HFS folders in
|
||||
their correct location.
|
||||
|
||||
Mon Jul 21 15:50:05 BST 1997 James Pearson <j.pearson@ps.ucl.ac.uk>
|
||||
|
||||
Version 0.3a, first public release.
|
|
@ -0,0 +1,149 @@
|
|||
#
|
||||
# Id: Makefile.in,v 1.3 2008/03/08 15:36:12 espie Exp
|
||||
#
|
||||
## Makefile for mkhybrid - based on mkisofs v1.12
|
||||
# James Pearson 16/3/1999
|
||||
|
||||
#### Start of system configuration section. ####
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
CC = @CC@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
LIBS = @LIBS@ -lhfs -lfile
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
|
||||
RANLIB = @RANLIB@
|
||||
|
||||
libhfsdir = libhfs_iso
|
||||
LIBHFS = $(libhfsdir)/libhfs.a
|
||||
INCHFS = $(libhfsdir)/hfs.h
|
||||
|
||||
libfiledir = libfile
|
||||
LIBFILE = $(libfiledir)/libfile.a
|
||||
|
||||
DEFINES = -DAPPLE_HYB
|
||||
|
||||
COPTS=@CFLAGS@
|
||||
|
||||
# Where to put the manual pages.
|
||||
mandir = $(prefix)/man/man8
|
||||
# Extension (not including `.') for the manual page filenames.
|
||||
manext = 8
|
||||
|
||||
#### End of system configuration section. ####
|
||||
|
||||
CFLAGS=$(COPTS) $(DEFINES) -I. -Iinclude -I$(libhfsdir) -DVANILLA_AUTOCONF
|
||||
LDFLAGS=@LDFLAGS@ -L$(libhfsdir) -L$(libfiledir)
|
||||
OBJS=mkisofs.o tree.o write.o hash.o rock.o multi.o \
|
||||
joliet.o match.o name.o eltorito.o \
|
||||
apple.o volume.o desktop.o mac_label.o
|
||||
|
||||
World: mkhybrid
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
config.status: configure
|
||||
$(SHELL) config.status --recheck
|
||||
|
||||
configure: configure.in
|
||||
cd $(srcdir) && autoconf
|
||||
|
||||
mkhybrid: Makefile $(OBJS) $(LIBHFS) $(LIBFILE)
|
||||
$(CC) $(LDFLAGS) -o mkhybrid $(OBJS) $(LIBS)
|
||||
|
||||
mkisofs: Makefile $(OBJS) $(LIBHFS) $(LIBFILE)
|
||||
$(CC) $(LDFLAGS) -o mkisofs $(OBJS) $(LIBS)
|
||||
|
||||
apple_driver: apple_driver.o
|
||||
$(CC) $(LDFLAGS) -o apple_driver apple_driver.o
|
||||
apple_driver.o: apple_driver.c mac_label.h
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/apple_driver.c
|
||||
|
||||
install: mkisofs mkisofs.8
|
||||
[ -d $(bindir) ] || mkdir $(bindir)
|
||||
[ -d $(mandir) ] || mkdir $(mandir)
|
||||
$(INSTALL_PROGRAM) mkhybrid $(bindir)/mkhybrid
|
||||
-$(INSTALL_DATA) $(srcdir)/mkhybrid.8 $(mandir)/mkhybrid.$(manext)
|
||||
|
||||
tree.o: tree.c mkisofs.h iso9660.h exclude.h config.h Makefile
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/tree.c
|
||||
|
||||
write.o: write.c mkisofs.h iso9660.h config.h Makefile
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/write.c
|
||||
|
||||
hash.o: hash.c mkisofs.h config.h Makefile
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/hash.c
|
||||
|
||||
rock.o: rock.c mkisofs.h iso9660.h config.h Makefile
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/rock.c
|
||||
|
||||
joliet.o: joliet.c mkisofs.h iso9660.h config.h Makefile
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/joliet.c
|
||||
|
||||
match.o: match.c match.h config.h Makefile
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/match.c
|
||||
|
||||
multi.o: multi.c iso9660.h mkisofs.h config.h Makefile
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/multi.c
|
||||
|
||||
name.o: name.c iso9660.h mkisofs.h config.h Makefile
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/name.c
|
||||
|
||||
mkisofs.o: mkisofs.c iso9660.h mkisofs.h exclude.h config.h Makefile $(LIBHFS) $(INCHFS) $(LIBFILE)
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/mkisofs.c
|
||||
|
||||
eltorito.o: eltorito.c iso9660.h mkisofs.h config.h Makefile
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/eltorito.c
|
||||
|
||||
apple.o: apple.c apple.h Makefile mkisofs.h
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/apple.c
|
||||
|
||||
volume.o: volume.c mkisofs.h config.h Makefile $(LIBHFS) $(INCHFS)
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/volume.c
|
||||
|
||||
desktop.o: desktop.c mkisofs.h config.h Makefile $(LIBHFS) $(INCHFS)
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/desktop.c
|
||||
|
||||
mac_label.o: mac_label.c mac_label.h Makefile config.h mkisofs.h
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/mac_label.c
|
||||
|
||||
$(LIBHFS) ::
|
||||
cd $(libhfsdir) && $(MAKE) CC="$(CC)" COPTS="$(COPTS)" DEFINES="$(DEFINES)" RANLIB="$(RANLIB)"
|
||||
|
||||
$(LIBFILE) ::
|
||||
cd $(libfiledir) && $(MAKE) CC="$(CC)" COPTS="$(COPTS)" DEFINES="$(DEFINES)" RANLIB="$(RANLIB)"
|
||||
|
||||
clean:
|
||||
/bin/rm -f *.o core mkhybrid apple_driver *~ #*#
|
||||
/bin/rm -f config.status config.log config.cache config.h
|
||||
(cd diag/; make clean)
|
||||
(cd $(libhfsdir); make clean)
|
||||
(cd $(libfiledir); make clean)
|
||||
|
||||
#
|
||||
# All .h files except for config.h get copied.
|
||||
#
|
||||
dist: Makefile
|
||||
(mydir=`basename \`pwd\``;\
|
||||
cd .. && tar -cvvf - $$mydir/README $$mydir/README.eltorito \
|
||||
$$mydir/configure.in $$mydir/configure $$mydir/config.h.in \
|
||||
$$mydir/Makefile.in $$mydir/make.com $$mydir/TODO \
|
||||
$$mydir/COPYING $$mydir/ChangeLog $$mydir/*.8 $$mydir/*.c \
|
||||
$$mydir/mkisofs.spec $$mydir/acconfig.h \
|
||||
$$mydir/install-sh $$mydir/[d-z]*.h \
|
||||
$$mydir/README.session $$mydir/diag/Makefile.in \
|
||||
$$mydir/diag/README $$mydir/diag/*.c $$mydir/diag/isoinfo.8 \
|
||||
$$mydir/include/*.h | gzip -9 > $${mydir}.tar.gz)
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
Please start by reading the file README.mkhybrid
|
||||
|
||||
[The original README file for mkisofs is README.mkisofs]
|
|
@ -0,0 +1,97 @@
|
|||
# Id: README.eltorito,v 1.1 2000/10/10 20:40:10 beck Exp
|
||||
What is El Torito?
|
||||
------------------
|
||||
Simply put, El Torito is a specification that says how a cdrom should
|
||||
be formatted such that you can directly boot from it.
|
||||
|
||||
The "El Torito" spec says that ANY cdrom drive should work (scsi/eide)
|
||||
as long as the BIOS supports El Torito. So far this has only been
|
||||
tested with EIDE drives because none of the scsi controllers that has
|
||||
been tested so far appears to support El Torito. The motherboard
|
||||
definately has to support El Torito. The ones that do let you choose
|
||||
booting from HD, Floppy, Network or CDROM.
|
||||
|
||||
How To Make Bootable CDs
|
||||
------------------------
|
||||
|
||||
For the x86 platform, many BIOS's have begun to support bootable CDs.
|
||||
The standard my patches for mkisofs is based on is called "El Torito".
|
||||
|
||||
The "El Torito" standard works by making the CD drive appear, through BIOS
|
||||
calls, to be a normal floppy drive. This way you simply put an floppy
|
||||
size image (exactly 1440k for a 1.44 meg floppy) somewhere in the
|
||||
iso fs. In the headers of the iso fs you place a pointer to this image.
|
||||
The BIOS will then grab this image from the CD and for all purposes it
|
||||
acts as if it were booting from the floppy drive. This allows a working
|
||||
LILO boot disk, for example, to simply be used as is.
|
||||
|
||||
It is simple then to make a bootable CD. First create a file, say "boot.img"
|
||||
which is an exact image of the boot floppu currently in use. There is
|
||||
at least one HOWTO on making bootable floppies. If you have a bootable
|
||||
floppy handy, you can make a boot image with the command
|
||||
|
||||
dd if=/dev/fd0 of=boot.img bs=10k count=144
|
||||
|
||||
assuming the floppy is in the A: drive.
|
||||
|
||||
Place this image somewhere in the hierarchy which will be the source
|
||||
for the iso9660 filesystem. It is a good idea to put all boot related
|
||||
files in their own directory ("boot/" under the root of the iso9660 fs,
|
||||
for example), but this is not necessary.
|
||||
|
||||
One caveat - Your boot floppy MUST load any initial ramdisk via LILO,
|
||||
not the kernel ramdisk driver! This is because once the linux kernel
|
||||
starts up, the BIOS emulation of the CD as a floppy disk is circumvented
|
||||
and will fail miserably. LILO will load the initial ramdisk using BIOS
|
||||
disk calls, so the emulation works as designed.
|
||||
|
||||
The "El Torito" specification requires a "boot catalog" to be created as
|
||||
ll.
|
||||
This is a 2048 byte file which is of no interest except it is required.
|
||||
My patches to mkisofs will cause it to automatically create the
|
||||
boot catalog. You must specify where the boot catalog will go in the
|
||||
iso9660 filesystem. Usually it is a good idea to put it the same place
|
||||
as the boot image, and a name like "boot.catalog" seems appropriate.
|
||||
|
||||
|
||||
So we have our boot image in the file "boot.image", and we are going to
|
||||
put it in the directory "boot/" under the root of the iso9660 filesystem.
|
||||
We will have the boot catalog go in the same directory with the name
|
||||
"boot.catalog". The command to create the iso9660 fs in the file
|
||||
bootcd.iso is then
|
||||
|
||||
mkisofs -b boot/boot.imh -c boot/boot.catalog -o bootcd.iso .
|
||||
|
||||
The -b option specifies the boot image to be used (note the path is
|
||||
relative to the root of the iso9660 disc), and the -c option is
|
||||
for the boot catalog file.
|
||||
|
||||
Now burn the CD and its ready to boot!
|
||||
|
||||
CAVEATS
|
||||
-------
|
||||
|
||||
I don't think this will work with multisession CDs.
|
||||
|
||||
If your bootable floppy image needs to access the boot floppy, it has
|
||||
to do so through BIOS calls. This is because if your O/S tries to talk to
|
||||
the floppy directly it will bypass the "floppy emulation" the El Torito spec
|
||||
creates through BIOS. For example, under Linux it is possible to
|
||||
have an initial RAM disk loaded when the kernel starts up. If you let the
|
||||
kernel try to read in the initial RAM disk from floppy, it will fail
|
||||
miserably because Linux is not using BIOS calls to access the floppy drive.
|
||||
Instead of seeing the floppy image on the CD, Linux will be looking at
|
||||
the actually floppy drive.
|
||||
|
||||
The solution is to have the initial boot loader, called LILO, load your
|
||||
initial RAM disk for you. LILO uses BIOS calls entirely for these
|
||||
operations, so it can grab it from the emulated floppy image.
|
||||
|
||||
I don't think making a CD bootable renders it unreadable by non-El Torito
|
||||
machines. The El Torito spec uses parts of the iso9660 filesystem which
|
||||
were reserved for future use, so no existing code should care what it does.
|
||||
|
||||
Mkisofs currently stores identification records in the iso9660 filesystem
|
||||
saying that the system is a x86 system. The El Torito spec also allows
|
||||
one to write PowerPC or Mac id's instead. If you look at the code in write.c
|
||||
you could figure out how to change what is written.
|
|
@ -0,0 +1,66 @@
|
|||
Making HFS bootable CDs
|
||||
|
||||
It *may* be possible to make the hybrid CD bootable on a Mac. As I do not
|
||||
have easy access to a CD-R (nor a Mac) at the moment, I have not actually
|
||||
created and written a bootable hybrid to CD - however, I *think* it will work!
|
||||
|
||||
A bootable HFS CD requires an Apple CD-ROM (or compatible) driver, a bootable
|
||||
HFS partition and the necessary System, Finder, etc. files.
|
||||
|
||||
A driver can be obtained from any other Mac bootable CD-ROM using the
|
||||
"apple_driver" utility (to make, type "make apple_driver"). This file can
|
||||
then be used with the -boot-hfs-file option. See below for usage.
|
||||
|
||||
The HFS partition (i.e. the hybrid disk in our case) must contain a
|
||||
suitable System Folder, again from another CD-ROM or disk.
|
||||
|
||||
For a partition to be bootable, it must have it's "boot block" set. The boot
|
||||
block is in the first two blocks of a partition. For a non-bootable partition
|
||||
the boot block is full of zeros. Normally, when a System file is copied to
|
||||
partition on a Mac disk, the boot block is filled with a number of required
|
||||
settings - unfortunately I don't know the full spec for the boot block ...
|
||||
|
||||
I'm guessing that this will work OK ...
|
||||
|
||||
Therefore, the utility "apple_driver" also extracts the boot block from the
|
||||
first HFS partition it finds on the given CD-ROM and this is used for the
|
||||
HFS partition created by mkhybrid.
|
||||
|
||||
To extract the driver and boot block:
|
||||
|
||||
apple_driver CDROM_device > HFS_driver_file
|
||||
|
||||
where CDROM_device is the device name used by the CD-ROM (e.g. /dev/cdrom)
|
||||
|
||||
The format of the HFS driver file is:
|
||||
|
||||
HFS CD Label Block 512 bytes
|
||||
Driver Partition Map (for 2048 byte blocks) 512 bytes
|
||||
Driver Partition Map (for 512 byte blocks) 512 bytes
|
||||
Empty 512 bytes
|
||||
Driver Partition N x 2048 bytes
|
||||
HFS Partition Boot Block 1024 bytes
|
||||
|
||||
The Perl script "hdisk.pl" can be used to give a listing of what's on
|
||||
a Mac CD. hdisk.pl is part of hfsutils.
|
||||
|
||||
A hybrid CD is made using the option "-boot-hfs-file" e.g.
|
||||
|
||||
mkhybrid -boot-hfs-file HFS_driver_file -o hfs.raw src_files/
|
||||
|
||||
The -boot-hfs-file implies the -hfs option.
|
||||
|
||||
PLEASE NOTE:
|
||||
|
||||
By using a driver from an Apple CD and copying Apple software to your CD,
|
||||
you become liable to obey Apple Computer, Inc. Software License Agreements.
|
||||
|
||||
The driver code (both extracting the driver and creating partitions etc.
|
||||
is based on code from "mkisofs 1.05 PLUS" by Andy Polyakov
|
||||
<appro@fy.chalmers.se> (see http://fy.chalmers.se/~appro/mkisofs_plus.html)
|
||||
|
||||
|
||||
Any comments, bug reports/fixes to the address below
|
||||
|
||||
James Pearson (j.pearson@ge.ucl.ac.uk)
|
||||
18/5/98
|
|
@ -0,0 +1,69 @@
|
|||
|
||||
Find file types by using a modified "magic" file
|
||||
|
||||
Based on file v3.22 by Ian F. Darwin (see libfile/LEGAL.NOTICE and
|
||||
libfile/README.dist - File v3.22 can be found at many archive sites)
|
||||
|
||||
For each entry in the magic file, the "message" for the initial offset MUST
|
||||
be 4 characters for the CREATOR and 4 characters for the TYPE - white space is
|
||||
optional between them. Any other characters on this line are ignored.
|
||||
Continuation lines (starting with a '>') are also ignored i.e. only the initial
|
||||
offset lines are used.
|
||||
|
||||
e.g magic entry for a GIF file:
|
||||
|
||||
# off type test message
|
||||
#
|
||||
# GIF image
|
||||
0 string GIF8 8BIM GIFf
|
||||
>4 string 7a \b, version 8%s,
|
||||
>4 string 9a \b, version 8%s,
|
||||
>6 leshort >0 %hd x
|
||||
>8 leshort >0 %hd,
|
||||
#>10 byte &0x80 color mapped,
|
||||
#>10 byte&0x07 =0x00 2 colors
|
||||
#>10 byte&0x07 =0x01 4 colors
|
||||
#>10 byte&0x07 =0x02 8 colors
|
||||
#>10 byte&0x07 =0x03 16 colors
|
||||
#>10 byte&0x07 =0x04 32 colors
|
||||
#>10 byte&0x07 =0x05 64 colors
|
||||
#>10 byte&0x07 =0x06 128 colors
|
||||
#>10 byte&0x07 =0x07 256 colors
|
||||
|
||||
Just the "8BIM" "GIFf" will be used whatever the type of GIF file it is.
|
||||
The continuation lines are used by the "file" command, but ignored by
|
||||
mkhybrid. They could be left out completely.
|
||||
|
||||
The complete format of the magic file is given in the magic man page (magic.5).
|
||||
|
||||
See the file "magic" for other examples
|
||||
|
||||
Use with the -magic magic_file option, where magic_file is a file
|
||||
described above.
|
||||
|
||||
The magic file can be used with the mapping file (option -map) - the order
|
||||
these options appear on the command line is important. mkhybrid will try to
|
||||
detect if the file is one of the Unix/Mac files (e.g. a CAP or Netatalk
|
||||
file) first. If that fails, it will then use the magic and/or mapping
|
||||
file e.g:
|
||||
|
||||
mkhybrid -o output.raw -map mapping -magic magic src_dir
|
||||
|
||||
The above will check filename extensions first, if that fails to set the
|
||||
CREATOR/TYPE, the magic file will be used. To check the magic file
|
||||
before the filename extensions, use:
|
||||
|
||||
mkhybrid -o output.raw -magic magic -map mapping src_dir
|
||||
|
||||
|
||||
Using just a magic file - filename extensions will not be checked e.g:
|
||||
|
||||
mkhybrid -o output.raw -magic magic src_dir
|
||||
|
||||
For the magic method to work, each file must be opened and read twice
|
||||
(once to find it's CREATOR/TYPE, and a second time to actually copy the
|
||||
file to the CD image). Therefore the -magic option may significantly
|
||||
increase processing time.
|
||||
|
||||
If a file's CREATOR/TYPE is not set via the magic and mapping matches,
|
||||
then the file is given the default CREATOR/TYPE.
|
|
@ -0,0 +1,108 @@
|
|||
|
||||
mkhybrid v1.12b5.1 - make ISO9660/HFS shared hybrid CD volume
|
||||
|
||||
HFS hybrid code Copyright (C) James Pearson 1997, 1998, 1999
|
||||
libhfs code Copyright (C) 1996, 1997 Robert Leslie
|
||||
libfile code Copyright (c) Ian F. Darwin 1986, 1987, 1989,
|
||||
1990, 1991, 1992, 1994, 1995
|
||||
mkisofs code Copyright 1993 Yggdrasil Computing, Incorporated
|
||||
|
||||
WARNING - this is Beta release code - please use with care!
|
||||
If you find a bug, please report it to the address given below.
|
||||
|
||||
This code is based on a Beta release of mkisofs, so there may be
|
||||
problems unrelated to my additions. However, I have found mkisofs
|
||||
v1.12b5 to be very stable.
|
||||
|
||||
However, many people are using v1.12, so although it's called a "beta"
|
||||
release, I would encourage people to use it ...
|
||||
Most of the HFS features work fine, however, some are not fully tested.
|
||||
These are marked as "Alpha" in the man page.
|
||||
|
||||
Please read the man page (mkhybrid.8, or mkhybrid_man.html) for information
|
||||
on how to use mkhybrid.
|
||||
|
||||
Also see "ChangeLog.mkhybrid" for any minor changes/bug fixes
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
mkhybrid is a pre-mastering utility that creates ISO9660/ROCKRIDGE/JOLIET/HFS
|
||||
hybrid CDROM images. You will have to use some other CD-R package to write
|
||||
the image to a CD.
|
||||
|
||||
INSTALLATION
|
||||
|
||||
To make/install, type "./configure", make any changes to the Makefile
|
||||
and type "make"
|
||||
|
||||
This has been tested with gcc on SunOS 4.1.3 (see below), gcc on Linux
|
||||
(Redhat v5.1), cc on IRIX 5.3/6.2 and gcc on Win95/WinNT4 using Cygnus'
|
||||
cygwin (see README.win32)
|
||||
|
||||
If you are using SunOS 4.1.[34], then you need the following patches
|
||||
to read CDs with associated files:
|
||||
|
||||
SunOS 4.1.3: Patch 101832-05
|
||||
SunOS 4.1.3_U1: Patch 101833-02
|
||||
SunOS 4.1.4: Patch 102583-02
|
||||
|
||||
|
||||
EXAMPLES
|
||||
|
||||
To create a HFS hybrid CD with the Joliet and Rock Ridge extensions or
|
||||
the source directory cd_dir:
|
||||
|
||||
% mkhybrid -o cd.iso -r -J -hfs cd_dir
|
||||
|
||||
To create a HFS hybrid CD from the source directory cd_dir that contains
|
||||
Netatalk Apple/Unix files:
|
||||
|
||||
% mkhybrid -o cd.iso --netatalk cd_dir
|
||||
|
||||
To create a HFS hybrid CD from the source directory cd_dir, giving all files
|
||||
CREATOR and TYPES based on just their filename extensions listed in the file
|
||||
"mapping".:
|
||||
|
||||
% mkhybrid -o cd.iso -no-mac-files -map mapping cd_dir
|
||||
|
||||
To create a CD with the 'Apple Extensions to ISO9660', from the source
|
||||
direcories cd_dir and another_dir. Files in all the known Apple/Unix format
|
||||
are decoded and any other files are given CREATOR and TYPE based on their
|
||||
magic number given in the file "magic":
|
||||
|
||||
% mkhybird -o cd.iso -magic -apple cd_dir another_dir
|
||||
|
||||
The following example puts different files on the CD that all have
|
||||
the name README, but have different contents when seen as a
|
||||
ISO9660/RockRidge Joliet or HFS CD.
|
||||
|
||||
Current directory contains
|
||||
|
||||
% ls -F
|
||||
README.hfs README.joliet README.unix cd_dir/
|
||||
|
||||
The following command puts the contents of the directory "cd_dir" on the
|
||||
CD along with the three README files - but only one will be seen from
|
||||
each of the three filesystems:
|
||||
|
||||
% mkhybrid -o cd.iso -hfs -J -r \
|
||||
-hide README.hfs -hide README.joliet \
|
||||
-hide-joliet README.hfs -hide-joliet README.unix \
|
||||
-hide-hfs README.joliet -hide-hfs README.unix \
|
||||
README=README.hfs README=README.joliet README=README.unix \
|
||||
cd_dir
|
||||
|
||||
i.e. the file README.hfs will be seen as README on the HFS CD and the
|
||||
other two README files will be hidden. Similarly for the Joliet and
|
||||
ISO9660/RockRidge CD.
|
||||
|
||||
There are probably all sorts of stange results possible with
|
||||
combinations of the hide options ...
|
||||
|
||||
|
||||
Any comments, bug reports/fixes to the address below.
|
||||
|
||||
Please state the version, platform and command line used when submitting
|
||||
a bug report - the output from "-log-file -v" would help.
|
||||
|
||||
James Pearson (j.pearson@ge.ucl.ac.uk)
|
|
@ -0,0 +1,145 @@
|
|||
# Id: README.mkisofs,v 1.1 2000/10/10 20:40:11 beck Exp
|
||||
Note:
|
||||
|
||||
This program requires a lot of virtual memory to run since it
|
||||
builds all of the directories in memory. The exact requirements
|
||||
depend upon a lot of things, but for Rock Ridge discs 12Mb would not
|
||||
be unreasonable. Without RockRidge and without the translation
|
||||
tables, the requirements would be considerably less.
|
||||
|
||||
The cdwrite utility is maintained separately from mkisofs by
|
||||
yggdrasil.com. It is enclosed here as a convenience, since the two programs
|
||||
are often useful together.
|
||||
|
||||
*****************************
|
||||
Notes for version 1.12
|
||||
|
||||
Joliet support is now complete. See the -J option.
|
||||
|
||||
The file scanning code is much improved - mkisofs can use multiple
|
||||
sources of input files and merge them together to form the output
|
||||
image. In addition, each source can be grafted at any point in the
|
||||
iso9660 image.
|
||||
|
||||
The image writing code has been cleaned up to make it much easier
|
||||
to add custom extensions.
|
||||
|
||||
The ADD_FILES feature has been removed as it didn't work well,
|
||||
and it was hard to figure out. The recent rearrangements in the
|
||||
file scanning code would tend to solve these issues.
|
||||
|
||||
*****************************
|
||||
Notes for version 1.11
|
||||
|
||||
There is a feature which can be optionally compiled into
|
||||
mkisofs that allows you to merge arbitrary directory trees into the
|
||||
image you are creating. You need to compile with -DADD_FILES for my
|
||||
changes to take effect. Thanks to Ross Biro biro@yggdrasil.com.
|
||||
|
||||
*****************************
|
||||
Notes for version 1.10b1
|
||||
|
||||
Big news is that multi-session capability is very close to being
|
||||
done. There is still a missing interface to cdwrite that is
|
||||
used to determine the next writable address and the sector number
|
||||
of the last existing session. Until we get the interface to cdwrite
|
||||
done, this is a beta version.
|
||||
|
||||
Bug involving DST fixed (dates are always calculated, since some
|
||||
files may be DST and other ones would not be).
|
||||
|
||||
Unfortunately the notes on some of the small patches got lost.
|
||||
|
||||
*****************************
|
||||
Notes for version 1.06
|
||||
|
||||
Jan-Piet Mens <jpm@mens.de> added support for the '-m' switch. This
|
||||
allows exclusion of shell-style globs from the CDROM.
|
||||
See manual mkisofs.8 for more information.
|
||||
|
||||
*****************************
|
||||
Notes for version 1.05
|
||||
|
||||
Added support for '-r' switch. This is very similar to -R for
|
||||
Rock Ridge, but echos of the development environment are removed
|
||||
(i.e. uid/gid set to 0, and permissions of the files are canonicalized).
|
||||
Useful in applications where a distribution medium is being produced.
|
||||
|
||||
*****************************
|
||||
Notes for version 1.04
|
||||
|
||||
No notes for 1.04.
|
||||
|
||||
*****************************
|
||||
Notes for version 1.03
|
||||
|
||||
No notes for 1.03.
|
||||
|
||||
*****************************
|
||||
Notes for version 1.02.
|
||||
|
||||
Minor bugfixes here and there. Support for compiled in
|
||||
defaults for many of the text fields in the volume header are now
|
||||
present, and there is also support for a file ".mkisofsrc" that can
|
||||
also read settings for these parameters.
|
||||
|
||||
A short script "Configure" was added to allow us to set up special
|
||||
compile options that depend upon the system that we are running on.
|
||||
This should help stamp out the sphaghetti-isms that were starting to grow
|
||||
up in various places in the code.
|
||||
|
||||
You should get more meaningful error messages if you run out of
|
||||
memory.
|
||||
|
||||
*****************************
|
||||
Notes for version 1.1.
|
||||
|
||||
The big news is that SUSP CE entries are now generated for
|
||||
extremely long filenames and symlink names. This virtually guarantees
|
||||
that there is no limit (OK, well, about 600Mb) for file name lengths.
|
||||
I have tested this as well as I can, and it seems to work with linux.
|
||||
This would only be used very rarely I suspect.
|
||||
|
||||
Also, I believe that support for VMS is done. You must be
|
||||
careful, because only Stream-LF and FIxed length record files can be
|
||||
recorded. The rest are rejected with error messages. Perhaps I am
|
||||
being too severe here.
|
||||
|
||||
There is a bugfix in the sorting of entries on the disc - we
|
||||
need to stop comparing once we reach the ';' character.
|
||||
|
||||
There are four new options -z -d -D -l -V. Some of these tell
|
||||
mkisofs to relax some of the iso9660 restrictions, and many systems
|
||||
apparently do not really seem to mind. Use these with caution.
|
||||
|
||||
Some diagnostic programs to scan disc images are in the diag
|
||||
directory. These are not as portable as mkisofs, and may have some
|
||||
bugs. Still they are useful because they can check for bugs that I might
|
||||
have introduced as I add new features.
|
||||
|
||||
*****************************
|
||||
Notes for version 1.0.
|
||||
|
||||
In version 1.0, the date fields in the TF fields were fixed -
|
||||
previously I was storing st_ctime as the file creation time instead of
|
||||
the file attribute change time. Thanks to Peter van der Veen for
|
||||
pointing this out. I have one slight concern with this change,
|
||||
however. The Young Minds software is definitely supplying 3 dates
|
||||
(creation, modification and access), and I would strongly suspect that
|
||||
they are incorrectly putting the file attribute change time in the
|
||||
file creation slot. I would be curious to see how the different RRIP
|
||||
filesystems treat this. Anyway, this is something to keep in the back
|
||||
of your mind.
|
||||
|
||||
The symlink handling was not quite correct in 0.99 - this is
|
||||
now fixed. Only some systems seemed to have been affected by this bug.
|
||||
|
||||
A command line option is now present to allow you to
|
||||
specifically exclude certain files from the distribution.
|
||||
|
||||
The case where you do not have permissions to read a directory
|
||||
is now handled better by mkisofs. The directory that cannot be opened
|
||||
is converted into a zero-length file, and processing continues normally.
|
||||
|
||||
A few portability things have been fixed (hopefully).
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
# Id: README.session,v 1.1 2000/10/10 20:40:11 beck Exp
|
||||
|
||||
This release of mkisofs has basic support completed for
|
||||
multiple sessions. However, we still need some interaction
|
||||
between cdrecord and mkisofs for this to work correctly. This is needed as
|
||||
only cdrecord knows the different ways to gather these numbers for all
|
||||
different drives. It may be that future versions of mkisofs will include
|
||||
the needed support for MMC compliant drives.
|
||||
|
||||
There are a few new options to mkisofs to allow for this.
|
||||
The first one is "-M /dev/scd0", and is used so that mkisofs can examine
|
||||
the entirety of the previous image so that it can figure out what additional
|
||||
files need to be written in the new session. Note that there are operating
|
||||
systems that don't allow to read from CD drives with a sector size
|
||||
of 2048 bytes per sector. To use mkisofs on such an operating system, you
|
||||
will need a version of mkisofs that includes the SCSI transport library
|
||||
from cdrecord. Simply use the dev= syntax from cdrecord with -M in
|
||||
such a case. It will tell mkisofs to use the SCSI transport library to
|
||||
read from the CD instead of using the standard read() OS interface.
|
||||
|
||||
There is also a temporary hack in mkisofs in the form of a '-C' option.
|
||||
The -C option takes two numbers as input, which are delimited by commas.
|
||||
For example, you could specify "-C 1000,1020", but you should never just
|
||||
make up numbers to use here. These numbers are determined from cdrecord.
|
||||
|
||||
Note that if you use -C and omit -M, it effectively means that
|
||||
you are writing a new session, starting at a non-zero block number,
|
||||
and you are effectively ignoring all of the previous session contents.
|
||||
When this session is sent to the writer, the new session effectively
|
||||
"erases" the previous session.
|
||||
|
||||
In practice you should be able to do something like:
|
||||
|
||||
mkisofs [other options] -C `cdrecord dev=b,t,l -msinfo` \
|
||||
-M /dev/cdblkdev
|
||||
|
||||
Replace 'b,t,l' by the aproriate numbers for SCSIbus, target and lun
|
||||
of your drive.
|
||||
|
||||
Note: As of the 1.12b5 release, the multi-session technology has
|
||||
matured quite significantly. It is entirely possible that bugs
|
||||
exists, or that further tweaks will be required somewhere along the
|
||||
way to get things working correctly. The data gathering mode of
|
||||
cdrecord has been tested, and I believe it works correctly. Caveat
|
||||
Emptor.
|
||||
|
||||
[Mar 1, 1999].
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
mkhybrid can be compiled on Win9X/NT4 using Cygnus' cygwin
|
||||
available from:
|
||||
|
||||
http://sourceware.cygnus.com/cygwin/
|
||||
|
||||
To build, start a "bash" shell (open a DOS/Command window, cd to the required
|
||||
directory and type "bash"), and type "./configure" and "make"
|
||||
|
||||
A pre-compiled current Win32 binary is available from:
|
||||
|
||||
ftp://ftp.ge.ucl.ac.uk/pub/mkhfs/win32
|
||||
|
||||
To use the pre-compiled binary, extract the files from the Zip archive, put
|
||||
the files cygwin1.dll, mount.exe and mkhybrid.exe in your WINDOWS directory
|
||||
and from a Command/MS-DOS window type mkhybrid for usage (also see
|
||||
mkhybrid_man.html).
|
||||
|
||||
mkhybrid is a Unix command line utility and knows nothing about DOS/WIN.
|
||||
Therefore all directory names are given in Unix format (i.e. use '/' for a
|
||||
directory separator, not '\'). To access files on another disk (i.e.
|
||||
floppy, CDROM and network disk), you need to use the supplied "mount"
|
||||
command e.g.
|
||||
|
||||
mount a: /a
|
||||
mount d: /cdrom
|
||||
|
||||
i.e. files on the floppy disk are accessed as being in directory /a and
|
||||
files on the CDROM are accessed as /cdrom (assuming your CDROM is drive d:)
|
||||
e.g. the following command creates a CD image in the current directory
|
||||
using a source directories on the CDROM drive, a sub-directory and the
|
||||
floppy drive:
|
||||
|
||||
mkhybrid -o hfs.iso -h -J -r /cdrom/subdir dir1 /a
|
||||
|
||||
Please note: Starting with v1.12b5.0 the Win32 executable uses the b20.1
|
||||
version of the cygwin DLL. If you are using an earlier version of mkhybrid,
|
||||
then you will need this DLL as well.
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# Id: TODO,v 1.1 2000/10/10 20:40:11 beck Exp
|
||||
1) Finish multiple paths. Update nlink count on directories if it is
|
||||
different than what stat returned. Save the nlink count that we store in
|
||||
the rock ridge attributes so know when we don't have to adjust it.
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
/* Definitions for mkisofs processed by autoheader. */
|
||||
|
||||
#undef NODIR /* none -- don't make numbered backup files */
|
||||
|
||||
/* This shows us where to find the major()/minor() macros */
|
||||
#undef MAJOR_IN_MKDEV
|
||||
#undef MAJOR_IN_SYSMACROS
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
** apple.h: cut down macfile.h from CAP distribution
|
||||
*/
|
||||
#ifndef _APPLE_H
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <mactypes.h>
|
||||
|
||||
#ifdef __sgi /* bit of a hack ... need to investigate further */
|
||||
#define __svr4__ /* maybe there's a "configure" solution ? */
|
||||
#endif /* __sgi */
|
||||
|
||||
#ifdef __svr4__
|
||||
#include <sys/statvfs.h>
|
||||
#else
|
||||
#if defined(__FreeBSD__) || defined(__bsdi__) || defined(__OpenBSD__)
|
||||
#include <sys/mount.h>
|
||||
#else
|
||||
#if defined(_IBMR2)
|
||||
#include <sys/statfs.h>
|
||||
#else
|
||||
#include <sys/vfs.h>
|
||||
#endif /* _IBMR2 */
|
||||
#endif /* __FreeBSD__ || __bsdi__ */
|
||||
#endif /* __svr4__ */
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif /* O_BINARY */
|
||||
|
||||
#ifdef _WIN32_TEST
|
||||
#undef UNICODE
|
||||
#include <windows.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#endif /* MIN */
|
||||
|
||||
#define CT_SIZE 4 /* Size of type/creator */
|
||||
#define NUMMAP 512 /* initial number of maps */
|
||||
#define BLANK " " /* blank type/creator */
|
||||
#define DEFMATCH "*" /* default mapping extension */
|
||||
|
||||
typedef struct {
|
||||
char *extn; /* filename extension */
|
||||
int elen; /* length of extension */
|
||||
char type[CT_SIZE+1]; /* extension type */
|
||||
char creator[CT_SIZE+1]; /* extension creator */
|
||||
unsigned short fdflags; /* finder flags */
|
||||
} afpmap;
|
||||
|
||||
/* from "data.h" - libhfs routines */
|
||||
unsigned long d_toutime(unsigned long);
|
||||
long d_getl(unsigned char *);
|
||||
short d_getw(unsigned char *);
|
||||
|
||||
#include "libfile/proto.h"
|
||||
|
||||
/****** TYPE_CAP ******/
|
||||
|
||||
/*
|
||||
* taken from the CAP distribution:
|
||||
* macfile.h - header file with Macintosh file definitions
|
||||
*
|
||||
* AppleTalk package for UNIX (4.2 BSD).
|
||||
*
|
||||
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
|
||||
* City of New York.
|
||||
*
|
||||
* Edit History:
|
||||
*
|
||||
* Sept 1987 Created by Charlie
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef USE_MAC_DATES
|
||||
#define USE_MAC_DATES
|
||||
#endif /* USE_MAC_DATES */
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef char sbyte;
|
||||
typedef unsigned short word;
|
||||
typedef short sword;
|
||||
typedef unsigned int dword;
|
||||
typedef int sdword;
|
||||
/*
|
||||
typedef unsigned long dword;
|
||||
typedef long sdword;
|
||||
*/
|
||||
|
||||
#define MAXCLEN 199 /* max size of a comment string */
|
||||
#define FINFOLEN 32 /* Finder info is 32 bytes */
|
||||
#define MAXMACFLEN 31 /* max Mac file name length */
|
||||
|
||||
typedef struct {
|
||||
/* base finder information */
|
||||
byte fdType[4]; /* File type [4]*/
|
||||
byte fdCreator[4]; /* File creator [8]*/
|
||||
word fdFlags; /* Finder flags [10]*/
|
||||
word fdLocation[2]; /* File's location [14] */
|
||||
word fdFldr; /* File's window [16] */
|
||||
/* extended finder information */
|
||||
word fdIconID; /* Icon ID [18] */
|
||||
word fdUnused[4]; /* Unused [26] */
|
||||
word fdComment; /* Comment ID [28] */
|
||||
dword fdPutAway; /* Home directory ID [32] */
|
||||
word fi_attr; /* attributes */
|
||||
#define FI_MAGIC1 255
|
||||
byte fi_magic1; /* was: length of comment */
|
||||
#define FI_VERSION 0x10 /* version major 1, minor 0 */
|
||||
/* if we have more than 8 versions wer're */
|
||||
/* doiong something wrong anyway */
|
||||
byte fi_version; /* version number */
|
||||
#define FI_MAGIC 0xda
|
||||
byte fi_magic; /* magic word check */
|
||||
byte fi_bitmap; /* bitmap of included info */
|
||||
#define FI_BM_SHORTFILENAME 0x1 /* is this included? */
|
||||
#define FI_BM_MACINTOSHFILENAME 0x2 /* is this included? */
|
||||
byte fi_shortfilename[12+1]; /* possible short file name */
|
||||
byte fi_macfilename[32+1]; /* possible macintosh file name */
|
||||
byte fi_comln; /* comment length */
|
||||
byte fi_comnt[MAXCLEN+1]; /* comment string */
|
||||
#ifdef USE_MAC_DATES
|
||||
byte fi_datemagic; /* sanity check */
|
||||
#define FI_MDATE 0x01 /* mtime & utime are valid */
|
||||
#define FI_CDATE 0x02 /* ctime is valid */
|
||||
byte fi_datevalid; /* validity flags */
|
||||
byte fi_ctime[4]; /* mac file create time */
|
||||
byte fi_mtime[4]; /* mac file modify time */
|
||||
byte fi_utime[4]; /* (real) time mtime was set */
|
||||
#endif /* USE_MAC_DATES */
|
||||
} FileInfo;
|
||||
|
||||
/* Atribute flags */
|
||||
#define FI_ATTR_SETCLEAR 0x8000 /* set-clear attributes */
|
||||
#define FI_ATTR_READONLY 0x20 /* file is read-only */
|
||||
#define FI_ATTR_ROPEN 0x10 /* resource fork in use */
|
||||
#define FI_ATTR_DOPEN 0x80 /* data fork in use */
|
||||
#define FI_ATTR_MUSER 0x2 /* multi-user */
|
||||
#define FI_ATTR_INVISIBLE 0x1 /* invisible */
|
||||
|
||||
/**** MAC STUFF *****/
|
||||
|
||||
/* Flags */
|
||||
#define FNDR_fOnDesk 0x1
|
||||
#define FNDR_fHasBundle 0x2000
|
||||
#define FNDR_fInvisible 0x4000
|
||||
/* locations */
|
||||
#define FNDR_fTrash -3 /* File in Trash */
|
||||
#define FNDR_fDesktop -2 /* File on desktop */
|
||||
#define FNDR_fDisk 0 /* File in disk window */
|
||||
|
||||
/****** TYPE_ESHARE ******/
|
||||
|
||||
/*
|
||||
** Information supplied by Jens-Uwe Mager (jum@helios.de)
|
||||
*/
|
||||
|
||||
#define ES_VERSION 0x0102
|
||||
#define ES_MAGIC 0x3681093
|
||||
#define ES_INFOLEN 32
|
||||
#define ES_INFO_SIZE 512
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint32;
|
||||
|
||||
typedef struct {
|
||||
uint32 magic;
|
||||
uint32 serno; /* written only, never read */
|
||||
uint16 version;
|
||||
uint16 attr; /* invisible... */
|
||||
uint16 openMax; /* max number of opens */
|
||||
uint16 filler0;
|
||||
uint32 backupCleared; /* time backup bit cleared */
|
||||
uint32 id; /* dir/file id */
|
||||
uint32 createTime; /* unix format */
|
||||
uint32 backupTime; /* unix format */
|
||||
/* uint8 finderInfo[INFOLEN];*/
|
||||
/* base finder information (compatible with CAP) */
|
||||
uint8 fdType[4]; /* File type [4]*/
|
||||
uint8 fdCreator[4]; /* File creator [8]*/
|
||||
uint16 fdFlags; /* Finder flags [10]*/
|
||||
uint16 fdLocation[2]; /* File's location [14] */
|
||||
uint16 fdFldr; /* File's window [16] */
|
||||
/* extended finder information */
|
||||
uint16 fdIconID; /* Icon ID [18] */
|
||||
uint16 fdUnused[4]; /* Unused [26] */
|
||||
uint16 fdComment; /* Comment ID [28] */
|
||||
uint32 fdPutAway; /* Home directory ID [32] */
|
||||
} es_FileInfo;
|
||||
|
||||
/****** TYPE_USHARE ******/
|
||||
|
||||
/* similar to the EtherShare layout, but the finder info stuff is different
|
||||
info provided by: Phil Sylvester <psylvstr@interaccess.com> */
|
||||
|
||||
typedef struct {
|
||||
uint8 fdType[4]; /* File type [4]*/
|
||||
uint8 fdCreator[4]; /* File creator [8]*/
|
||||
uint16 fdFlags; /* Finder flags [10]*/
|
||||
uint8 unknown1[22]; /* ignore [32] */
|
||||
uint32 btime; /* mac file backup time [36]*/
|
||||
uint8 unknown2[4]; /* ignore [40] */
|
||||
uint32 ctime; /* mac file create time [44]*/
|
||||
uint8 unknown3[8]; /* ignore [52] */
|
||||
uint32 mtime; /* mac file modify time [56]*/
|
||||
uint8 unknown4[456]; /* ignore [512] */
|
||||
} us_FileInfo;
|
||||
|
||||
/****** TYPE_DOUBLE, TYPE_SINGLE ******/
|
||||
|
||||
/*
|
||||
** Taken from cvt2cap (c) May 1988, Paul Campbell
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
dword id;
|
||||
dword offset;
|
||||
dword length;
|
||||
} a_entry;
|
||||
|
||||
typedef struct {
|
||||
dword magic;
|
||||
dword version;
|
||||
char home[16];
|
||||
word nentries;
|
||||
a_entry entries[1];
|
||||
} a_hdr;
|
||||
|
||||
#define A_HDR_SIZE 26
|
||||
#define A_ENTRY_SIZE sizeof(a_entry)
|
||||
|
||||
#define A_VERSION 0x00010000
|
||||
#define APPLE_SINGLE 0x00051600
|
||||
#define APPLE_DOUBLE 0x00051607
|
||||
#define ID_DATA 1
|
||||
#define ID_RESOURCE 2
|
||||
#define ID_NAME 3
|
||||
#define ID_FINDER 9
|
||||
|
||||
/****** TYPE_MACBIN ******/
|
||||
/*
|
||||
** taken from capit.c by Nigel Perry, np@doc.ic.ac.uk which is adapted
|
||||
** from unmacbin by John M. Sellens, jmsellens@watdragon.uwaterloo.ca
|
||||
*/
|
||||
|
||||
|
||||
#define MB_NAMELEN 63 /* maximum legal Mac file name length */
|
||||
#define MB_SIZE 128
|
||||
|
||||
/* Format of a bin file:
|
||||
A bin file is composed of 128 byte blocks. The first block is the
|
||||
info_header (see below). Then comes the data fork, null padded to fill the
|
||||
last block. Then comes the resource fork, padded to fill the last block. A
|
||||
proposal to follow with the text of the Get Info box has not been implemented,
|
||||
to the best of my knowledge. Version, zero1 and zero2 are what the receiving
|
||||
program looks at to determine if a MacBinary transfer is being initiated.
|
||||
*/
|
||||
typedef struct { /* info file header (128 bytes). Unfortunately, these
|
||||
longs don't align to word boundaries */
|
||||
byte version; /* there is only a version 0 at this time */
|
||||
byte nlen; /* Length of filename. */
|
||||
byte name[MB_NAMELEN]; /* Filename */
|
||||
byte type[4]; /* File type. */
|
||||
byte auth[4]; /* File creator. */
|
||||
byte flags; /* file flags: LkIvBnSyBzByChIt */
|
||||
byte zero1; /* Locked, Invisible,Bundle, System */
|
||||
/* Bozo, Busy, Changed, Init */
|
||||
byte icon_vert[2]; /* Vertical icon position within window */
|
||||
byte icon_horiz[2]; /* Horizontal icon postion in window */
|
||||
byte window_id[2]; /* Window or folder ID. */
|
||||
byte protect; /* = 1 for protected file, 0 otherwise */
|
||||
byte zero2;
|
||||
byte dflen[4]; /* Data Fork length (bytes) - most sig. */
|
||||
byte rflen[4]; /* Resource Fork length byte first */
|
||||
byte cdate[4]; /* File's creation date. */
|
||||
byte mdate[4]; /* File's "last modified" date. */
|
||||
byte ilen[2]; /* GetInfo message length */
|
||||
byte flags2; /* Finder flags, bits 0-7 */
|
||||
byte unused[14];
|
||||
byte packlen[4]; /* length of total files when unpacked */
|
||||
byte headlen[2]; /* length of secondary header */
|
||||
byte uploadvers; /* Version of MacBinary II that the uploading program is written for */
|
||||
byte readvers; /* Minimum MacBinary II version needed to read this file */
|
||||
byte crc[2]; /* CRC of the previous 124 bytes */
|
||||
byte padding[2]; /* two trailing unused bytes */
|
||||
} mb_info;
|
||||
|
||||
/*
|
||||
** An array useful for CRC calculations that use 0x1021 as the "seed"
|
||||
** taken from mcvert.c modified by Jim Van Verth.
|
||||
*/
|
||||
|
||||
static unsigned short mb_magic[] = {
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
|
||||
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
|
||||
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
|
||||
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
|
||||
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
|
||||
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
|
||||
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
|
||||
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
|
||||
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
|
||||
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
|
||||
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
|
||||
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
|
||||
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
|
||||
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
|
||||
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
|
||||
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
|
||||
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
|
||||
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
|
||||
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
|
||||
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
|
||||
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
|
||||
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
|
||||
};
|
||||
|
||||
|
||||
/****** TYPE_FE ******/
|
||||
|
||||
/* Information provided by Mark Weinstein <mrwesq@earthlink.net> */
|
||||
|
||||
typedef struct {
|
||||
byte nlen;
|
||||
byte name[31];
|
||||
byte type[4];
|
||||
byte creator[4];
|
||||
byte flags[2];
|
||||
byte location[4];
|
||||
byte fldr[2];
|
||||
byte xinfo[16];
|
||||
byte cdate[4];
|
||||
byte mdate[4];
|
||||
byte bdate[4];
|
||||
byte fileid[4];
|
||||
byte sname[8];
|
||||
byte ext[3];
|
||||
byte pad;
|
||||
} fe_info;
|
||||
|
||||
#define FE_SIZE 92
|
||||
|
||||
/****** TYPE_SGI ******/
|
||||
|
||||
typedef struct {
|
||||
char unknown1[8];
|
||||
char type[4];
|
||||
char creator[4];
|
||||
char unknown2[238];
|
||||
char name[32];
|
||||
char unknown3[14];
|
||||
} sgi_info;
|
||||
|
||||
#define SGI_SIZE 300
|
||||
|
||||
#define _APPLE_H
|
||||
#endif /* _APPLE_H */
|
|
@ -0,0 +1,35 @@
|
|||
/* apple_proto.h */
|
||||
/* $OpenBSD: apple_proto.h,v 1.1 2008/03/08 15:36:12 espie Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008 Marc Espie <espie@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef APPLE_PROTO_H
|
||||
#define APPLE_PROTO_H
|
||||
|
||||
struct directory_entry;
|
||||
struct hfs_info;
|
||||
|
||||
extern void hfs_init(char *, unsigned short, int, int, unsigned int);
|
||||
extern void clean_hfs(void);
|
||||
extern int hfs_exclude(char *);
|
||||
extern int get_hfs_rname(char *, char *, char *);
|
||||
extern int get_hfs_dir(char *, char *, struct directory_entry *);
|
||||
extern int get_hfs_info(char *, char *, struct directory_entry *);
|
||||
extern void print_hfs_info(struct directory_entry *);
|
||||
extern void delete_rsrc_ent(struct directory_entry *);
|
||||
extern void del_hfs_info(struct hfs_info *);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,67 @@
|
|||
/* config.h. Generated automatically by configure. */
|
||||
/* config.h.in. Generated automatically from configure.in by autoheader. */
|
||||
|
||||
/* Define to empty if the keyword does not work. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define if major, minor, and makedev are declared in <mkdev.h>. */
|
||||
/* #undef MAJOR_IN_MKDEV */
|
||||
|
||||
/* Define if major, minor, and makedev are declared in <sysmacros.h>. */
|
||||
/* #undef MAJOR_IN_SYSMACROS */
|
||||
|
||||
/* #undef NODIR */ /* none -- don't make numbered backup files */
|
||||
|
||||
/* This shows us where to find the major()/minor() macros */
|
||||
/* #undef MAJOR_IN_MKDEV */
|
||||
/* #undef MAJOR_IN_SYSMACROS */
|
||||
|
||||
/* Define if you have the memmove function. */
|
||||
#define HAVE_MEMMOVE 1
|
||||
|
||||
/* Define if you have the sbrk function. */
|
||||
#define HAVE_SBRK 1
|
||||
|
||||
/* Define if you have the <dirent.h> header file. */
|
||||
#define HAVE_DIRENT_H 1
|
||||
|
||||
/* Define if you have the <malloc.h> header file. */
|
||||
/* #undef HAVE_MALLOC_H */
|
||||
|
||||
/* Define if you have the <ndir.h> header file. */
|
||||
/* #undef HAVE_NDIR_H */
|
||||
|
||||
/* Define if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define if you have the <sys/dir.h> header file. */
|
||||
/* #undef HAVE_SYS_DIR_H */
|
||||
|
||||
/* Define if you have the <sys/fcntl.h> header file. */
|
||||
#define HAVE_SYS_FCNTL_H 1
|
||||
|
||||
/* Define if you have the <sys/mkdev.h> header file. */
|
||||
/* #undef HAVE_SYS_MKDEV_H */
|
||||
|
||||
/* Define if you have the <sys/ndir.h> header file. */
|
||||
/* #undef HAVE_SYS_NDIR_H */
|
||||
|
||||
/* Define if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define if you have the <sys/sysmacros.h> header file. */
|
||||
/* #undef HAVE_SYS_SYSMACROS_H */
|
||||
|
||||
/* Define if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define if you have the <termios.h> header file. */
|
||||
#define HAVE_TERMIOS_H 1
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
#define HAVE_FLOCK 1
|
|
@ -0,0 +1,64 @@
|
|||
/* config.h.in. Generated automatically from configure.in by autoheader. */
|
||||
|
||||
/* Define to empty if the keyword does not work. */
|
||||
#undef const
|
||||
|
||||
/* Define if major, minor, and makedev are declared in <mkdev.h>. */
|
||||
#undef MAJOR_IN_MKDEV
|
||||
|
||||
/* Define if major, minor, and makedev are declared in <sysmacros.h>. */
|
||||
#undef MAJOR_IN_SYSMACROS
|
||||
|
||||
#undef NODIR /* none -- don't make numbered backup files */
|
||||
|
||||
/* This shows us where to find the major()/minor() macros */
|
||||
#undef MAJOR_IN_MKDEV
|
||||
#undef MAJOR_IN_SYSMACROS
|
||||
|
||||
/* Define if you have the memmove function. */
|
||||
#undef HAVE_MEMMOVE
|
||||
|
||||
/* Define if you have the sbrk function. */
|
||||
#undef HAVE_SBRK
|
||||
|
||||
/* Define if you have the <dirent.h> header file. */
|
||||
#undef HAVE_DIRENT_H
|
||||
|
||||
/* Define if you have the <malloc.h> header file. */
|
||||
#undef HAVE_MALLOC_H
|
||||
|
||||
/* Define if you have the <ndir.h> header file. */
|
||||
#undef HAVE_NDIR_H
|
||||
|
||||
/* Define if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define if you have the <sys/dir.h> header file. */
|
||||
#undef HAVE_SYS_DIR_H
|
||||
|
||||
/* Define if you have the <sys/fcntl.h> header file. */
|
||||
#undef HAVE_SYS_FCNTL_H
|
||||
|
||||
/* Define if you have the <sys/mkdev.h> header file. */
|
||||
#undef HAVE_SYS_MKDEV_H
|
||||
|
||||
/* Define if you have the <sys/ndir.h> header file. */
|
||||
#undef HAVE_SYS_NDIR_H
|
||||
|
||||
/* Define if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define if you have the <sys/sysmacros.h> header file. */
|
||||
#undef HAVE_SYS_SYSMACROS_H
|
||||
|
||||
/* Define if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define if you have the <termios.h> header file. */
|
||||
#undef HAVE_TERMIOS_H
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,18 @@
|
|||
dnl Id: configure.in,v 1.1 2000/10/10 20:40:13 beck Exp
|
||||
dnl Modified for mkhybrid James Pearson 22/1/98
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(mkisofs.c)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PROG_CC
|
||||
AC_CONST
|
||||
AC_HEADER_MAJOR
|
||||
AC_HEADER_DIRENT
|
||||
if test -z "$ac_header_dirent"; then
|
||||
AC_DEFINE(NODIR)
|
||||
fi
|
||||
AC_CHECK_FUNCS(memmove sbrk strdup)
|
||||
AC_CHECK_HEADERS(sys/mkdev.h sys/sysmacros.h malloc.h termios.h sys/types.h)
|
||||
AC_CHECK_HEADERS(unistd.h string.h strings.h sys/stat.h sys/fcntl.h)
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_RANLIB
|
||||
AC_OUTPUT(Makefile diag/Makefile)
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Header file defaults.h - assorted default values for character strings in
|
||||
* the volume descriptor.
|
||||
*
|
||||
* Id: defaults.h,v 1.1 2000/10/10 20:40:13 beck Exp
|
||||
*/
|
||||
|
||||
#define PREPARER_DEFAULT NULL
|
||||
#define PUBLISHER_DEFAULT NULL
|
||||
#ifndef APPID_DEFAULT
|
||||
#define APPID_DEFAULT "MKHYBRID ISO9660/HFS FILESYSTEM BUILDER"
|
||||
#endif
|
||||
#define COPYRIGHT_DEFAULT NULL
|
||||
#define BIBLIO_DEFAULT NULL
|
||||
#define ABSTRACT_DEFAULT NULL
|
||||
#define VOLSET_ID_DEFAULT NULL
|
||||
#define VOLUME_ID_DEFAULT "CDROM"
|
||||
#define BOOT_CATALOG_DEFAULT "boot.catalog"
|
||||
#define BOOT_IMAGE_DEFAULT NULL
|
||||
#ifdef APPLE_HYB
|
||||
#define DEFTYPE "TEXT" /* default Apple TYPE */
|
||||
#define DEFCREATOR "unix" /* default Apple CREATOR */
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
#ifdef __QNX__
|
||||
#define SYSTEM_ID_DEFAULT "QNX"
|
||||
#endif
|
||||
|
||||
#ifdef __osf__
|
||||
#define SYSTEM_ID_DEFAULT "OSF"
|
||||
#endif
|
||||
|
||||
#ifdef __sun
|
||||
#ifdef __SVR4
|
||||
#define SYSTEM_ID_DEFAULT "Solaris"
|
||||
#else
|
||||
#define SYSTEM_ID_DEFAULT "SunOS"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __hpux
|
||||
#define SYSTEM_ID_DEFAULT "HP-UX"
|
||||
#endif
|
||||
|
||||
#ifdef __sgi
|
||||
#define SYSTEM_ID_DEFAULT "SGI"
|
||||
#endif
|
||||
|
||||
#ifdef _AIX
|
||||
#define SYSTEM_ID_DEFAULT "AIX"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN
|
||||
#define SYSTEM_ID_DEFAULT "Win32"
|
||||
#endif /* _WIN */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define SYSTEM_ID_DEFAULT "FreeBSD"
|
||||
#endif
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#define SYSTEM_ID_DEFAULT "OpenBSD"
|
||||
#endif
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#define SYSTEM_ID_DEFAULT "NetBSD"
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#define SYSTEM_ID_DEFAULT "LINUX"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define SYSTEM_ID_DEFAULT "FreeBSD"
|
||||
#endif
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#define SYSTEM_ID_DEFAULT "OpenBSD"
|
||||
#endif
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#define SYSTEM_ID_DEFAULT "NetBSD"
|
||||
#endif
|
||||
|
||||
#ifndef SYSTEM_ID_DEFAULT
|
||||
#define SYSTEM_ID_DEFAULT "Unknown"
|
||||
#endif
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
** make_desktop: create "Desktop DB" and "Desktop DF" files.
|
||||
**
|
||||
** These are set up to prevent the Mac "rebuilding the desktop"
|
||||
** when the CD is inserted ???
|
||||
**
|
||||
** I don't know if these files should be populated, but I've just
|
||||
** created these files in their initial states:
|
||||
**
|
||||
** Desktop DB: Initial size == volume's clump size
|
||||
** first block contents found by using od ...
|
||||
** rest of file seems to be padding
|
||||
** No resource fork
|
||||
**
|
||||
** Desktop DF: Empty
|
||||
**
|
||||
** If the files already exist, then set correct type/creator/flags
|
||||
**
|
||||
** James Pearson 11/8/97
|
||||
** Adapted from mkhfs routines for mkhybrid
|
||||
*/
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
#include "hfs.h"
|
||||
|
||||
#define DB "Desktop DB"
|
||||
#define DBFC "DMGR"
|
||||
#define DBT "BTFL"
|
||||
|
||||
#define DF "Desktop DF"
|
||||
#define DFT "DTFL"
|
||||
|
||||
/* from "data.h" - libhfs routines */
|
||||
void d_putw(unsigned char *, short);
|
||||
void d_putl(unsigned char *, long);
|
||||
|
||||
extern hce_mem *hce; /* libhfs/mkisofs extras */
|
||||
|
||||
int
|
||||
make_desktop(hfsvol *vol, int end)
|
||||
/* hfsvol *vol; Mac volume */
|
||||
{
|
||||
hfsfile *hfp; /* Mac file */
|
||||
hfsdirent ent; /* Mac finderinfo */
|
||||
unsigned short clps; /* clump size */
|
||||
unsigned short blks; /* blocks in a clump */
|
||||
unsigned char *blk; /* user data */
|
||||
|
||||
/* set up default directory entries - not all these fields
|
||||
are needed, but we'll set them up anyway ... */
|
||||
ent.rsize = 0; /* resource size == 0 */
|
||||
strcpy(ent.creator, DBFC); /* creator */
|
||||
strcpy(ent.type, DBT); /* type */
|
||||
ent.crdate = ent.mddate = time(0); /* date is now */
|
||||
ent.fdflags = HFS_FNDR_ISINVISIBLE; /* invisible files */
|
||||
|
||||
/* clear the DB file */
|
||||
blk = hce->hfs_ce + hce->hfs_ce_size*HFS_BLOCKSZ;
|
||||
blks = hce->hfs_dt_size;
|
||||
clps = blks*HFS_BLOCKSZ;
|
||||
|
||||
memset(blk, 0, clps);
|
||||
|
||||
/* create "Desktop DB" (if it doesn't exist) */
|
||||
if(hfs_create(vol, DB, ent.type, ent.creator) == 0)
|
||||
{
|
||||
/* DB file size from hce_mem info */
|
||||
/* set up "Desktop DB" data - following found by od'ing
|
||||
the "Desktop DB" file */
|
||||
d_putw(blk+8, 0x100);
|
||||
d_putw(blk+10, 0x3);
|
||||
|
||||
d_putw(blk+32, 0x200);
|
||||
d_putw(blk+34, 0x25);
|
||||
|
||||
d_putl(blk+36, blks);
|
||||
d_putl(blk+40, blks - 1);
|
||||
|
||||
d_putw(blk+48, clps);
|
||||
d_putw(blk+50, 0xff);
|
||||
|
||||
d_putw(blk+120, 0x20a);
|
||||
d_putw(blk+122, 0x100);
|
||||
|
||||
d_putw(blk+248, 0x8000);
|
||||
|
||||
d_putl(blk+504, 0x1f800f8);
|
||||
d_putl(blk+508, 0x78000e);
|
||||
|
||||
/* entries for "Desktop DB" */
|
||||
ent.dsize = clps; /* size = clump size */
|
||||
|
||||
/* open file */
|
||||
if((hfp = hfs_open(vol, DB)) == 0)
|
||||
err(1, hfs_error);
|
||||
|
||||
/* "write" file */
|
||||
write_fork(hfp, clps);
|
||||
|
||||
/* set DB file attributes */
|
||||
if (hfs_fsetattr(hfp, &ent) < 0)
|
||||
err(1, hfs_error);
|
||||
|
||||
/* find the real start of the file */
|
||||
end += hce->hfs_ce_size;
|
||||
|
||||
/* close DB file */
|
||||
if (hfs_close(hfp, end, 0) < 0)
|
||||
err(1, hfs_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if it already exists, then make sure it has the correct
|
||||
type/creator and flags */
|
||||
if(hfs_setattr(vol, DB, &ent) < 0)
|
||||
err(1, hfs_error);
|
||||
}
|
||||
|
||||
/* setup "Desktop DF" file as an empty file */
|
||||
strcpy(ent.type, DFT); /* type */
|
||||
ent.dsize = 0; /* empty */
|
||||
|
||||
/* create DF file (if it doesn't exist) - no need to open it */
|
||||
hfs_create(vol, DF, ent.type, ent.creator);
|
||||
|
||||
/* set DB file attributes */
|
||||
if (hfs_setattr(vol, DF, &ent) < 0)
|
||||
err(1, hfs_error);
|
||||
return 0;
|
||||
}
|
||||
#endif /* APPLE_HYB */
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
* Program eltorito.c - Handle El Torito specific extensions to iso9660.
|
||||
*
|
||||
|
||||
Written by Michael Fulbright <msf@redhat.com> (1996).
|
||||
|
||||
Copyright 1996 RedHat Software, 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 <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mkisofs.h"
|
||||
#include "iso9660.h"
|
||||
|
||||
/* used by Win32 for opening binary file - not used by Unix */
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif /* O_BINARY */
|
||||
|
||||
#undef MIN
|
||||
#define MIN(a, b) (((a) < (b))? (a): (b))
|
||||
|
||||
static struct eltorito_validation_entry valid_desc;
|
||||
static struct eltorito_defaultboot_entry default_desc;
|
||||
static struct eltorito_boot_descriptor gboot_desc;
|
||||
|
||||
static int tvd_write __PR((FILE * outfile));
|
||||
|
||||
/*
|
||||
* Check for presence of boot catalog. If it does not exist then make it
|
||||
*/
|
||||
void FDECL1(init_boot_catalog, const char *, path)
|
||||
{
|
||||
|
||||
int bcat;
|
||||
char * bootpath; /* filename of boot catalog */
|
||||
char * buf;
|
||||
struct stat statbuf;
|
||||
|
||||
bootpath = (char *) e_malloc(strlen(boot_catalog)+strlen(path)+2);
|
||||
strcpy(bootpath, path);
|
||||
if (bootpath[strlen(bootpath)-1] != '/')
|
||||
{
|
||||
strcat(bootpath,"/");
|
||||
}
|
||||
|
||||
strcat(bootpath, boot_catalog);
|
||||
|
||||
/*
|
||||
* check for the file existing
|
||||
*/
|
||||
#ifdef DEBUG_TORITO
|
||||
fprintf(stderr,"Looking for boot catalog file %s\n",bootpath);
|
||||
#endif
|
||||
|
||||
if (!stat_filter(bootpath, &statbuf))
|
||||
{
|
||||
/*
|
||||
* make sure its big enough to hold what we want
|
||||
*/
|
||||
if (statbuf.st_size == 2048)
|
||||
{
|
||||
/*
|
||||
* printf("Boot catalog exists, so we do nothing\n");
|
||||
*/
|
||||
free(bootpath);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "A boot catalog exists and appears corrupted.\n");
|
||||
fprintf(stderr, "Please check the following file: %s.\n",bootpath);
|
||||
fprintf(stderr, "This file must be removed before a bootable CD can be done.\n");
|
||||
free(bootpath);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* file does not exist, so we create it
|
||||
* make it one CD sector long
|
||||
*/
|
||||
bcat = open(bootpath, O_WRONLY | O_CREAT | O_BINARY, S_IROTH | S_IRGRP | S_IRWXU );
|
||||
if (bcat == -1)
|
||||
{
|
||||
fprintf(stderr, "Error creating boot catalog, exiting...\n");
|
||||
perror("");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
buf = (char *) e_malloc( 2048 );
|
||||
write(bcat, buf, 2048);
|
||||
close(bcat);
|
||||
free(bootpath);
|
||||
} /* init_boot_catalog(... */
|
||||
|
||||
void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
|
||||
{
|
||||
int bootcat;
|
||||
int checksum;
|
||||
unsigned char * checksum_ptr;
|
||||
struct directory_entry * de;
|
||||
struct directory_entry * de2;
|
||||
int i;
|
||||
int nsectors;
|
||||
|
||||
memset(boot_desc, 0, sizeof(*boot_desc));
|
||||
boot_desc->id[0] = 0;
|
||||
memcpy(boot_desc->id2, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID) - 1);
|
||||
boot_desc->version[0] = 1;
|
||||
|
||||
memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof(EL_TORITO_ID));
|
||||
|
||||
/*
|
||||
* search from root of iso fs to find boot catalog
|
||||
*/
|
||||
de2 = search_tree_file(root, boot_catalog);
|
||||
if (!de2)
|
||||
{
|
||||
fprintf(stderr,"Uh oh, I cant find the boot catalog!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
set_731(boot_desc->bootcat_ptr,
|
||||
(unsigned int) get_733(de2->isorec.extent));
|
||||
|
||||
/*
|
||||
* now adjust boot catalog
|
||||
* lets find boot image first
|
||||
*/
|
||||
de=search_tree_file(root, boot_image);
|
||||
if (!de)
|
||||
{
|
||||
fprintf(stderr,"Uh oh, I cant find the boot image!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* we have the boot image, so write boot catalog information
|
||||
* Next we write out the primary descriptor for the disc
|
||||
*/
|
||||
memset(&valid_desc, 0, sizeof(valid_desc));
|
||||
valid_desc.headerid[0] = 1;
|
||||
valid_desc.arch[0] = EL_TORITO_ARCH_x86;
|
||||
|
||||
/*
|
||||
* we'll shove start of publisher id into id field, may get truncated
|
||||
* but who really reads this stuff!
|
||||
*/
|
||||
if (publisher)
|
||||
memcpy_max(valid_desc.id, publisher, MIN(23, strlen(publisher)));
|
||||
|
||||
valid_desc.key1[0] = 0x55;
|
||||
valid_desc.key2[0] = 0xAA;
|
||||
|
||||
/*
|
||||
* compute the checksum
|
||||
*/
|
||||
checksum=0;
|
||||
checksum_ptr = (unsigned char *) &valid_desc;
|
||||
for (i=0; i<sizeof(valid_desc); i+=2)
|
||||
{
|
||||
/*
|
||||
* skip adding in ckecksum word, since we dont have it yet!
|
||||
*/
|
||||
if (i == 28)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
checksum += (unsigned int)checksum_ptr[i];
|
||||
checksum += ((unsigned int)checksum_ptr[i+1])*256;
|
||||
}
|
||||
|
||||
/*
|
||||
* now find out the real checksum
|
||||
*/
|
||||
checksum = -checksum;
|
||||
set_721(valid_desc.cksum, (unsigned int) checksum);
|
||||
|
||||
/*
|
||||
* now make the initial/default entry for boot catalog
|
||||
*/
|
||||
memset(&default_desc, 0, sizeof(default_desc));
|
||||
default_desc.boot_id[0] = EL_TORITO_BOOTABLE;
|
||||
|
||||
/*
|
||||
* use default BIOS loadpnt
|
||||
*/
|
||||
set_721(default_desc.loadseg, 0);
|
||||
default_desc.arch[0] = EL_TORITO_ARCH_x86;
|
||||
|
||||
/*
|
||||
* figure out size of boot image in sectors, for now hard code to
|
||||
* assume 512 bytes/sector on a bootable floppy
|
||||
*/
|
||||
nsectors = ((de->size + 511) & ~(511))/512;
|
||||
#ifdef APPLE_HYB
|
||||
/* NON-HFS change */
|
||||
if (verbose > 0 )
|
||||
#endif /* APPLE_HYB */
|
||||
fprintf(stderr, "\nSize of boot image is %d sectors -> ", nsectors);
|
||||
|
||||
/*
|
||||
* choose size of emulated floppy based on boot image size
|
||||
*/
|
||||
if (nsectors == 2880 )
|
||||
{
|
||||
default_desc.boot_media[0] = EL_TORITO_MEDIA_144FLOP;
|
||||
#ifdef APPLE_HYB
|
||||
/* NON-HFS change */
|
||||
if (verbose > 0 )
|
||||
#endif /* APPLE_HYB */
|
||||
fprintf(stderr, "Emulating a 1.44 meg floppy\n");
|
||||
}
|
||||
else if (nsectors == 5760 )
|
||||
{
|
||||
default_desc.boot_media[0] = EL_TORITO_MEDIA_288FLOP;
|
||||
#ifdef APPLE_HYB
|
||||
/* NON-HFS change */
|
||||
if (verbose > 0 )
|
||||
#endif /* APPLE_HYB */
|
||||
fprintf(stderr,"Emulating a 2.88 meg floppy\n");
|
||||
}
|
||||
else if (nsectors == 2400 )
|
||||
{
|
||||
default_desc.boot_media[0] = EL_TORITO_MEDIA_12FLOP;
|
||||
#ifdef APPLE_HYB
|
||||
/* NON-HFS change */
|
||||
if (verbose > 0 )
|
||||
#endif /* APPLE_HYB */
|
||||
fprintf(stderr,"Emulating a 1.2 meg floppy\n");
|
||||
}
|
||||
else if (nsectors == 4 )
|
||||
{
|
||||
default_desc.boot_media[0] = EL_TORITO_MEDIA_NOEMUL;
|
||||
#ifdef APPLE_HYB
|
||||
/* NON-HFS change */
|
||||
if (verbose > 0 )
|
||||
#endif /* APPLE_HYB */
|
||||
fprintf(stderr,"No-emulation CD boot sector\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"\nError - boot image is not the an allowable size.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FOR NOW LOAD 1 SECTOR, JUST LIKE FLOPPY BOOT, unless it's no-emulation
|
||||
* boot.
|
||||
*/
|
||||
if (default_desc.boot_media[0] != EL_TORITO_MEDIA_NOEMUL)
|
||||
nsectors = 1;
|
||||
set_721(default_desc.nsect, (unsigned int) nsectors );
|
||||
#ifdef DEBUG_TORITO
|
||||
fprintf(stderr,"Extent of boot images is %d\n",get_733(de->isorec.extent));
|
||||
#endif
|
||||
set_731(default_desc.bootoff,
|
||||
(unsigned int) get_733(de->isorec.extent));
|
||||
|
||||
/*
|
||||
* now write it to disk
|
||||
*/
|
||||
bootcat = open(de2->whole_name, O_RDWR | O_BINARY);
|
||||
if (bootcat == -1)
|
||||
{
|
||||
fprintf(stderr,"Error opening boot catalog for update.\n");
|
||||
perror("");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* write out
|
||||
*/
|
||||
write(bootcat, &valid_desc, 32);
|
||||
write(bootcat, &default_desc, 32);
|
||||
close(bootcat);
|
||||
} /* get_torito_desc(... */
|
||||
|
||||
/*
|
||||
* Function to write the EVD for the disc.
|
||||
*/
|
||||
static int FDECL1(tvd_write, FILE *, outfile)
|
||||
{
|
||||
/*
|
||||
* Next we write out the boot volume descriptor for the disc
|
||||
*/
|
||||
get_torito_desc(&gboot_desc);
|
||||
xfwrite(&gboot_desc, 1, 2048, outfile);
|
||||
last_extent_written ++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write};
|
|
@ -0,0 +1,760 @@
|
|||
/* Getopt for GNU.
|
||||
NOTE: getopt is now part of the C library, so if you don't know what
|
||||
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
|
||||
before changing it!
|
||||
|
||||
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the libiberty library. This library is free
|
||||
software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if you link this library with files
|
||||
compiled with a GNU compiler to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
|
||||
Ditto for AIX 3.2 and <stdlib.h>. */
|
||||
#ifndef _NO_PROTO
|
||||
#define _NO_PROTO
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#if defined (emacs) || defined (CONFIG_BROKETS)
|
||||
/* We use <config.h> instead of "config.h" so that a compilation
|
||||
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
|
||||
(which it would do because it found this file in $srcdir). */
|
||||
#include <config.h>
|
||||
#else
|
||||
#include "config.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __STDC__
|
||||
/* This is a separate conditional since some stdc systems
|
||||
reject `defined (const)'. */
|
||||
#ifndef const
|
||||
#define const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
/* Many versions of the Linux C library include older, broken versions
|
||||
of these routines, which will break the linker's command-line
|
||||
parsing. */
|
||||
|
||||
#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__)
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#if defined(__GNU_LIBRARY__) || defined(__OpenBSD__)
|
||||
/* Don't include stdlib.h for non-GNU C libraries because some of them
|
||||
contain conflicting prototypes for getopt. */
|
||||
#include <stdlib.h>
|
||||
#endif /* GNU C library. */
|
||||
|
||||
/* This version of `getopt' appears to the caller like standard Unix `getopt'
|
||||
but it behaves differently for the user, since it allows the user
|
||||
to intersperse the options with the other arguments.
|
||||
|
||||
As `getopt' works, it permutes the elements of ARGV so that,
|
||||
when it is done, all the options precede everything else. Thus
|
||||
all application programs are extended to handle flexible argument order.
|
||||
|
||||
Setting the environment variable POSIXLY_CORRECT disables permutation.
|
||||
Then the behavior is completely standard.
|
||||
|
||||
GNU application programs can use a third alternative mode in which
|
||||
they can distinguish the relative order of options and other arguments. */
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
char *optarg = NULL;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns EOF, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
/* XXX 1003.2 says this must be 1 before any call. */
|
||||
int optind = 0;
|
||||
|
||||
/* The next char to be scanned in the option-element
|
||||
in which the last option character we returned was found.
|
||||
This allows us to pick up the scan where we left off.
|
||||
|
||||
If this is zero, or a null string, it means resume the scan
|
||||
by advancing to the next ARGV-element. */
|
||||
|
||||
static char *nextchar;
|
||||
|
||||
/* Callers store zero here to inhibit the error message
|
||||
for unrecognized options. */
|
||||
|
||||
int opterr = 1;
|
||||
|
||||
/* Set to an option character which was unrecognized.
|
||||
This must be initialized on some systems to avoid linking in the
|
||||
system's own getopt implementation. */
|
||||
|
||||
int optopt = '?';
|
||||
|
||||
/* Describe how to deal with options that follow non-option ARGV-elements.
|
||||
|
||||
If the caller did not specify anything,
|
||||
the default is REQUIRE_ORDER if the environment variable
|
||||
POSIXLY_CORRECT is defined, PERMUTE otherwise.
|
||||
|
||||
REQUIRE_ORDER means don't recognize them as options;
|
||||
stop option processing when the first non-option is seen.
|
||||
This is what Unix does.
|
||||
This mode of operation is selected by either setting the environment
|
||||
variable POSIXLY_CORRECT, or using `+' as the first character
|
||||
of the list of option characters.
|
||||
|
||||
PERMUTE is the default. We permute the contents of ARGV as we scan,
|
||||
so that eventually all the non-options are at the end. This allows options
|
||||
to be given in any order, even with programs that were not written to
|
||||
expect this.
|
||||
|
||||
RETURN_IN_ORDER is an option available to programs that were written
|
||||
to expect options and other ARGV-elements in any order and that care about
|
||||
the ordering of the two. We describe each non-option ARGV-element
|
||||
as if it were the argument of an option with character code 1.
|
||||
Using `-' as the first character of the list of option characters
|
||||
selects this mode of operation.
|
||||
|
||||
The special argument `--' forces an end of option-scanning regardless
|
||||
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
|
||||
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
|
||||
|
||||
static enum
|
||||
{
|
||||
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
|
||||
} ordering;
|
||||
|
||||
#if defined(__GNU_LIBRARY__) || defined(__OpenBSD__)
|
||||
/* We want to avoid inclusion of string.h with non-GNU libraries
|
||||
because there are many ways it can cause trouble.
|
||||
On some systems, it contains special magic macros that don't work
|
||||
in GCC. */
|
||||
#include <string.h>
|
||||
#define my_index strchr
|
||||
#else
|
||||
|
||||
/* Avoid depending on library functions or files
|
||||
whose names are inconsistent. */
|
||||
|
||||
char *getenv ();
|
||||
|
||||
static char *
|
||||
my_index (str, chr)
|
||||
const char *str;
|
||||
int chr;
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
if (*str == chr)
|
||||
return (char *) str;
|
||||
str++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If using GCC, we can safely declare strlen this way.
|
||||
If not using GCC, it is ok not to declare it. */
|
||||
#ifdef __GNUC__
|
||||
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
|
||||
That was relevant to code that was here before. */
|
||||
#ifndef __STDC__
|
||||
/* gcc with -traditional declares the built-in strlen to return int,
|
||||
and has done so at least since version 2.4.5. -- rms. */
|
||||
extern int strlen (const char *);
|
||||
#endif /* not __STDC__ */
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#endif /* not __GNU_LIBRARY__ */
|
||||
|
||||
/* Handle permutation of arguments. */
|
||||
|
||||
/* Describe the part of ARGV that contains non-options that have
|
||||
been skipped. `first_nonopt' is the index in ARGV of the first of them;
|
||||
`last_nonopt' is the index after the last of them. */
|
||||
|
||||
static int first_nonopt;
|
||||
static int last_nonopt;
|
||||
|
||||
/* Exchange two adjacent subsequences of ARGV.
|
||||
One subsequence is elements [first_nonopt,last_nonopt)
|
||||
which contains all the non-options that have been skipped so far.
|
||||
The other is elements [last_nonopt,optind), which contains all
|
||||
the options processed since those non-options were skipped.
|
||||
|
||||
`first_nonopt' and `last_nonopt' are relocated so that they describe
|
||||
the new indices of the non-options in ARGV after they are moved. */
|
||||
|
||||
static void
|
||||
exchange (argv)
|
||||
char **argv;
|
||||
{
|
||||
int bottom = first_nonopt;
|
||||
int middle = last_nonopt;
|
||||
int top = optind;
|
||||
char *tem;
|
||||
|
||||
/* Exchange the shorter segment with the far end of the longer segment.
|
||||
That puts the shorter segment into the right place.
|
||||
It leaves the longer segment in the right place overall,
|
||||
but it consists of two parts that need to be swapped next. */
|
||||
|
||||
while (top > middle && middle > bottom)
|
||||
{
|
||||
if (top - middle > middle - bottom)
|
||||
{
|
||||
/* Bottom segment is the short one. */
|
||||
int len = middle - bottom;
|
||||
register int i;
|
||||
|
||||
/* Swap it with the top part of the top segment. */
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
tem = argv[bottom + i];
|
||||
argv[bottom + i] = argv[top - (middle - bottom) + i];
|
||||
argv[top - (middle - bottom) + i] = tem;
|
||||
}
|
||||
/* Exclude the moved bottom segment from further swapping. */
|
||||
top -= len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Top segment is the short one. */
|
||||
int len = top - middle;
|
||||
register int i;
|
||||
|
||||
/* Swap it with the bottom part of the bottom segment. */
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
tem = argv[bottom + i];
|
||||
argv[bottom + i] = argv[middle + i];
|
||||
argv[middle + i] = tem;
|
||||
}
|
||||
/* Exclude the moved top segment from further swapping. */
|
||||
bottom += len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update records for the slots the non-options now occupy. */
|
||||
|
||||
first_nonopt += (optind - last_nonopt);
|
||||
last_nonopt = optind;
|
||||
}
|
||||
|
||||
/* Initialize the internal data when the first call is made. */
|
||||
|
||||
static const char *
|
||||
_getopt_initialize (optstring)
|
||||
const char *optstring;
|
||||
{
|
||||
/* Start processing options with ARGV-element 1 (since ARGV-element 0
|
||||
is the program name); the sequence of previously skipped
|
||||
non-option ARGV-elements is empty. */
|
||||
|
||||
first_nonopt = last_nonopt = optind = 1;
|
||||
|
||||
nextchar = NULL;
|
||||
|
||||
/* Determine how to handle the ordering of options and nonoptions. */
|
||||
|
||||
if (optstring[0] == '-')
|
||||
{
|
||||
ordering = RETURN_IN_ORDER;
|
||||
++optstring;
|
||||
}
|
||||
else if (optstring[0] == '+')
|
||||
{
|
||||
ordering = REQUIRE_ORDER;
|
||||
++optstring;
|
||||
}
|
||||
else if (getenv ("POSIXLY_CORRECT") != NULL)
|
||||
ordering = REQUIRE_ORDER;
|
||||
else
|
||||
ordering = PERMUTE;
|
||||
|
||||
return optstring;
|
||||
}
|
||||
|
||||
/* Scan elements of ARGV (whose length is ARGC) for option characters
|
||||
given in OPTSTRING.
|
||||
|
||||
If an element of ARGV starts with '-', and is not exactly "-" or "--",
|
||||
then it is an option element. The characters of this element
|
||||
(aside from the initial '-') are option characters. If `getopt'
|
||||
is called repeatedly, it returns successively each of the option characters
|
||||
from each of the option elements.
|
||||
|
||||
If `getopt' finds another option character, it returns that character,
|
||||
updating `optind' and `nextchar' so that the next call to `getopt' can
|
||||
resume the scan with the following option character or ARGV-element.
|
||||
|
||||
If there are no more option characters, `getopt' returns `EOF'.
|
||||
Then `optind' is the index in ARGV of the first ARGV-element
|
||||
that is not an option. (The ARGV-elements have been permuted
|
||||
so that those that are not options now come last.)
|
||||
|
||||
OPTSTRING is a string containing the legitimate option characters.
|
||||
If an option character is seen that is not listed in OPTSTRING,
|
||||
return '?' after printing an error message. If you set `opterr' to
|
||||
zero, the error message is suppressed but we still return '?'.
|
||||
|
||||
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
|
||||
so the following text in the same ARGV-element, or the text of the following
|
||||
ARGV-element, is returned in `optarg'. Two colons mean an option that
|
||||
wants an optional arg; if there is text in the current ARGV-element,
|
||||
it is returned in `optarg', otherwise `optarg' is set to zero.
|
||||
|
||||
If OPTSTRING starts with `-' or `+', it requests different methods of
|
||||
handling the non-option ARGV-elements.
|
||||
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
|
||||
|
||||
Long-named options begin with `--' instead of `-'.
|
||||
Their names may be abbreviated as long as the abbreviation is unique
|
||||
or is an exact match for some defined option. If they have an
|
||||
argument, it follows the option name in the same ARGV-element, separated
|
||||
from the option name by a `=', or else the in next ARGV-element.
|
||||
When `getopt' finds a long-named option, it returns 0 if that option's
|
||||
`flag' field is nonzero, the value of the option's `val' field
|
||||
if the `flag' field is zero.
|
||||
|
||||
The elements of ARGV aren't really const, because we permute them.
|
||||
But we pretend they're const in the prototype to be compatible
|
||||
with other systems.
|
||||
|
||||
LONGOPTS is a vector of `struct option' terminated by an
|
||||
element containing a name which is zero.
|
||||
|
||||
LONGIND returns the index in LONGOPT of the long-named option found.
|
||||
It is only valid when a long-named option has been found by the most
|
||||
recent call.
|
||||
|
||||
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
|
||||
long-named options. */
|
||||
|
||||
int
|
||||
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *optstring;
|
||||
const struct option *longopts;
|
||||
int *longind;
|
||||
int long_only;
|
||||
{
|
||||
optarg = NULL;
|
||||
|
||||
if (optind == 0)
|
||||
optstring = _getopt_initialize (optstring);
|
||||
|
||||
if (argc == 0)
|
||||
return EOF;
|
||||
|
||||
if (nextchar == NULL || *nextchar == '\0')
|
||||
{
|
||||
/* Advance to the next ARGV-element. */
|
||||
|
||||
if (ordering == PERMUTE)
|
||||
{
|
||||
/* If we have just processed some options following some non-options,
|
||||
exchange them so that the options come first. */
|
||||
|
||||
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
||||
exchange ((char **) argv);
|
||||
else if (last_nonopt != optind)
|
||||
first_nonopt = optind;
|
||||
|
||||
/* Skip any additional non-options
|
||||
and extend the range of non-options previously skipped. */
|
||||
|
||||
while (optind < argc
|
||||
&& (argv[optind][0] != '-' || argv[optind][1] == '\0'))
|
||||
optind++;
|
||||
last_nonopt = optind;
|
||||
}
|
||||
|
||||
/* The special ARGV-element `--' means premature end of options.
|
||||
Skip it like a null option,
|
||||
then exchange with previous non-options as if it were an option,
|
||||
then skip everything else like a non-option. */
|
||||
|
||||
if (optind != argc && !strcmp (argv[optind], "--"))
|
||||
{
|
||||
optind++;
|
||||
|
||||
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
||||
exchange ((char **) argv);
|
||||
else if (first_nonopt == last_nonopt)
|
||||
first_nonopt = optind;
|
||||
last_nonopt = argc;
|
||||
|
||||
optind = argc;
|
||||
}
|
||||
|
||||
/* If we have done all the ARGV-elements, stop the scan
|
||||
and back over any non-options that we skipped and permuted. */
|
||||
|
||||
if (optind == argc)
|
||||
{
|
||||
/* Set the next-arg-index to point at the non-options
|
||||
that we previously skipped, so the caller will digest them. */
|
||||
if (first_nonopt != last_nonopt)
|
||||
optind = first_nonopt;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* If we have come to a non-option and did not permute it,
|
||||
either stop the scan or describe it to the caller and pass it by. */
|
||||
|
||||
if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
|
||||
{
|
||||
if (ordering == REQUIRE_ORDER)
|
||||
return EOF;
|
||||
optarg = argv[optind++];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We have found another option-ARGV-element.
|
||||
Skip the initial punctuation. */
|
||||
|
||||
nextchar = (argv[optind] + 1
|
||||
+ (longopts != NULL && argv[optind][1] == '-'));
|
||||
}
|
||||
|
||||
/* Decode the current option-ARGV-element. */
|
||||
|
||||
/* Check whether the ARGV-element is a long option.
|
||||
|
||||
If long_only and the ARGV-element has the form "-f", where f is
|
||||
a valid short option, don't consider it an abbreviated form of
|
||||
a long option that starts with f. Otherwise there would be no
|
||||
way to give the -f short option.
|
||||
|
||||
On the other hand, if there's a long option "fubar" and
|
||||
the ARGV-element is "-fu", do consider that an abbreviation of
|
||||
the long option, just like "--fu", and not "-f" with arg "u".
|
||||
|
||||
This distinction seems to be the most useful approach. */
|
||||
|
||||
if (longopts != NULL
|
||||
&& (argv[optind][1] == '-'
|
||||
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
|
||||
{
|
||||
char *nameend;
|
||||
const struct option *p;
|
||||
const struct option *pfound = NULL;
|
||||
int exact = 0;
|
||||
int ambig = 0;
|
||||
int indfound;
|
||||
int option_index;
|
||||
|
||||
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
|
||||
/* Do nothing. */ ;
|
||||
|
||||
/* Test all long options for either exact match
|
||||
or abbreviated matches. */
|
||||
for (p = longopts, option_index = 0; p->name; p++, option_index++)
|
||||
if (!strncmp (p->name, nextchar, nameend - nextchar))
|
||||
{
|
||||
if (nameend - nextchar == strlen (p->name))
|
||||
{
|
||||
/* Exact match found. */
|
||||
pfound = p;
|
||||
indfound = option_index;
|
||||
exact = 1;
|
||||
break;
|
||||
}
|
||||
else if (pfound == NULL)
|
||||
{
|
||||
/* First nonexact match found. */
|
||||
pfound = p;
|
||||
indfound = option_index;
|
||||
}
|
||||
else
|
||||
/* Second or later nonexact match found. */
|
||||
ambig = 1;
|
||||
}
|
||||
|
||||
if (ambig && !exact)
|
||||
{
|
||||
if (opterr)
|
||||
fprintf (stderr, "%s: option `%s' is ambiguous\n",
|
||||
argv[0], argv[optind]);
|
||||
nextchar += strlen (nextchar);
|
||||
optind++;
|
||||
return '?';
|
||||
}
|
||||
|
||||
if (pfound != NULL)
|
||||
{
|
||||
option_index = indfound;
|
||||
optind++;
|
||||
if (*nameend)
|
||||
{
|
||||
/* Don't test has_arg with >, because some C compilers don't
|
||||
allow it to be used on enums. */
|
||||
if (pfound->has_arg)
|
||||
optarg = nameend + 1;
|
||||
else
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
if (argv[optind - 1][1] == '-')
|
||||
/* --option */
|
||||
fprintf (stderr,
|
||||
"%s: option `--%s' doesn't allow an argument\n",
|
||||
argv[0], pfound->name);
|
||||
else
|
||||
/* +option or -option */
|
||||
fprintf (stderr,
|
||||
"%s: option `%c%s' doesn't allow an argument\n",
|
||||
argv[0], argv[optind - 1][0], pfound->name);
|
||||
}
|
||||
nextchar += strlen (nextchar);
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
else if (pfound->has_arg == 1)
|
||||
{
|
||||
if (optind < argc)
|
||||
optarg = argv[optind++];
|
||||
else
|
||||
{
|
||||
if (opterr)
|
||||
fprintf (stderr, "%s: option `%s' requires an argument\n",
|
||||
argv[0], argv[optind - 1]);
|
||||
nextchar += strlen (nextchar);
|
||||
return optstring[0] == ':' ? ':' : '?';
|
||||
}
|
||||
}
|
||||
nextchar += strlen (nextchar);
|
||||
if (longind != NULL)
|
||||
*longind = option_index;
|
||||
if (pfound->flag)
|
||||
{
|
||||
*(pfound->flag) = pfound->val;
|
||||
return 0;
|
||||
}
|
||||
return pfound->val;
|
||||
}
|
||||
|
||||
/* Can't find it as a long option. If this is not getopt_long_only,
|
||||
or the option starts with '--' or is not a valid short
|
||||
option, then it's an error.
|
||||
Otherwise interpret it as a short option. */
|
||||
if (!long_only || argv[optind][1] == '-'
|
||||
|| my_index (optstring, *nextchar) == NULL)
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
if (argv[optind][1] == '-')
|
||||
/* --option */
|
||||
fprintf (stderr, "%s: unrecognized option `--%s'\n",
|
||||
argv[0], nextchar);
|
||||
else
|
||||
/* +option or -option */
|
||||
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
|
||||
argv[0], argv[optind][0], nextchar);
|
||||
}
|
||||
nextchar = (char *) "";
|
||||
optind++;
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
/* Look at and handle the next short option-character. */
|
||||
|
||||
{
|
||||
char c = *nextchar++;
|
||||
char *temp = my_index (optstring, c);
|
||||
|
||||
/* Increment `optind' when we start to process its last character. */
|
||||
if (*nextchar == '\0')
|
||||
++optind;
|
||||
|
||||
if (temp == NULL || c == ':')
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
/* 1003.2 specifies the format of this message. */
|
||||
fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
|
||||
}
|
||||
optopt = c;
|
||||
return '?';
|
||||
}
|
||||
if (temp[1] == ':')
|
||||
{
|
||||
if (temp[2] == ':')
|
||||
{
|
||||
/* This is an option that accepts an argument optionally. */
|
||||
if (*nextchar != '\0')
|
||||
{
|
||||
optarg = nextchar;
|
||||
optind++;
|
||||
}
|
||||
else
|
||||
optarg = NULL;
|
||||
nextchar = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is an option that requires an argument. */
|
||||
if (*nextchar != '\0')
|
||||
{
|
||||
optarg = nextchar;
|
||||
/* If we end this ARGV-element by taking the rest as an arg,
|
||||
we must advance to the next element now. */
|
||||
optind++;
|
||||
}
|
||||
else if (optind == argc)
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
/* 1003.2 specifies the format of this message. */
|
||||
fprintf (stderr, "%s: option requires an argument -- %c\n",
|
||||
argv[0], c);
|
||||
}
|
||||
optopt = c;
|
||||
if (optstring[0] == ':')
|
||||
c = ':';
|
||||
else
|
||||
c = '?';
|
||||
}
|
||||
else
|
||||
/* We already incremented `optind' once;
|
||||
increment it again when taking next ARGV-elt as argument. */
|
||||
optarg = argv[optind++];
|
||||
nextchar = NULL;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
getopt (argc, argv, optstring)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *optstring;
|
||||
{
|
||||
return _getopt_internal (argc, argv, optstring,
|
||||
(const struct option *) 0,
|
||||
(int *) 0,
|
||||
0);
|
||||
}
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
/* Compile with -DTEST to make an executable for use in testing
|
||||
the above definition of `getopt'. */
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int this_option_optind = optind ? optind : 1;
|
||||
|
||||
c = getopt (argc, argv, "abc:d:0123456789");
|
||||
if (c == EOF)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
||||
printf ("digits occur in two different argv-elements.\n");
|
||||
digit_optind = this_option_optind;
|
||||
printf ("option %c\n", c);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
printf ("option a\n");
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf ("option b\n");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printf ("option c with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("?? getopt returned character code 0%o ??\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
printf ("non-option ARGV-elements: ");
|
||||
while (optind < argc)
|
||||
printf ("%s ", argv[optind++]);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
|
@ -0,0 +1,129 @@
|
|||
/* Declarations for getopt.
|
||||
Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _GETOPT_H
|
||||
#define _GETOPT_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
extern char *optarg;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns EOF, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
extern int optind;
|
||||
|
||||
/* Callers store zero here to inhibit the error message `getopt' prints
|
||||
for unrecognized options. */
|
||||
|
||||
extern int opterr;
|
||||
|
||||
/* Set to an option character which was unrecognized. */
|
||||
|
||||
extern int optopt;
|
||||
|
||||
/* Describe the long-named options requested by the application.
|
||||
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
|
||||
of `struct option' terminated by an element containing a name which is
|
||||
zero.
|
||||
|
||||
The field `has_arg' is:
|
||||
no_argument (or 0) if the option does not take an argument,
|
||||
required_argument (or 1) if the option requires an argument,
|
||||
optional_argument (or 2) if the option takes an optional argument.
|
||||
|
||||
If the field `flag' is not NULL, it points to a variable that is set
|
||||
to the value given in the field `val' when the option is found, but
|
||||
left unchanged if the option is not found.
|
||||
|
||||
To have a long-named option do something other than set an `int' to
|
||||
a compiled-in constant, such as set a value from `optarg', set the
|
||||
option's `flag' field to zero and its `val' field to a nonzero
|
||||
value (the equivalent single-letter option character, if there is
|
||||
one). For long options that have a zero `flag' field, `getopt'
|
||||
returns the contents of the `val' field. */
|
||||
|
||||
struct option
|
||||
{
|
||||
#if __STDC__
|
||||
const char *name;
|
||||
#else
|
||||
char *name;
|
||||
#endif
|
||||
/* has_arg can't be an enum because some compilers complain about
|
||||
type mismatches in all the code that assumes it is an int. */
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
/* Names for the values of the `has_arg' field of `struct option'. */
|
||||
|
||||
#define no_argument 0
|
||||
#define required_argument 1
|
||||
#define optional_argument 2
|
||||
|
||||
#if __STDC__
|
||||
#if defined(__GNU_LIBRARY__)
|
||||
/* Many other libraries have conflicting prototypes for getopt, with
|
||||
differences in the consts, in stdlib.h. To avoid compilation
|
||||
errors, only prototype getopt for the GNU C library. */
|
||||
extern int getopt (int argc, char *const *argv, const char *shortopts);
|
||||
#else /* not __GNU_LIBRARY__ */
|
||||
extern int getopt ();
|
||||
#endif /* not __GNU_LIBRARY__ */
|
||||
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
|
||||
const struct option *longopts, int *longind);
|
||||
extern int getopt_long_only (int argc, char *const *argv,
|
||||
const char *shortopts,
|
||||
const struct option *longopts, int *longind);
|
||||
|
||||
/* Internal only. Users should not call this directly. */
|
||||
extern int _getopt_internal (int argc, char *const *argv,
|
||||
const char *shortopts,
|
||||
const struct option *longopts, int *longind,
|
||||
int long_only);
|
||||
#else /* not __STDC__ */
|
||||
extern int getopt ();
|
||||
extern int getopt_long ();
|
||||
extern int getopt_long_only ();
|
||||
|
||||
extern int _getopt_internal ();
|
||||
#endif /* not __STDC__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GETOPT_H */
|
|
@ -0,0 +1,190 @@
|
|||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#if defined (emacs) || defined (CONFIG_BROKETS)
|
||||
/* We use <config.h> instead of "config.h" so that a compilation
|
||||
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
|
||||
(which it would do because it found this file in $srcdir). */
|
||||
#include <config.h>
|
||||
#else
|
||||
#include "config.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
#ifndef __STDC__
|
||||
/* This is a separate conditional since some stdc systems
|
||||
reject `defined (const)'. */
|
||||
#ifndef const
|
||||
#define const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
/* Many versions of the Linux C library include older, broken versions
|
||||
of these routines, which will break the linker's command-line
|
||||
parsing. */
|
||||
|
||||
#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__)
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
char *getenv ();
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
int
|
||||
getopt_long (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
|
||||
}
|
||||
|
||||
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
|
||||
If an option that starts with '-' (not '--') doesn't match a long option,
|
||||
but does match a short option, it is parsed as a short option
|
||||
instead. */
|
||||
|
||||
int
|
||||
getopt_long_only (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
|
||||
}
|
||||
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int this_option_optind = optind ? optind : 1;
|
||||
int option_index = 0;
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"add", 1, 0, 0},
|
||||
{"append", 0, 0, 0},
|
||||
{"delete", 1, 0, 0},
|
||||
{"verbose", 0, 0, 0},
|
||||
{"create", 0, 0, 0},
|
||||
{"file", 1, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "abc:d:0123456789",
|
||||
long_options, &option_index);
|
||||
if (c == EOF)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
printf ("option %s", long_options[option_index].name);
|
||||
if (optarg)
|
||||
printf (" with arg %s", optarg);
|
||||
printf ("\n");
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
||||
printf ("digits occur in two different argv-elements.\n");
|
||||
digit_optind = this_option_optind;
|
||||
printf ("option %c\n", c);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
printf ("option a\n");
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf ("option b\n");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printf ("option c with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
printf ("option d with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("?? getopt returned character code 0%o ??\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
printf ("non-option ARGV-elements: ");
|
||||
while (optind < argc)
|
||||
printf ("%s ", argv[optind++]);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* 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 "config.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 > 1) fprintf(stderr,"%s ",spnt->name);
|
||||
#endif
|
||||
s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash));
|
||||
s_hash->next = hash_table[hash_number];
|
||||
s_hash->inode = spnt->inode;
|
||||
s_hash->dev = spnt->dev;
|
||||
s_hash->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;
|
||||
}
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
/* based on flush_file_hash() below - needed as we wnat to re-use the
|
||||
file hash table */
|
||||
void flush_hash(){
|
||||
struct file_hash * fh, *fh1;
|
||||
int i;
|
||||
|
||||
for(i=0; i<NR_HASH; i++) {
|
||||
fh = hash_table[i];
|
||||
while(fh) {
|
||||
fh1 = fh->next;
|
||||
free(fh);
|
||||
fh = fh1;
|
||||
}
|
||||
hash_table[i] = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
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,};
|
||||
|
||||
/*
|
||||
* Find the hash bucket for this name.
|
||||
*/
|
||||
static unsigned int FDECL1(name_hash, const char *, name)
|
||||
{
|
||||
unsigned int hash = 0;
|
||||
const char * p;
|
||||
|
||||
p = name;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
/*
|
||||
* Don't hash the iso9660 version number. This way
|
||||
* we can detect duplicates in cases where we have
|
||||
* directories (i.e. foo) and non-directories
|
||||
* (i.e. foo;1).
|
||||
*/
|
||||
if( *p == ';' )
|
||||
{
|
||||
break;
|
||||
}
|
||||
hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++;
|
||||
}
|
||||
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;
|
||||
char * p1;
|
||||
char * p2;
|
||||
|
||||
for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
|
||||
{
|
||||
p1 = name;
|
||||
p2 = nh->de->isorec.name;
|
||||
|
||||
/*
|
||||
* Look for end of string, or a mismatch.
|
||||
*/
|
||||
while(1==1)
|
||||
{
|
||||
if( (*p1 == '\0' || *p1 == ';')
|
||||
|| (*p2 == '\0' || *p2 == ';')
|
||||
|| (*p1 != *p2) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
p1++;
|
||||
p2++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are at the end of both strings, then
|
||||
* we have a match.
|
||||
*/
|
||||
if( (*p1 == '\0' || *p1 == ';')
|
||||
&& (*p2 == '\0' || *p2 == ';') )
|
||||
{
|
||||
return nh->de;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* @(#)fctldefs.h 1.2 98/10/08 Copyright 1996 J. Schilling */
|
||||
/*
|
||||
* Generic header for users of open(), creat() and chmod()
|
||||
*
|
||||
* Copyright (c) 1996 J. Schilling
|
||||
*/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _FCTLDEFS_H
|
||||
#define _FCTLDEFS_H
|
||||
|
||||
#ifndef _MCONFIG_H
|
||||
#include <mconfig.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
|
||||
# include <fcntl.h>
|
||||
|
||||
#else /* HAVE_FCNTL_H */
|
||||
|
||||
# include <sys/file.h>
|
||||
|
||||
#endif /* HAVE_FCNTL_H */
|
||||
|
||||
/*
|
||||
* Do not define more than O_RDONLY / O_WRONLY / O_RDWR
|
||||
* The values may differ.
|
||||
*/
|
||||
#ifndef O_RDONLY
|
||||
#define O_RDONLY 0
|
||||
#endif
|
||||
#ifndef O_WRONLY
|
||||
#define O_WRONLY 1
|
||||
#endif
|
||||
#ifndef O_RDWR
|
||||
#define O_RDWR 2
|
||||
#endif
|
||||
|
||||
#endif /* _FCTLDEFS_H */
|
|
@ -0,0 +1,268 @@
|
|||
/* @(#)mconfig.h 1.24 98/12/14 Copyright 1995 J. Schilling */
|
||||
/*
|
||||
* definitions for machine configuration
|
||||
*
|
||||
* Copyright (c) 1995 J. Schilling
|
||||
*
|
||||
* This file must be included before any other file.
|
||||
* Use only cpp instructions.
|
||||
*
|
||||
* NOTE: SING: (Schily Is Not Gnu)
|
||||
*/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _MCONFIG_H
|
||||
#define _MCONFIG_H
|
||||
|
||||
/*
|
||||
* This hack that is needed as long as VMS has no POSIX shell.
|
||||
*/
|
||||
#ifdef VMS
|
||||
# define USE_STATIC_CONF
|
||||
#endif
|
||||
|
||||
#ifdef VANILLA_AUTOCONF
|
||||
#include <config.h>
|
||||
#else
|
||||
#ifdef USE_STATIC_CONF
|
||||
#include <xmconfig.h> /* This is the current static autoconf stuff */
|
||||
#else
|
||||
#include <xconfig.h> /* This is the current dynamic autoconf stuff */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(unix) || defined(__unix) || defined(__unix__)
|
||||
# define IS_UNIX
|
||||
#endif
|
||||
|
||||
#ifdef __MSDOS__
|
||||
# define IS_MSDOS
|
||||
#endif
|
||||
|
||||
#if defined(tos) || defined(__tos)
|
||||
# define IS_TOS
|
||||
#endif
|
||||
|
||||
#ifdef THINK_C
|
||||
# define IS_MAC
|
||||
#endif
|
||||
|
||||
#if defined(sun) || defined(__sun) || defined(__sun__)
|
||||
# define IS_SUN
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN32__)
|
||||
# define IS_GCC_WIN32
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Some magic that cannot (yet) be figured out with autoconf.
|
||||
*/
|
||||
|
||||
#ifdef sparc
|
||||
# ifndef HAVE_LDSTUB
|
||||
# define HAVE_LDSTUB
|
||||
# endif
|
||||
# ifndef HAVE_SCANSTACK
|
||||
# define HAVE_SCANSTACK
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__i386_) || defined(i386)
|
||||
# ifndef HAVE_XCHG
|
||||
# define HAVE_XCHG
|
||||
# endif
|
||||
# ifndef HAVE_SCANSTACK
|
||||
# define HAVE_SCANSTACK
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(SOL2) || defined(SOL2) || defined(S5R4) || defined(__S5R4) \
|
||||
|| defined(SVR4)
|
||||
# ifndef __SVR4
|
||||
# define __SVR4
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __SVR4
|
||||
# ifndef SVR4
|
||||
# define SVR4
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SunOS 4.x / SunOS 5.x
|
||||
*/
|
||||
#if defined(IS_SUN)
|
||||
# define HAVE_GETAV0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* AIX
|
||||
*/
|
||||
#if defined(_IBMR2) || defined(_AIX)
|
||||
# define IS_UNIX /* ??? really ??? */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Silicon Graphics (must be before SVR4)
|
||||
*/
|
||||
#if defined(sgi) || defined(__sgi)
|
||||
# define __NOT_SVR4__ /* Not a real SVR4 implementation */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Data General
|
||||
*/
|
||||
#if defined(__DGUX__)
|
||||
#ifdef XXXXXXX
|
||||
# undef HAVE_MTGET_DSREG
|
||||
# undef HAVE_MTGET_RESID
|
||||
# undef HAVE_MTGET_FILENO
|
||||
# undef HAVE_MTGET_BLKNO
|
||||
#endif
|
||||
# define mt_type mt_model
|
||||
# define mt_dsreg mt_status1
|
||||
# define mt_erreg mt_status2
|
||||
/*
|
||||
* DGUX hides its flock as dg_flock.
|
||||
*/
|
||||
# define HAVE_FLOCK
|
||||
# define flock dg_flock
|
||||
/*
|
||||
* Use the BSD style wait on DGUX to get the resource usages of child
|
||||
* processes.
|
||||
*/
|
||||
# define _BSD_WAIT_FLAVOR
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Apple Rhapsody
|
||||
*/
|
||||
#if defined(__NeXT__) && defined(__TARGET_OSNAME) && __TARGET_OSNAME == rhapsody
|
||||
# define HAVE_OSDEF /* prevent later definitions to overwrite current */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NextStep
|
||||
*/
|
||||
#if defined(__NeXT__) && !defined(HAVE_OSDEF)
|
||||
#define NO_PRINT_OVR
|
||||
#undef HAVE_USG_STDIO /*
|
||||
* NeXT Step 3.x uses __flsbuf(unsigned char , FILE *)
|
||||
* instead of __flsbuf(int, FILE *)
|
||||
*/
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NextStep 3.x has a broken linker that does not allow us to override
|
||||
* these functions.
|
||||
*/
|
||||
#ifndef __OPRINTF__
|
||||
|
||||
#ifdef NO_PRINT_OVR
|
||||
# define printf Xprintf
|
||||
# define fprintf Xfprintf
|
||||
# define sprintf Xsprintf
|
||||
#endif
|
||||
|
||||
#endif /* __OPRINTF__ */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*
|
||||
* If there is no flock defined by the system, use emulation
|
||||
* through fcntl record locking.
|
||||
*/
|
||||
#ifndef HAVE_FLOCK
|
||||
#define LOCK_SH 1 /* shared lock */
|
||||
#define LOCK_EX 2 /* exclusive lock */
|
||||
#define LOCK_NB 4 /* don't block when locking */
|
||||
#define LOCK_UN 8 /* unlock */
|
||||
#endif
|
||||
|
||||
#include <prototyp.h>
|
||||
|
||||
/*
|
||||
* gcc 2.x generally implements the long long type.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
# if __GNUC__ > 1
|
||||
# ifndef HAVE_LONGLONG
|
||||
# define HAVE_LONGLONG
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convert to GNU name
|
||||
*/
|
||||
#ifdef HAVE_STDC_HEADERS
|
||||
# ifndef STDC_HEADERS
|
||||
# define STDC_HEADERS
|
||||
# endif
|
||||
#endif
|
||||
/*
|
||||
* Convert to SCHILY name
|
||||
*/
|
||||
#ifdef STDC_HEADERS
|
||||
# ifndef HAVE_STDC_HEADERS
|
||||
# define HAVE_STDC_HEADERS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef IS_UNIX
|
||||
# define PATH_DELIM '/'
|
||||
# define PATH_DELIM_STR "/"
|
||||
# define far
|
||||
# define near
|
||||
#endif
|
||||
|
||||
#ifdef IS_GCC_WIN32
|
||||
# define PATH_DELIM '/'
|
||||
# define PATH_DELIM_STR "/"
|
||||
# define far
|
||||
# define near
|
||||
#endif
|
||||
|
||||
#ifdef IS_MSDOS
|
||||
# define PATH_DELIM '\\'
|
||||
# define PATH_DELIM_STR "\\"
|
||||
#endif
|
||||
|
||||
#ifdef IS_TOS
|
||||
# define PATH_DELIM '\\'
|
||||
# define PATH_DELIM_STR "\\"
|
||||
# define far
|
||||
# define near
|
||||
#endif
|
||||
|
||||
#ifdef IS_MAC
|
||||
# define PATH_DELIM ':'
|
||||
# define PATH_DELIM_STR ":"
|
||||
# define far
|
||||
# define near
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _MCONFIG_H */
|
|
@ -0,0 +1,74 @@
|
|||
/* @(#)prototyp.h 1.7 98/10/08 Copyright 1995 J. Schilling */
|
||||
/*
|
||||
* Definitions for dealing with ANSI / KR C-Compilers
|
||||
*
|
||||
* Copyright (c) 1995 J. Schilling
|
||||
*/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _PROTOTYP_H
|
||||
#define _PROTOTYP_H
|
||||
|
||||
#ifndef PROTOTYPES
|
||||
/*
|
||||
* If this has already been defined,
|
||||
* someone else knows better than us...
|
||||
*/
|
||||
# ifdef __STDC__
|
||||
# if __STDC__ /* ANSI C */
|
||||
# define PROTOTYPES
|
||||
# endif
|
||||
# if defined(sun) && __STDC__ - 0 == 0 /* Sun C */
|
||||
# define PROTOTYPES
|
||||
# endif
|
||||
# endif
|
||||
#endif /* PROTOTYPES */
|
||||
|
||||
/*
|
||||
* If we have prototypes, we should have stdlib.h string.h stdarg.h
|
||||
*/
|
||||
#ifdef PROTOTYPES
|
||||
#if !(defined(SABER) && defined(sun))
|
||||
# ifndef HAVE_STDARG_H
|
||||
# define HAVE_STDARG_H
|
||||
# endif
|
||||
#endif
|
||||
# ifndef HAVE_STDLIB_H
|
||||
# define HAVE_STDLIB_H
|
||||
# endif
|
||||
# ifndef HAVE_STRING_H
|
||||
# define HAVE_STRING_H
|
||||
# endif
|
||||
# ifndef HAVE_STDC_HEADERS
|
||||
# define HAVE_STDC_HEADERS
|
||||
# endif
|
||||
# ifndef STDC_HEADERS
|
||||
# define STDC_HEADERS /* GNU name */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef NO_PROTOTYPES /* Force not to use prototypes */
|
||||
# undef PROTOTYPES
|
||||
#endif
|
||||
|
||||
#ifdef PROTOTYPES
|
||||
# define __PR(a) a
|
||||
#else
|
||||
# define __PR(a) ()
|
||||
#endif
|
||||
|
||||
#endif /* _PROTOTYP_H */
|
|
@ -0,0 +1,139 @@
|
|||
/* @(#)statdefs.h 1.1 98/11/22 Copyright 1998 J. Schilling */
|
||||
/*
|
||||
* Definitions for stat() file mode
|
||||
*
|
||||
* Copyright (c) 1998 J. Schilling
|
||||
*/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _STATDEFS_H
|
||||
#define _STATDEFS_H
|
||||
|
||||
#ifndef _MCONFIG_H
|
||||
#include <mconfig.h>
|
||||
#endif
|
||||
|
||||
#ifdef STAT_MACROS_BROKEN
|
||||
#undef S_ISFIFO /* Named pipe */
|
||||
#undef S_ISCHR /* Character special */
|
||||
#undef S_ISMPC /* UNUSED multiplexed c */
|
||||
#undef S_ISDIR /* Directory */
|
||||
#undef S_ISNAM /* Named file (XENIX) */
|
||||
#undef S_ISBLK /* Block special */
|
||||
#undef S_ISMPB /* UNUSED multiplexed b */
|
||||
#undef S_ISREG /* Regular file */
|
||||
#undef S_ISCNT /* Contiguous file */
|
||||
#undef S_ISLNK /* Symbolic link */
|
||||
#undef S_ISSHAD /* Solaris shadow inode */
|
||||
#undef S_ISSOCK /* UNIX domain socket */
|
||||
#undef S_ISDOOR /* Solaris DOOR */
|
||||
#endif
|
||||
|
||||
#ifndef S_ISFIFO /* Named pipe */
|
||||
# ifdef S_IFIFO
|
||||
# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
||||
# else
|
||||
# define S_ISFIFO(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISCHR /* Character special */
|
||||
# ifdef S_IFCHR
|
||||
# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
||||
# else
|
||||
# define S_ISCHR(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISMPC /* UNUSED multiplexed c */
|
||||
# ifdef S_IFMPC
|
||||
# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
|
||||
# else
|
||||
# define S_ISMPC(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISDIR /* Directory */
|
||||
# ifdef S_IFDIR
|
||||
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
# else
|
||||
# define S_ISDIR(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISNAM /* Named file (XENIX) */
|
||||
# ifdef S_IFNAM
|
||||
# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM)
|
||||
# else
|
||||
# define S_ISNAM(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISBLK /* Block special */
|
||||
# ifdef S_IFBLK
|
||||
# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
|
||||
# else
|
||||
# define S_ISBLK(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISMPB /* UNUSED multiplexed b */
|
||||
# ifdef S_IFMPB
|
||||
# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
|
||||
# else
|
||||
# define S_ISMPB(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISREG /* Regular file */
|
||||
# ifdef S_IFREG
|
||||
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
# else
|
||||
# define S_ISREG(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISCNT /* Contiguous file */
|
||||
# ifdef S_IFCNT
|
||||
# define S_ISCNT(m) (((m) & S_IFMT) == S_IFCNT)
|
||||
# else
|
||||
# define S_ISCNT(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISLNK /* Symbolic link */
|
||||
# ifdef S_IFLNK
|
||||
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
# else
|
||||
# define S_ISLNK(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISSHAD /* Solaris shadow inode */
|
||||
# ifdef S_IFSHAD
|
||||
# define S_ISSHAD(m) (((m) & S_IFMT) == S_IFSHAD)
|
||||
# else
|
||||
# define S_ISSHAD(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISSOCK /* UNIX domain socket */
|
||||
# ifdef S_IFSOCK
|
||||
# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
|
||||
# else
|
||||
# define S_ISSOCK(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef S_ISDOOR /* Solaris DOOR */
|
||||
# ifdef S_IFDOOR
|
||||
# define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR)
|
||||
# else
|
||||
# define S_ISDOOR(m) (0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _STATDEFS_H */
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
#! /bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
#
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d $dst ]; then
|
||||
instcmd=:
|
||||
else
|
||||
instcmd=mkdir
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
true
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
shift
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
||||
else
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
|
||||
fi &&
|
||||
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* 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. */
|
||||
|
||||
/*
|
||||
* Id: iso9660.h,v 1.1 2000/10/10 20:40:16 beck Exp
|
||||
*/
|
||||
|
||||
#ifndef _ISOFS_FS_H
|
||||
#define _ISOFS_FS_H
|
||||
|
||||
/*
|
||||
* The isofs filesystem constants/structures
|
||||
*/
|
||||
|
||||
/* This part borrowed from the bsd386 isofs */
|
||||
#define ISODCL(from, to) (to - from + 1)
|
||||
|
||||
struct iso_volume_descriptor {
|
||||
char type[ISODCL(1,1)]; /* 711 */
|
||||
char id[ISODCL(2,6)];
|
||||
char version[ISODCL(7,7)];
|
||||
char data[ISODCL(8,2048)];
|
||||
};
|
||||
|
||||
/* volume descriptor types */
|
||||
#define ISO_VD_PRIMARY 1
|
||||
#define ISO_VD_SUPPLEMENTARY 2 /* Used by Joliet */
|
||||
#define ISO_VD_END 255
|
||||
|
||||
#define ISO_STANDARD_ID "CD001"
|
||||
|
||||
#define EL_TORITO_ID "EL TORITO SPECIFICATION"
|
||||
#define EL_TORITO_ARCH_x86 0
|
||||
#define EL_TORITO_ARCH_PPC 1
|
||||
#define EL_TORITO_ARCH_MAC 2
|
||||
#define EL_TORITO_BOOTABLE 0x88
|
||||
#define EL_TORITO_MEDIA_NOEMUL 0
|
||||
#define EL_TORITO_MEDIA_12FLOP 1
|
||||
#define EL_TORITO_MEDIA_144FLOP 2
|
||||
#define EL_TORITO_MEDIA_288FLOP 3
|
||||
#define EL_TORITO_MEDIA_HD 4
|
||||
|
||||
struct iso_primary_descriptor {
|
||||
char type [ISODCL ( 1, 1)]; /* 711 */
|
||||
char id [ISODCL ( 2, 6)];
|
||||
char version [ISODCL ( 7, 7)]; /* 711 */
|
||||
char unused1 [ISODCL ( 8, 8)];
|
||||
char system_id [ISODCL ( 9, 40)]; /* achars */
|
||||
char volume_id [ISODCL ( 41, 72)]; /* dchars */
|
||||
char unused2 [ISODCL ( 73, 80)];
|
||||
char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
|
||||
char escape_sequences [ISODCL ( 89, 120)];
|
||||
char volume_set_size [ISODCL (121, 124)]; /* 723 */
|
||||
char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
|
||||
char logical_block_size [ISODCL (129, 132)]; /* 723 */
|
||||
char path_table_size [ISODCL (133, 140)]; /* 733 */
|
||||
char type_l_path_table [ISODCL (141, 144)]; /* 731 */
|
||||
char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
|
||||
char type_m_path_table [ISODCL (149, 152)]; /* 732 */
|
||||
char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
|
||||
char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
|
||||
char volume_set_id [ISODCL (191, 318)]; /* dchars */
|
||||
char publisher_id [ISODCL (319, 446)]; /* achars */
|
||||
char preparer_id [ISODCL (447, 574)]; /* achars */
|
||||
char application_id [ISODCL (575, 702)]; /* achars */
|
||||
char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
|
||||
char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
|
||||
char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
|
||||
char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
|
||||
char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
|
||||
char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
|
||||
char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
|
||||
char file_structure_version [ISODCL (882, 882)]; /* 711 */
|
||||
char unused4 [ISODCL (883, 883)];
|
||||
char application_data [ISODCL (884, 1395)];
|
||||
char unused5 [ISODCL (1396, 2048)];
|
||||
};
|
||||
|
||||
/* El Torito Boot Record Volume Descriptor */
|
||||
struct eltorito_boot_descriptor {
|
||||
char id [ISODCL ( 1, 1)]; /* 711 */
|
||||
char id2 [ISODCL ( 2, 6)];
|
||||
char version [ISODCL ( 7, 7)]; /* 711 */
|
||||
char system_id [ISODCL ( 8, 39)];
|
||||
char unused2 [ISODCL ( 40, 71)];
|
||||
char bootcat_ptr [ISODCL ( 72 , 75)];
|
||||
char unused5 [ISODCL ( 76, 2048)];
|
||||
};
|
||||
|
||||
/* Validation entry for El Torito */
|
||||
struct eltorito_validation_entry {
|
||||
char headerid [ISODCL ( 1, 1)]; /* 711 */
|
||||
char arch [ISODCL ( 2, 2)];
|
||||
char pad1 [ISODCL ( 3, 4)]; /* 711 */
|
||||
char id [ISODCL ( 5, 28)];
|
||||
char cksum [ISODCL ( 29, 30)];
|
||||
char key1 [ISODCL ( 31, 31)];
|
||||
char key2 [ISODCL ( 32, 32)];
|
||||
};
|
||||
|
||||
/* El Torito initial/default entry in boot catalog */
|
||||
struct eltorito_defaultboot_entry {
|
||||
char boot_id [ISODCL ( 1, 1)]; /* 711 */
|
||||
char boot_media [ISODCL ( 2, 2)];
|
||||
char loadseg [ISODCL ( 3, 4)]; /* 711 */
|
||||
char arch [ISODCL ( 5, 5)];
|
||||
char pad1 [ISODCL ( 6, 6)];
|
||||
char nsect [ISODCL ( 7, 8)];
|
||||
char bootoff [ISODCL ( 9, 12)];
|
||||
char pad2 [ISODCL ( 13, 32)];
|
||||
};
|
||||
|
||||
|
||||
/* 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
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,25 @@
|
|||
/* proto.h */
|
||||
/* $OpenBSD: proto.h,v 1.1 2008/03/08 15:36:12 espie Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008 Marc Espie <espie@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifndef LIBFILE_PROTO_H
|
||||
#define LIBFILE_PROTO_H
|
||||
|
||||
extern int init_magic(char *);
|
||||
extern char *get_magic_match(const char *);
|
||||
extern void clean_magic(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,75 @@
|
|||
###############################################################################
|
||||
#
|
||||
# hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
# Copyright (C) 1996, 1997 Robert Leslie
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
CC = gcc
|
||||
INCLUDES =
|
||||
|
||||
LIBS =
|
||||
DEFINES =
|
||||
|
||||
COPTS = -g -Wall -pedantic
|
||||
CFLAGS = $(COPTS) $(INCLUDES) $(DEFINES)
|
||||
ARFLAGS = rc
|
||||
RANLIB = ranlib
|
||||
|
||||
###############################################################################
|
||||
|
||||
TARGET = libhfs.a
|
||||
OBJS = data.o block.o low.o file.o btree.o node.o record.o volume.o \
|
||||
hfs.o
|
||||
|
||||
###############################################################################
|
||||
|
||||
all :: $(TARGET)
|
||||
|
||||
again :: depend clean all
|
||||
|
||||
depend ::
|
||||
( sed -n '1,/^### DEPEND/p' Makefile; \
|
||||
echo; \
|
||||
$(CC) -MM $(CFLAGS) *.c; \
|
||||
) > Makefile.new
|
||||
mv -f Makefile.new Makefile
|
||||
|
||||
clean ::
|
||||
rm -f $(TARGET) *.o core
|
||||
|
||||
###############################################################################
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
ar $(ARFLAGS) $@ \
|
||||
$(OBJS)
|
||||
$(RANLIB) $@
|
||||
|
||||
### DEPENDENCIES FOLLOW #######################################################
|
||||
|
||||
block.o: block.c internal.h hfs.h data.h block.h low.h
|
||||
btree.o: btree.c internal.h hfs.h data.h block.h file.h btree.h node.h
|
||||
data.o: data.c internal.h hfs.h data.h btree.h
|
||||
file.o: file.c internal.h hfs.h data.h block.h file.h btree.h record.h \
|
||||
volume.h
|
||||
hfs.o: hfs.c internal.h hfs.h data.h block.h low.h file.h btree.h \
|
||||
node.h record.h volume.h
|
||||
low.o: low.c internal.h hfs.h data.h block.h low.h file.h
|
||||
node.o: node.c internal.h hfs.h data.h btree.h node.h
|
||||
record.o: record.c internal.h hfs.h data.h record.h
|
||||
volume.o: volume.c internal.h hfs.h data.h low.h btree.h record.h \
|
||||
volume.h
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
Modified version of libhfs (v2.0) to work with mkhybrid.
|
||||
|
||||
To complile for mkhybrid, use the #define -DAPPLE_HYB
|
||||
|
||||
The libhfs.a created with this option must not be used with other
|
||||
hfsutils routines.
|
||||
|
||||
James Pearson 18/7/97
|
||||
|
||||
Copyright information from hfsutils:
|
||||
|
||||
hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
Copyright (C) 1996, 1997 Robert Leslie
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
# include <string.h>
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
# include <errno.h>
|
||||
# include <time.h>
|
||||
|
||||
# include "internal.h"
|
||||
# include "data.h"
|
||||
# include "block.h"
|
||||
# include "low.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* NAME: block->readlb()
|
||||
* DESCRIPTION: read a logical block from a volume
|
||||
*/
|
||||
int b_readlb(hfsvol *vol, unsigned long num, block *bp)
|
||||
{
|
||||
#ifdef APPLE_HYB
|
||||
block *b;
|
||||
hce_mem *hce;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"b_readlb: start block = %d\n", vol->vstart + num);
|
||||
#endif /* DEBUG */
|
||||
|
||||
hce = vol->hce;
|
||||
|
||||
/* Check to see if requested block is in the HFS header or catalog/exents
|
||||
files. If it is, read info from memory copy. If not, then something
|
||||
has gone horribly wrong ... */
|
||||
|
||||
if (num < hce->hfs_hdr_size)
|
||||
b = (block *)hce->hfs_hdr + num;
|
||||
else if (num < hce->hfs_hdr_size + hce->hfs_ce_size)
|
||||
b = (block *)hce->hfs_ce + num - hce->hfs_hdr_size;
|
||||
else
|
||||
{
|
||||
ERROR(EIO, "should not happen!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(bp, b, HFS_BLOCKSZ);
|
||||
|
||||
#else
|
||||
int bytes;
|
||||
|
||||
if (lseek(vol->fd, (vol->vstart + num) * HFS_BLOCKSZ, SEEK_SET) < 0)
|
||||
{
|
||||
ERROR(errno, "error seeking device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes = read(vol->fd, bp, HFS_BLOCKSZ);
|
||||
if (bytes < 0)
|
||||
{
|
||||
ERROR(errno, "error reading from device");
|
||||
return -1;
|
||||
}
|
||||
else if (bytes == 0)
|
||||
{
|
||||
ERROR(EIO, "read EOF on volume");
|
||||
return -1;
|
||||
}
|
||||
else if (bytes != HFS_BLOCKSZ)
|
||||
{
|
||||
ERROR(EIO, "read incomplete block");
|
||||
return -1;
|
||||
}
|
||||
#endif /* APPLE_HYB */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: block->writelb()
|
||||
* DESCRIPTION: write a logical block to a volume
|
||||
*/
|
||||
int b_writelb(hfsvol *vol, unsigned long num, block *bp)
|
||||
{
|
||||
#ifdef APPLE_HYB
|
||||
block *b;
|
||||
hce_mem *hce;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"b_writelb: start block = %d\n", vol->vstart + num);
|
||||
#endif /* DEBUG */
|
||||
|
||||
hce = vol->hce;
|
||||
|
||||
/* Check to see if requested block is in the HFS header or catalog/exents
|
||||
files. If it is, write info to memory copy. If not, then it's a block
|
||||
for an ordinary file - and as we are writing the files later, then just
|
||||
ignore and return OK */
|
||||
if (num < hce->hfs_hdr_size)
|
||||
b = (block *)hce->hfs_hdr + num;
|
||||
else if (num < hce->hfs_hdr_size + hce->hfs_ce_size)
|
||||
b = (block *)hce->hfs_ce + num - hce->hfs_hdr_size;
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"b_writelb: ignoring\n");
|
||||
#endif /* DEBUG */
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(b, bp, HFS_BLOCKSZ);
|
||||
|
||||
#else
|
||||
int bytes;
|
||||
|
||||
if (lseek(vol->fd, (vol->vstart + num) * HFS_BLOCKSZ, SEEK_SET) < 0)
|
||||
{
|
||||
ERROR(errno, "error seeking device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes = write(vol->fd, bp, HFS_BLOCKSZ);
|
||||
|
||||
if (bytes < 0)
|
||||
{
|
||||
ERROR(errno, "error writing to device");
|
||||
return -1;
|
||||
}
|
||||
else if (bytes != HFS_BLOCKSZ)
|
||||
{
|
||||
ERROR(EIO, "wrote incomplete block");
|
||||
return -1;
|
||||
}
|
||||
#endif /* APPLE_HYB */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: block->readab()
|
||||
* DESCRIPTION: read a block from an allocation block from a volume
|
||||
*/
|
||||
int b_readab(hfsvol *vol,
|
||||
unsigned int anum, unsigned int index, block *bp)
|
||||
{
|
||||
/* verify the allocation block exists and is marked as in-use */
|
||||
|
||||
if (anum >= vol->mdb.drNmAlBlks)
|
||||
{
|
||||
ERROR(EIO, "read nonexistent block");
|
||||
return -1;
|
||||
}
|
||||
else if (vol->vbm && ! BMTST(vol->vbm, anum))
|
||||
{
|
||||
ERROR(EIO, "read unallocated block");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return b_readlb(vol, vol->mdb.drAlBlSt + anum * vol->lpa + index, bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: b->writeab()
|
||||
* DESCRIPTION: write a block to an allocation block to a volume
|
||||
*/
|
||||
int b_writeab(hfsvol *vol,
|
||||
unsigned int anum, unsigned int index, block *bp)
|
||||
{
|
||||
/* verify the allocation block exists and is marked as in-use */
|
||||
|
||||
if (anum >= vol->mdb.drNmAlBlks)
|
||||
{
|
||||
ERROR(EIO, "write nonexistent block");
|
||||
return -1;
|
||||
}
|
||||
else if (vol->vbm && ! BMTST(vol->vbm, anum))
|
||||
{
|
||||
ERROR(EIO, "write unallocated block");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vol->mdb.drAtrb &= ~HFS_ATRB_UMOUNTED;
|
||||
vol->mdb.drLsMod = d_tomtime(time(0));
|
||||
++vol->mdb.drWrCnt;
|
||||
|
||||
vol->flags |= HFS_UPDATE_MDB;
|
||||
|
||||
return b_writelb(vol, vol->mdb.drAlBlSt + anum * vol->lpa + index, bp);
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
int b_readlb(hfsvol *, unsigned long, block *);
|
||||
int b_writelb(hfsvol *, unsigned long, block *);
|
||||
|
||||
int b_readab(hfsvol *, unsigned int, unsigned int, block *);
|
||||
int b_writeab(hfsvol *, unsigned int, unsigned int, block *);
|
|
@ -0,0 +1,719 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <errno.h>
|
||||
|
||||
# include "internal.h"
|
||||
# include "data.h"
|
||||
# include "block.h"
|
||||
# include "file.h"
|
||||
# include "btree.h"
|
||||
# include "node.h"
|
||||
|
||||
/*
|
||||
* NAME: btree->getnode()
|
||||
* DESCRIPTION: retrieve a numbered node from a B*-tree file
|
||||
*/
|
||||
int bt_getnode(node *np)
|
||||
{
|
||||
btree *bt = np->bt;
|
||||
block *bp = &np->data;
|
||||
unsigned char *ptr;
|
||||
int i;
|
||||
|
||||
/* verify the node exists and is marked as in-use */
|
||||
|
||||
if (np->nnum < 0 || (np->nnum > 0 && np->nnum >= bt->hdr.bthNNodes))
|
||||
{
|
||||
ERROR(EIO, "read nonexistent b*-tree node");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bt->map && ! BMTST(bt->map, np->nnum))
|
||||
{
|
||||
ERROR(EIO, "read unallocated b*-tree node");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (f_getblock(&bt->f, np->nnum, bp) < 0)
|
||||
return -1;
|
||||
|
||||
ptr = *bp;
|
||||
|
||||
d_fetchl(&ptr, (long *) &np->nd.ndFLink);
|
||||
d_fetchl(&ptr, (long *) &np->nd.ndBLink);
|
||||
d_fetchb(&ptr, (char *) &np->nd.ndType);
|
||||
d_fetchb(&ptr, (char *) &np->nd.ndNHeight);
|
||||
d_fetchw(&ptr, (short *) &np->nd.ndNRecs);
|
||||
d_fetchw(&ptr, &np->nd.ndResv2);
|
||||
|
||||
if (np->nd.ndNRecs > HFS_MAXRECS)
|
||||
{
|
||||
ERROR(EIO, "too many b*-tree node records");
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = np->nd.ndNRecs + 1;
|
||||
|
||||
ptr = *bp + HFS_BLOCKSZ - (2 * i);
|
||||
|
||||
while (i--)
|
||||
d_fetchw(&ptr, (short *) &np->roff[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: btree->putnode()
|
||||
* DESCRIPTION: store a numbered node into a B*-tree file
|
||||
*/
|
||||
int bt_putnode(node *np)
|
||||
{
|
||||
btree *bt = np->bt;
|
||||
block *bp = &np->data;
|
||||
unsigned char *ptr;
|
||||
int i;
|
||||
|
||||
/* verify the node exists and is marked as in-use */
|
||||
|
||||
if (np->nnum && np->nnum >= bt->hdr.bthNNodes)
|
||||
{
|
||||
ERROR(EIO, "write nonexistent b*-tree node");
|
||||
return -1;
|
||||
}
|
||||
else if (bt->map && ! BMTST(bt->map, np->nnum))
|
||||
{
|
||||
ERROR(EIO, "write unallocated b*-tree node");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptr = *bp;
|
||||
|
||||
d_storel(&ptr, np->nd.ndFLink);
|
||||
d_storel(&ptr, np->nd.ndBLink);
|
||||
d_storeb(&ptr, np->nd.ndType);
|
||||
d_storeb(&ptr, np->nd.ndNHeight);
|
||||
d_storew(&ptr, np->nd.ndNRecs);
|
||||
d_storew(&ptr, np->nd.ndResv2);
|
||||
|
||||
if (np->nd.ndNRecs > HFS_MAXRECS)
|
||||
{
|
||||
ERROR(EIO, "too many b*-tree node records");
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = np->nd.ndNRecs + 1;
|
||||
|
||||
ptr = *bp + HFS_BLOCKSZ - (2 * i);
|
||||
|
||||
while (i--)
|
||||
d_storew(&ptr, np->roff[i]);
|
||||
|
||||
if (f_putblock(&bt->f, np->nnum, bp) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: btree->readhdr()
|
||||
* DESCRIPTION: read the header node of a B*-tree
|
||||
*/
|
||||
int bt_readhdr(btree *bt)
|
||||
{
|
||||
unsigned char *ptr;
|
||||
char *map;
|
||||
int i;
|
||||
unsigned long nnum;
|
||||
|
||||
bt->hdrnd.bt = bt;
|
||||
bt->hdrnd.nnum = 0;
|
||||
|
||||
if (bt_getnode(&bt->hdrnd) < 0)
|
||||
return -1;
|
||||
|
||||
if (bt->hdrnd.nd.ndType != ndHdrNode ||
|
||||
bt->hdrnd.nd.ndNRecs != 3 ||
|
||||
bt->hdrnd.roff[0] != 0x00e ||
|
||||
bt->hdrnd.roff[1] != 0x078 ||
|
||||
bt->hdrnd.roff[2] != 0x0f8 ||
|
||||
bt->hdrnd.roff[3] != 0x1f8)
|
||||
{
|
||||
ERROR(EIO, "malformed b*-tree header node");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read header record */
|
||||
|
||||
ptr = HFS_NODEREC(bt->hdrnd, 0);
|
||||
|
||||
d_fetchw(&ptr, (short *) &bt->hdr.bthDepth);
|
||||
d_fetchl(&ptr, (long *) &bt->hdr.bthRoot);
|
||||
d_fetchl(&ptr, (long *) &bt->hdr.bthNRecs);
|
||||
d_fetchl(&ptr, (long *) &bt->hdr.bthFNode);
|
||||
d_fetchl(&ptr, (long *) &bt->hdr.bthLNode);
|
||||
d_fetchw(&ptr, (short *) &bt->hdr.bthNodeSize);
|
||||
d_fetchw(&ptr, (short *) &bt->hdr.bthKeyLen);
|
||||
d_fetchl(&ptr, (long *) &bt->hdr.bthNNodes);
|
||||
d_fetchl(&ptr, (long *) &bt->hdr.bthFree);
|
||||
|
||||
for (i = 0; i < 76; ++i)
|
||||
d_fetchb(&ptr, (char *) &bt->hdr.bthResv[i]);
|
||||
|
||||
if (bt->hdr.bthNodeSize != HFS_BLOCKSZ)
|
||||
{
|
||||
ERROR(EINVAL, "unsupported b*-tree node size");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read map record; construct btree bitmap */
|
||||
/* don't set bt->map until we're done, since getnode() checks it */
|
||||
|
||||
map = ALLOC(char, HFS_MAP1SZ);
|
||||
if (map == 0)
|
||||
{
|
||||
ERROR(ENOMEM, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(map, HFS_NODEREC(bt->hdrnd, 2), HFS_MAP1SZ);
|
||||
bt->mapsz = HFS_MAP1SZ;
|
||||
|
||||
/* read continuation map records, if any */
|
||||
|
||||
nnum = bt->hdrnd.nd.ndFLink;
|
||||
|
||||
while (nnum)
|
||||
{
|
||||
node n;
|
||||
char *newmap;
|
||||
|
||||
n.bt = bt;
|
||||
n.nnum = nnum;
|
||||
|
||||
if (bt_getnode(&n) < 0)
|
||||
{
|
||||
FREE(map);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (n.nd.ndType != ndMapNode ||
|
||||
n.nd.ndNRecs != 1 ||
|
||||
n.roff[0] != 0x00e ||
|
||||
n.roff[1] != 0x1fa)
|
||||
{
|
||||
FREE(map);
|
||||
ERROR(EIO, "malformed b*-tree map node");
|
||||
return -1;
|
||||
}
|
||||
|
||||
newmap = REALLOC(map, char, bt->mapsz + HFS_MAPXSZ);
|
||||
if (newmap == 0)
|
||||
{
|
||||
FREE(map);
|
||||
ERROR(ENOMEM, 0);
|
||||
return -1;
|
||||
}
|
||||
map = newmap;
|
||||
|
||||
memcpy(map + bt->mapsz, HFS_NODEREC(n, 0), HFS_MAPXSZ);
|
||||
bt->mapsz += HFS_MAPXSZ;
|
||||
|
||||
nnum = n.nd.ndFLink;
|
||||
}
|
||||
|
||||
bt->map = map;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: btree->writehdr()
|
||||
* DESCRIPTION: write the header node of a B*-tree
|
||||
*/
|
||||
int bt_writehdr(btree *bt)
|
||||
{
|
||||
unsigned char *ptr;
|
||||
char *map;
|
||||
unsigned long mapsz, nnum;
|
||||
int i;
|
||||
|
||||
if (bt->hdrnd.bt != bt ||
|
||||
bt->hdrnd.nnum != 0 ||
|
||||
bt->hdrnd.nd.ndType != ndHdrNode ||
|
||||
bt->hdrnd.nd.ndNRecs != 3)
|
||||
abort();
|
||||
|
||||
ptr = HFS_NODEREC(bt->hdrnd, 0);
|
||||
|
||||
d_storew(&ptr, bt->hdr.bthDepth);
|
||||
d_storel(&ptr, bt->hdr.bthRoot);
|
||||
d_storel(&ptr, bt->hdr.bthNRecs);
|
||||
d_storel(&ptr, bt->hdr.bthFNode);
|
||||
d_storel(&ptr, bt->hdr.bthLNode);
|
||||
d_storew(&ptr, bt->hdr.bthNodeSize);
|
||||
d_storew(&ptr, bt->hdr.bthKeyLen);
|
||||
d_storel(&ptr, bt->hdr.bthNNodes);
|
||||
d_storel(&ptr, bt->hdr.bthFree);
|
||||
|
||||
for (i = 0; i < 76; ++i)
|
||||
d_storeb(&ptr, bt->hdr.bthResv[i]);
|
||||
|
||||
memcpy(HFS_NODEREC(bt->hdrnd, 2), bt->map, HFS_MAP1SZ);
|
||||
|
||||
if (bt_putnode(&bt->hdrnd) < 0)
|
||||
return -1;
|
||||
|
||||
map = bt->map + HFS_MAP1SZ;
|
||||
mapsz = bt->mapsz - HFS_MAP1SZ;
|
||||
|
||||
nnum = bt->hdrnd.nd.ndFLink;
|
||||
|
||||
while (mapsz)
|
||||
{
|
||||
node n;
|
||||
|
||||
if (nnum == 0)
|
||||
{
|
||||
ERROR(EIO, "truncated b*-tree map");
|
||||
return -1;
|
||||
}
|
||||
|
||||
n.bt = bt;
|
||||
n.nnum = nnum;
|
||||
|
||||
if (bt_getnode(&n) < 0)
|
||||
return -1;
|
||||
|
||||
if (n.nd.ndType != ndMapNode ||
|
||||
n.nd.ndNRecs != 1 ||
|
||||
n.roff[0] != 0x00e ||
|
||||
n.roff[1] != 0x1fa)
|
||||
{
|
||||
ERROR(EIO, "malformed b*-tree map node");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(HFS_NODEREC(n, 0), map, HFS_MAPXSZ);
|
||||
|
||||
if (bt_putnode(&n) < 0)
|
||||
return -1;
|
||||
|
||||
map += HFS_MAPXSZ;
|
||||
mapsz -= HFS_MAPXSZ;
|
||||
|
||||
nnum = n.nd.ndFLink;
|
||||
}
|
||||
|
||||
bt->flags &= ~HFS_UPDATE_BTHDR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* High-Level B*-Tree Routines ============================================= */
|
||||
|
||||
/*
|
||||
* NAME: btree->space()
|
||||
* DESCRIPTION: assert space for new records, or extend the file
|
||||
*/
|
||||
int bt_space(btree *bt, unsigned int nrecs)
|
||||
{
|
||||
unsigned int nnodes;
|
||||
int space;
|
||||
|
||||
nnodes = nrecs * (bt->hdr.bthDepth + 1);
|
||||
|
||||
if (nnodes <= bt->hdr.bthFree)
|
||||
return 0;
|
||||
|
||||
/* make sure the extents tree has room too */
|
||||
|
||||
if (bt != &bt->f.vol->ext)
|
||||
{
|
||||
if (bt_space(&bt->f.vol->ext, 1) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
space = f_alloc(&bt->f);
|
||||
if (space < 0)
|
||||
return -1;
|
||||
|
||||
nnodes = space * (bt->f.vol->mdb.drAlBlkSiz / bt->hdr.bthNodeSize);
|
||||
|
||||
bt->hdr.bthNNodes += nnodes;
|
||||
bt->hdr.bthFree += nnodes;
|
||||
|
||||
bt->flags |= HFS_UPDATE_BTHDR;
|
||||
|
||||
bt->f.vol->flags |= HFS_UPDATE_ALTMDB;
|
||||
|
||||
while (bt->hdr.bthNNodes > bt->mapsz * 8)
|
||||
{
|
||||
char *newmap;
|
||||
node mapnd;
|
||||
|
||||
/* extend tree map */
|
||||
|
||||
newmap = REALLOC(bt->map, char, bt->mapsz + HFS_MAPXSZ);
|
||||
if (newmap == 0)
|
||||
{
|
||||
ERROR(ENOMEM, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(newmap + bt->mapsz, 0, HFS_MAPXSZ);
|
||||
|
||||
bt->map = newmap;
|
||||
bt->mapsz += HFS_MAPXSZ;
|
||||
|
||||
n_init(&mapnd, bt, ndMapNode, 0);
|
||||
if (n_new(&mapnd) < 0)
|
||||
return -1;
|
||||
|
||||
/* link the new map node */
|
||||
|
||||
if (bt->hdrnd.nd.ndFLink == 0)
|
||||
{
|
||||
bt->hdrnd.nd.ndFLink = mapnd.nnum;
|
||||
mapnd.nd.ndBLink = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
node n;
|
||||
|
||||
n.bt = bt;
|
||||
n.nnum = bt->hdrnd.nd.ndFLink;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (bt_getnode(&n) < 0)
|
||||
return -1;
|
||||
|
||||
if (n.nd.ndFLink == 0)
|
||||
break;
|
||||
|
||||
n.nnum = n.nd.ndFLink;
|
||||
}
|
||||
|
||||
n.nd.ndFLink = mapnd.nnum;
|
||||
mapnd.nd.ndBLink = n.nnum;
|
||||
|
||||
if (bt_putnode(&n) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
mapnd.nd.ndNRecs = 1;
|
||||
mapnd.roff[1] = 0x1fa;
|
||||
|
||||
if (bt_putnode(&mapnd) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: btree->insertx()
|
||||
* DESCRIPTION: recursively locate a node and insert a record
|
||||
*/
|
||||
int bt_insertx(node *np, unsigned char *record, int *reclen)
|
||||
{
|
||||
node child;
|
||||
unsigned char *rec;
|
||||
|
||||
if (n_search(np, record))
|
||||
{
|
||||
ERROR(EIO, "b*-tree record already exists");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch ((unsigned char) np->nd.ndType)
|
||||
{
|
||||
case ndIndxNode:
|
||||
if (np->rnum < 0)
|
||||
rec = HFS_NODEREC(*np, 0);
|
||||
else
|
||||
rec = HFS_NODEREC(*np, np->rnum);
|
||||
|
||||
child.bt = np->bt;
|
||||
child.nnum = d_getl(HFS_RECDATA(rec));
|
||||
|
||||
if (bt_getnode(&child) < 0 ||
|
||||
bt_insertx(&child, record, reclen) < 0)
|
||||
return -1;
|
||||
|
||||
if (np->rnum < 0)
|
||||
{
|
||||
n_index(np->bt, HFS_NODEREC(child, 0), child.nnum, rec, 0);
|
||||
if (*reclen == 0)
|
||||
return bt_putnode(np);
|
||||
}
|
||||
|
||||
return *reclen ? n_insert(np, record, reclen) : 0;
|
||||
|
||||
case ndLeafNode:
|
||||
return n_insert(np, record, reclen);
|
||||
|
||||
default:
|
||||
ERROR(EIO, "unexpected b*-tree node");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: btree->insert()
|
||||
* DESCRIPTION: insert a new node record into a tree
|
||||
*/
|
||||
int bt_insert(btree *bt, unsigned char *record, int reclen)
|
||||
{
|
||||
node root;
|
||||
|
||||
if (bt->hdr.bthRoot == 0)
|
||||
{
|
||||
/* create root node */
|
||||
|
||||
n_init(&root, bt, ndLeafNode, 1);
|
||||
if (n_new(&root) < 0 ||
|
||||
bt_putnode(&root) < 0)
|
||||
return -1;
|
||||
|
||||
bt->hdr.bthDepth = 1;
|
||||
bt->hdr.bthRoot = root.nnum;
|
||||
bt->hdr.bthFNode = root.nnum;
|
||||
bt->hdr.bthLNode = root.nnum;
|
||||
|
||||
bt->flags |= HFS_UPDATE_BTHDR;
|
||||
}
|
||||
else
|
||||
{
|
||||
root.bt = bt;
|
||||
root.nnum = bt->hdr.bthRoot;
|
||||
|
||||
if (bt_getnode(&root) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bt_insertx(&root, record, &reclen) < 0)
|
||||
return -1;
|
||||
|
||||
if (reclen)
|
||||
{
|
||||
unsigned char oroot[HFS_MAXRECLEN];
|
||||
int orootlen;
|
||||
|
||||
/* root node was split; create a new root */
|
||||
|
||||
n_index(bt, HFS_NODEREC(root, 0), root.nnum, oroot, &orootlen);
|
||||
|
||||
n_init(&root, bt, ndIndxNode, root.nd.ndNHeight + 1);
|
||||
if (n_new(&root) < 0)
|
||||
return -1;
|
||||
|
||||
++bt->hdr.bthDepth;
|
||||
bt->hdr.bthRoot = root.nnum;
|
||||
|
||||
bt->flags |= HFS_UPDATE_BTHDR;
|
||||
|
||||
/* insert index records for new root */
|
||||
|
||||
n_search(&root, oroot);
|
||||
n_insertx(&root, oroot, orootlen);
|
||||
|
||||
n_search(&root, record);
|
||||
n_insertx(&root, record, reclen);
|
||||
|
||||
if (bt_putnode(&root) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
++bt->hdr.bthNRecs;
|
||||
bt->flags |= HFS_UPDATE_BTHDR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: btree->deletex()
|
||||
* DESCRIPTION: recursively locate a node and delete a record
|
||||
*/
|
||||
int bt_deletex(node *np, unsigned char *key, unsigned char *record, int *flag)
|
||||
{
|
||||
node child;
|
||||
unsigned char *rec;
|
||||
int found;
|
||||
|
||||
found = n_search(np, key);
|
||||
|
||||
switch ((unsigned char) np->nd.ndType)
|
||||
{
|
||||
case ndIndxNode:
|
||||
if (np->rnum < 0)
|
||||
{
|
||||
ERROR(EIO, "b*-tree record not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rec = HFS_NODEREC(*np, np->rnum);
|
||||
|
||||
child.bt = np->bt;
|
||||
child.nnum = d_getl(HFS_RECDATA(rec));
|
||||
|
||||
if (bt_getnode(&child) < 0 ||
|
||||
bt_deletex(&child, key, rec, flag) < 0)
|
||||
return -1;
|
||||
|
||||
if (*flag)
|
||||
{
|
||||
*flag = 0;
|
||||
|
||||
if (HFS_RECKEYLEN(rec) == 0)
|
||||
return n_delete(np, record, flag);
|
||||
|
||||
if (np->rnum == 0)
|
||||
{
|
||||
n_index(np->bt, HFS_NODEREC(*np, 0), np->nnum, record, 0);
|
||||
*flag = 1;
|
||||
}
|
||||
|
||||
return bt_putnode(np);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case ndLeafNode:
|
||||
if (found == 0)
|
||||
{
|
||||
ERROR(EIO, "b*-tree record not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return n_delete(np, record, flag);
|
||||
|
||||
default:
|
||||
ERROR(EIO, "unexpected b*-tree node");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: btree->delete()
|
||||
* DESCRIPTION: remove a node record from a tree
|
||||
*/
|
||||
int bt_delete(btree *bt, unsigned char *key)
|
||||
{
|
||||
node root;
|
||||
unsigned char record[HFS_MAXRECLEN];
|
||||
int flag = 0;
|
||||
|
||||
root.bt = bt;
|
||||
root.nnum = bt->hdr.bthRoot;
|
||||
|
||||
if (root.nnum == 0)
|
||||
{
|
||||
ERROR(EIO, "empty b*-tree");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bt_getnode(&root) < 0 ||
|
||||
bt_deletex(&root, key, record, &flag) < 0)
|
||||
return -1;
|
||||
|
||||
if (bt->hdr.bthDepth > 1 && root.nd.ndNRecs == 1)
|
||||
{
|
||||
unsigned char *rec;
|
||||
|
||||
/* chop the root */
|
||||
|
||||
rec = HFS_NODEREC(root, 0);
|
||||
|
||||
--bt->hdr.bthDepth;
|
||||
bt->hdr.bthRoot = d_getl(HFS_RECDATA(rec));
|
||||
|
||||
n_free(&root);
|
||||
}
|
||||
else if (bt->hdr.bthDepth == 1 && root.nd.ndNRecs == 0)
|
||||
{
|
||||
/* delete the root node */
|
||||
|
||||
bt->hdr.bthDepth = 0;
|
||||
bt->hdr.bthRoot = 0;
|
||||
bt->hdr.bthFNode = 0;
|
||||
bt->hdr.bthLNode = 0;
|
||||
|
||||
n_free(&root);
|
||||
}
|
||||
|
||||
--bt->hdr.bthNRecs;
|
||||
bt->flags |= HFS_UPDATE_BTHDR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: btree->search()
|
||||
* DESCRIPTION: locate a data record given a search key
|
||||
*/
|
||||
int bt_search(btree *bt, unsigned char *key, node *np)
|
||||
{
|
||||
np->bt = bt;
|
||||
np->nnum = bt->hdr.bthRoot;
|
||||
|
||||
if (np->nnum == 0)
|
||||
{
|
||||
ERROR(ENOENT, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
int found;
|
||||
unsigned char *rec;
|
||||
|
||||
if (bt_getnode(np) < 0)
|
||||
return -1;
|
||||
|
||||
found = n_search(np, key);
|
||||
|
||||
switch ((unsigned char) np->nd.ndType)
|
||||
{
|
||||
case ndIndxNode:
|
||||
if (np->rnum < 0)
|
||||
{
|
||||
ERROR(ENOENT, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rec = HFS_NODEREC(*np, np->rnum);
|
||||
np->nnum = d_getl(HFS_RECDATA(rec));
|
||||
break;
|
||||
|
||||
case ndLeafNode:
|
||||
if (! found)
|
||||
ERROR(ENOENT, 0);
|
||||
|
||||
return found;
|
||||
|
||||
default:
|
||||
ERROR(EIO, "unexpected b*-tree node");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
int bt_getnode(node *);
|
||||
int bt_putnode(node *);
|
||||
|
||||
int bt_readhdr(btree *);
|
||||
int bt_writehdr(btree *);
|
||||
|
||||
int bt_space(btree *, unsigned int);
|
||||
|
||||
int bt_insertx(node *, unsigned char *, int *);
|
||||
int bt_insert(btree *, unsigned char *, int);
|
||||
|
||||
int bt_deletex(node *, unsigned char *, unsigned char *, int *);
|
||||
int bt_delete(btree *, unsigned char *);
|
||||
|
||||
int bt_search(btree *, unsigned char *, node *);
|
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
# include <string.h>
|
||||
# include <time.h>
|
||||
|
||||
# include "internal.h"
|
||||
# include "data.h"
|
||||
# include "btree.h"
|
||||
|
||||
# define MUTDIFF 2082844800L
|
||||
|
||||
static
|
||||
unsigned long tzdiff = -1;
|
||||
|
||||
unsigned char hfs_charorder[256] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
|
||||
0x20, 0x22, 0x23, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
|
||||
0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
|
||||
0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
|
||||
0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
|
||||
|
||||
0x47, 0x48, 0x58, 0x5a, 0x5e, 0x60, 0x67, 0x69,
|
||||
0x6b, 0x6d, 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7f,
|
||||
0x8d, 0x8f, 0x91, 0x93, 0x96, 0x98, 0x9f, 0xa1,
|
||||
0xa3, 0xa5, 0xa8, 0xaa, 0xab, 0xac, 0xad, 0xae,
|
||||
|
||||
0x54, 0x48, 0x58, 0x5a, 0x5e, 0x60, 0x67, 0x69,
|
||||
0x6b, 0x6d, 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7f,
|
||||
0x8d, 0x8f, 0x91, 0x93, 0x96, 0x98, 0x9f, 0xa1,
|
||||
0xa3, 0xa5, 0xa8, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
|
||||
|
||||
0x4c, 0x50, 0x5c, 0x62, 0x7d, 0x81, 0x9a, 0x55,
|
||||
0x4a, 0x56, 0x4c, 0x4e, 0x50, 0x5c, 0x62, 0x64,
|
||||
0x65, 0x66, 0x6f, 0x70, 0x71, 0x72, 0x7d, 0x89,
|
||||
0x8a, 0x8b, 0x81, 0x83, 0x9c, 0x9d, 0x9e, 0x9a,
|
||||
|
||||
0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0x95,
|
||||
0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0x52, 0x85,
|
||||
0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
|
||||
0xc9, 0xca, 0xcb, 0x57, 0x8c, 0xcc, 0x52, 0x85,
|
||||
|
||||
0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0x26,
|
||||
0x27, 0xd4, 0x20, 0x4a, 0x4e, 0x83, 0x87, 0x87,
|
||||
0xd5, 0xd6, 0x24, 0x25, 0x2d, 0x2e, 0xd7, 0xd8,
|
||||
0xa7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
||||
};
|
||||
|
||||
/*
|
||||
* NAME: data->getb()
|
||||
* DESCRIPTION: marshal 1 byte into local host format
|
||||
*/
|
||||
char d_getb(unsigned char *ptr)
|
||||
{
|
||||
return (char) ptr[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->getw()
|
||||
* DESCRIPTION: marshal 2 bytes into local host format
|
||||
*/
|
||||
short d_getw(unsigned char *ptr)
|
||||
{
|
||||
return (short)
|
||||
((ptr[0] << 8) |
|
||||
(ptr[1] << 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->getl()
|
||||
* DESCRIPTION: marshal 4 bytes into local host format
|
||||
*/
|
||||
long d_getl(unsigned char *ptr)
|
||||
{
|
||||
return (long)
|
||||
((ptr[0] << 24) |
|
||||
(ptr[1] << 16) |
|
||||
(ptr[2] << 8) |
|
||||
(ptr[3] << 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->putb()
|
||||
* DESCRIPTION: marshal 1 byte out to Macintosh (big-endian) format
|
||||
*/
|
||||
void d_putb(unsigned char *ptr, char data)
|
||||
{
|
||||
ptr[0] = (unsigned char) data;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->putw()
|
||||
* DESCRIPTION: marshal 2 bytes out to Macintosh (big-endian) format
|
||||
*/
|
||||
void d_putw(unsigned char *ptr, short data)
|
||||
{
|
||||
ptr[0] = ((unsigned short) data & 0xff00) >> 8;
|
||||
ptr[1] = ((unsigned short) data & 0x00ff) >> 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->putl()
|
||||
* DESCRIPTION: marshal 4 bytes out to Macintosh (big-endian) format
|
||||
*/
|
||||
void d_putl(unsigned char *ptr, long data)
|
||||
{
|
||||
ptr[0] = ((unsigned long) data & 0xff000000) >> 24;
|
||||
ptr[1] = ((unsigned long) data & 0x00ff0000) >> 16;
|
||||
ptr[2] = ((unsigned long) data & 0x0000ff00) >> 8;
|
||||
ptr[3] = ((unsigned long) data & 0x000000ff) >> 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->fetchb()
|
||||
* DESCRIPTION: incrementally retrieve a byte of data
|
||||
*/
|
||||
void d_fetchb(unsigned char **ptr, char *dest)
|
||||
{
|
||||
*dest = d_getb(*ptr);
|
||||
*ptr += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->fetchw()
|
||||
* DESCRIPTION: incrementally retrieve a word of data
|
||||
*/
|
||||
void d_fetchw(unsigned char **ptr, short *dest)
|
||||
{
|
||||
*dest = d_getw(*ptr);
|
||||
*ptr += 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->fetchl()
|
||||
* DESCRIPTION: incrementally retrieve a long word of data
|
||||
*/
|
||||
void d_fetchl(unsigned char **ptr, long *dest)
|
||||
{
|
||||
*dest = d_getl(*ptr);
|
||||
*ptr += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->fetchs()
|
||||
* DESCRIPTION: incrementally retrieve a string
|
||||
*/
|
||||
void d_fetchs(unsigned char **ptr, char *dest, int size)
|
||||
{
|
||||
int len;
|
||||
char blen;
|
||||
|
||||
d_fetchb(ptr, &blen);
|
||||
len = blen;
|
||||
|
||||
if (len > 0 && len < size)
|
||||
memcpy(dest, *ptr, len);
|
||||
else
|
||||
len = 0;
|
||||
|
||||
dest[len] = 0;
|
||||
|
||||
*ptr += size - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->storeb()
|
||||
* DESCRIPTION: incrementally store a byte of data
|
||||
*/
|
||||
void d_storeb(unsigned char **ptr, char data)
|
||||
{
|
||||
d_putb(*ptr, data);
|
||||
*ptr += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->storew()
|
||||
* DESCRIPTION: incrementally store a word of data
|
||||
*/
|
||||
void d_storew(unsigned char **ptr, short data)
|
||||
{
|
||||
d_putw(*ptr, data);
|
||||
*ptr += 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->storel()
|
||||
* DESCRIPTION: incrementally store a long word of data
|
||||
*/
|
||||
void d_storel(unsigned char **ptr, long data)
|
||||
{
|
||||
d_putl(*ptr, data);
|
||||
*ptr += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->stores()
|
||||
* DESCRIPTION: incrementally store a string
|
||||
*/
|
||||
void d_stores(unsigned char **ptr, char *src, int size)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = strlen(src);
|
||||
if (len > --size)
|
||||
len = 0;
|
||||
|
||||
d_storeb(ptr, (unsigned char) len);
|
||||
|
||||
memcpy(*ptr, src, len);
|
||||
memset(*ptr + len, 0, size - len);
|
||||
|
||||
*ptr += size;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: calctzdiff()
|
||||
* DESCRIPTION: calculate the timezone difference between local time and UTC
|
||||
*/
|
||||
static
|
||||
void calctzdiff(void)
|
||||
{
|
||||
time_t t;
|
||||
int isdst;
|
||||
struct tm tm, *tmp;
|
||||
|
||||
time(&t);
|
||||
isdst = localtime(&t)->tm_isdst;
|
||||
|
||||
tmp = gmtime(&t);
|
||||
if (tmp)
|
||||
{
|
||||
tm = *tmp;
|
||||
tm.tm_isdst = isdst;
|
||||
|
||||
tzdiff = t - mktime(&tm);
|
||||
}
|
||||
else
|
||||
tzdiff = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->tomtime()
|
||||
* DESCRIPTION: convert UNIX time to Macintosh time
|
||||
*/
|
||||
unsigned long d_tomtime(unsigned long secs)
|
||||
{
|
||||
time_t utime = secs;
|
||||
|
||||
if (tzdiff == -1)
|
||||
calctzdiff();
|
||||
|
||||
return utime + tzdiff + MUTDIFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->toutime()
|
||||
* DESCRIPTION: convert Macintosh time to UNIX time
|
||||
*/
|
||||
unsigned long d_toutime(unsigned long secs)
|
||||
{
|
||||
time_t utime = secs;
|
||||
|
||||
if (tzdiff == -1)
|
||||
calctzdiff();
|
||||
|
||||
return utime - MUTDIFF - tzdiff;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: data->relstring()
|
||||
* DESCRIPTION: compare two strings as per MacOS for HFS
|
||||
*/
|
||||
int d_relstring(char *str1, char *str2)
|
||||
{
|
||||
int diff;
|
||||
|
||||
while (*str1 && *str2)
|
||||
{
|
||||
diff = hfs_charorder[(unsigned char) *str1] -
|
||||
hfs_charorder[(unsigned char) *str2];
|
||||
|
||||
if (diff)
|
||||
return diff;
|
||||
|
||||
++str1, ++str2;
|
||||
}
|
||||
|
||||
if (! *str1 && *str2)
|
||||
return -1;
|
||||
else if (*str1 && ! *str2)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
char d_getb(unsigned char *);
|
||||
short d_getw(unsigned char *);
|
||||
long d_getl(unsigned char *);
|
||||
|
||||
void d_putb(unsigned char *, char);
|
||||
void d_putw(unsigned char *, short);
|
||||
void d_putl(unsigned char *, long);
|
||||
|
||||
void d_fetchb(unsigned char **, char *);
|
||||
void d_fetchw(unsigned char **, short *);
|
||||
void d_fetchl(unsigned char **, long *);
|
||||
void d_fetchs(unsigned char **, char *, int);
|
||||
|
||||
void d_storeb(unsigned char **, char);
|
||||
void d_storew(unsigned char **, short);
|
||||
void d_storel(unsigned char **, long);
|
||||
void d_stores(unsigned char **, char *, int);
|
||||
|
||||
unsigned long d_tomtime(unsigned long);
|
||||
unsigned long d_toutime(unsigned long);
|
||||
|
||||
int d_relstring(char *, char *);
|
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
# include <string.h>
|
||||
# include <errno.h>
|
||||
|
||||
# include "internal.h"
|
||||
# include "data.h"
|
||||
# include "block.h"
|
||||
# include "file.h"
|
||||
# include "btree.h"
|
||||
# include "record.h"
|
||||
# include "volume.h"
|
||||
|
||||
/* #include <stdio.h> */
|
||||
|
||||
|
||||
/*
|
||||
* NAME: file->selectfork()
|
||||
* DESCRIPTION: choose a fork for file operations
|
||||
*/
|
||||
void f_selectfork(hfsfile *file, int fork)
|
||||
{
|
||||
if (fork == 0)
|
||||
{
|
||||
file->fork = fkData;
|
||||
memcpy(file->ext, file->cat.u.fil.filExtRec, sizeof(ExtDataRec));
|
||||
}
|
||||
else
|
||||
{
|
||||
file->fork = fkRsrc;
|
||||
memcpy(file->ext, file->cat.u.fil.filRExtRec, sizeof(ExtDataRec));
|
||||
}
|
||||
|
||||
file->fabn = 0;
|
||||
file->pos = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: file->getptrs()
|
||||
* DESCRIPTION: make pointers to the current fork's lengths and extents
|
||||
*/
|
||||
void f_getptrs(hfsfile *file, unsigned long **lglen,
|
||||
unsigned long **pylen, ExtDataRec **extrec)
|
||||
{
|
||||
if (file->fork == fkData)
|
||||
{
|
||||
if (lglen)
|
||||
*lglen = &file->cat.u.fil.filLgLen;
|
||||
if (pylen)
|
||||
*pylen = &file->cat.u.fil.filPyLen;
|
||||
if (extrec)
|
||||
*extrec = &file->cat.u.fil.filExtRec;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lglen)
|
||||
*lglen = &file->cat.u.fil.filRLgLen;
|
||||
if (pylen)
|
||||
*pylen = &file->cat.u.fil.filRPyLen;
|
||||
if (extrec)
|
||||
*extrec = &file->cat.u.fil.filRExtRec;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: file->doblock()
|
||||
* DESCRIPTION: read or write a numbered block from a file
|
||||
*/
|
||||
int f_doblock(hfsfile *file, unsigned long num, block *bp,
|
||||
int (*func)(hfsvol *, unsigned int, unsigned int, block *))
|
||||
{
|
||||
unsigned int abnum;
|
||||
unsigned int blnum;
|
||||
unsigned int fabn;
|
||||
int i;
|
||||
|
||||
abnum = num / file->vol->lpa;
|
||||
blnum = num % file->vol->lpa;
|
||||
|
||||
/* locate the appropriate extent record */
|
||||
|
||||
fabn = file->fabn;
|
||||
|
||||
if (abnum < fabn)
|
||||
{
|
||||
ExtDataRec *extrec;
|
||||
|
||||
f_getptrs(file, 0, 0, &extrec);
|
||||
|
||||
fabn = file->fabn = 0;
|
||||
memcpy(file->ext, extrec, sizeof(ExtDataRec));
|
||||
}
|
||||
else
|
||||
abnum -= fabn;
|
||||
|
||||
while (1)
|
||||
{
|
||||
unsigned int num;
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
num = file->ext[i].xdrNumABlks;
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
if (i > 0) {
|
||||
/* SHOULD NOT HAPPEN! - all the files should not be fragmented
|
||||
if this happens, then a serious problem has occured, may be
|
||||
a hard linked file? */
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"file: %s %d\n",file->name, i); */
|
||||
#endif /* DEBUG */
|
||||
ERROR(HCE_ERROR, "Possible Catalog file overflow - please report error");
|
||||
return -1;
|
||||
}
|
||||
#endif /* APPLE_HYB */
|
||||
if (abnum < num)
|
||||
return func(file->vol, file->ext[i].xdrStABN + abnum, blnum, bp);
|
||||
|
||||
fabn += num;
|
||||
abnum -= num;
|
||||
}
|
||||
|
||||
if (v_extsearch(file, fabn, &file->ext, 0) <= 0)
|
||||
return -1;
|
||||
|
||||
file->fabn = fabn;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: file->alloc()
|
||||
* DESCRIPTION: reserve disk blocks for a file
|
||||
*/
|
||||
int f_alloc(hfsfile *file)
|
||||
{
|
||||
hfsvol *vol = file->vol;
|
||||
ExtDescriptor blocks;
|
||||
ExtDataRec *extrec;
|
||||
unsigned long *pylen, clumpsz;
|
||||
unsigned int start, end;
|
||||
node n;
|
||||
int i;
|
||||
|
||||
clumpsz = file->clump;
|
||||
if (clumpsz == 0)
|
||||
clumpsz = vol->mdb.drClpSiz;
|
||||
|
||||
blocks.xdrNumABlks = clumpsz / vol->mdb.drAlBlkSiz;
|
||||
|
||||
if (v_allocblocks(vol, &blocks) < 0)
|
||||
return -1;
|
||||
|
||||
/* update the file's extents */
|
||||
|
||||
f_getptrs(file, 0, &pylen, &extrec);
|
||||
|
||||
start = file->fabn;
|
||||
end = *pylen / vol->mdb.drAlBlkSiz;
|
||||
|
||||
n.nnum = 0;
|
||||
i = -1;
|
||||
|
||||
while (start < end)
|
||||
{
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
unsigned int num;
|
||||
|
||||
num = file->ext[i].xdrNumABlks;
|
||||
start += num;
|
||||
|
||||
if (start == end)
|
||||
break;
|
||||
else if (start > end)
|
||||
{
|
||||
v_freeblocks(vol, &blocks);
|
||||
ERROR(EIO, "file extents exceed file physical length");
|
||||
return -1;
|
||||
}
|
||||
else if (num == 0)
|
||||
{
|
||||
v_freeblocks(vol, &blocks);
|
||||
ERROR(EIO, "empty file extent");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (start == end)
|
||||
break;
|
||||
|
||||
if (v_extsearch(file, start, &file->ext, &n) <= 0)
|
||||
{
|
||||
v_freeblocks(vol, &blocks);
|
||||
return -1;
|
||||
}
|
||||
|
||||
file->fabn = start;
|
||||
}
|
||||
|
||||
if (i >= 0 &&
|
||||
file->ext[i].xdrStABN + file->ext[i].xdrNumABlks == blocks.xdrStABN)
|
||||
file->ext[i].xdrNumABlks += blocks.xdrNumABlks;
|
||||
else
|
||||
{
|
||||
/* create a new extent descriptor */
|
||||
|
||||
if (++i < 3)
|
||||
file->ext[i] = blocks;
|
||||
else
|
||||
{
|
||||
ExtKeyRec key;
|
||||
unsigned char record[HFS_EXTRECMAXLEN];
|
||||
int reclen;
|
||||
|
||||
/* record is full; create a new one */
|
||||
|
||||
file->ext[0] = blocks;
|
||||
|
||||
for (i = 1; i < 3; ++i)
|
||||
{
|
||||
file->ext[i].xdrStABN = 0;
|
||||
file->ext[i].xdrNumABlks = 0;
|
||||
}
|
||||
|
||||
file->fabn = start;
|
||||
|
||||
r_makeextkey(&key, file->fork, file->cat.u.fil.filFlNum, end);
|
||||
r_packextkey(&key, record, &reclen);
|
||||
r_packextdata(&file->ext, HFS_RECDATA(record), &reclen);
|
||||
|
||||
if (bt_insert(&vol->ext, record, reclen) < 0)
|
||||
{
|
||||
v_freeblocks(vol, &blocks);
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= 0)
|
||||
{
|
||||
/* store the modified extent record */
|
||||
|
||||
if (file->fabn)
|
||||
{
|
||||
if ((n.nnum == 0 &&
|
||||
v_extsearch(file, file->fabn, 0, &n) <= 0) ||
|
||||
v_putextrec(&file->ext, &n) < 0)
|
||||
{
|
||||
v_freeblocks(vol, &blocks);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(extrec, file->ext, sizeof(ExtDataRec));
|
||||
}
|
||||
|
||||
*pylen += blocks.xdrNumABlks * vol->mdb.drAlBlkSiz;
|
||||
|
||||
file->flags |= HFS_UPDATE_CATREC;
|
||||
|
||||
return blocks.xdrNumABlks;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: file->trunc()
|
||||
* DESCRIPTION: release disk blocks unneeded by a file
|
||||
*/
|
||||
int f_trunc(hfsfile *file)
|
||||
{
|
||||
ExtDataRec *extrec;
|
||||
unsigned long *lglen, *pylen, alblksz, newpylen;
|
||||
unsigned int dlen, start, end;
|
||||
node n;
|
||||
int i;
|
||||
|
||||
f_getptrs(file, &lglen, &pylen, &extrec);
|
||||
|
||||
alblksz = file->vol->mdb.drAlBlkSiz;
|
||||
newpylen = (*lglen / alblksz + (*lglen % alblksz != 0)) * alblksz;
|
||||
|
||||
if (newpylen > *pylen)
|
||||
{
|
||||
ERROR(EIO, "file size exceeds physical length");
|
||||
return -1;
|
||||
}
|
||||
else if (newpylen == *pylen)
|
||||
return 0;
|
||||
|
||||
dlen = (*pylen - newpylen) / alblksz;
|
||||
|
||||
start = file->fabn;
|
||||
end = newpylen / alblksz;
|
||||
|
||||
if (start >= end)
|
||||
{
|
||||
start = file->fabn = 0;
|
||||
memcpy(file->ext, extrec, sizeof(ExtDataRec));
|
||||
}
|
||||
|
||||
n.nnum = 0;
|
||||
i = -1;
|
||||
|
||||
while (start < end)
|
||||
{
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
unsigned int num;
|
||||
|
||||
num = file->ext[i].xdrNumABlks;
|
||||
start += num;
|
||||
|
||||
if (start >= end)
|
||||
break;
|
||||
else if (num == 0)
|
||||
{
|
||||
ERROR(EIO, "empty file extent");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (start >= end)
|
||||
break;
|
||||
|
||||
if (v_extsearch(file, start, &file->ext, &n) <= 0)
|
||||
return -1;
|
||||
|
||||
file->fabn = start;
|
||||
}
|
||||
|
||||
if (start > end)
|
||||
{
|
||||
ExtDescriptor blocks;
|
||||
|
||||
file->ext[i].xdrNumABlks -= start - end;
|
||||
dlen -= start - end;
|
||||
|
||||
blocks.xdrStABN = file->ext[i].xdrStABN + file->ext[i].xdrNumABlks;
|
||||
blocks.xdrNumABlks = start - end;
|
||||
|
||||
v_freeblocks(file->vol, &blocks);
|
||||
}
|
||||
|
||||
*pylen = newpylen;
|
||||
|
||||
file->flags |= HFS_UPDATE_CATREC;
|
||||
|
||||
do
|
||||
{
|
||||
while (dlen && ++i < 3)
|
||||
{
|
||||
unsigned int num;
|
||||
|
||||
num = file->ext[i].xdrNumABlks;
|
||||
start += num;
|
||||
|
||||
if (num == 0)
|
||||
{
|
||||
ERROR(EIO, "empty file extent");
|
||||
return -1;
|
||||
}
|
||||
else if (num > dlen)
|
||||
{
|
||||
ERROR(EIO, "file extents exceed physical size");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dlen -= num;
|
||||
v_freeblocks(file->vol, &file->ext[i]);
|
||||
|
||||
file->ext[i].xdrStABN = 0;
|
||||
file->ext[i].xdrNumABlks = 0;
|
||||
}
|
||||
|
||||
if (file->fabn)
|
||||
{
|
||||
if (n.nnum == 0 &&
|
||||
v_extsearch(file, file->fabn, 0, &n) <= 0)
|
||||
return -1;
|
||||
|
||||
if (file->ext[0].xdrNumABlks)
|
||||
{
|
||||
if (v_putextrec(&file->ext, &n) < 0)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bt_delete(&file->vol->ext, HFS_NODEREC(n, n.rnum)) < 0)
|
||||
return -1;
|
||||
|
||||
n.nnum = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(extrec, file->ext, sizeof(ExtDataRec));
|
||||
|
||||
if (dlen)
|
||||
{
|
||||
if (v_extsearch(file, start, &file->ext, &n) <= 0)
|
||||
return -1;
|
||||
|
||||
file->fabn = start;
|
||||
i = -1;
|
||||
}
|
||||
}
|
||||
while (dlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: file->flush()
|
||||
* DESCRIPTION: flush all pending changes to an open file
|
||||
*/
|
||||
int f_flush(hfsfile *file)
|
||||
{
|
||||
hfsvol *vol = file->vol;
|
||||
|
||||
if (! (vol->flags & HFS_READONLY))
|
||||
{
|
||||
if (file->flags & HFS_UPDATE_CATREC)
|
||||
{
|
||||
node n;
|
||||
|
||||
file->cat.u.fil.filStBlk = file->cat.u.fil.filExtRec[0].xdrStABN;
|
||||
file->cat.u.fil.filRStBlk = file->cat.u.fil.filRExtRec[0].xdrStABN;
|
||||
file->cat.u.fil.filClpSize = file->clump;
|
||||
|
||||
if (v_catsearch(file->vol, file->parid, file->name, 0, 0, &n) <= 0 ||
|
||||
v_putcatrec(&file->cat, &n) < 0)
|
||||
return -1;
|
||||
|
||||
file->flags &= ~HFS_UPDATE_CATREC;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
enum {
|
||||
fkData = 0x00,
|
||||
fkRsrc = 0xff
|
||||
};
|
||||
|
||||
void f_selectfork(hfsfile *, int);
|
||||
void f_getptrs(hfsfile *, unsigned long **, unsigned long **, ExtDataRec **);
|
||||
|
||||
int f_doblock(hfsfile *, unsigned long, block *,
|
||||
int (*)(hfsvol *, unsigned int, unsigned int, block *));
|
||||
|
||||
# define f_getblock(file, num, bp) f_doblock(file, num, bp, b_readab)
|
||||
# define f_putblock(file, num, bp) f_doblock(file, num, bp, b_writeab)
|
||||
|
||||
int f_alloc(hfsfile *);
|
||||
int f_trunc(hfsfile *);
|
||||
int f_flush(hfsfile *);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
# include <time.h>
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
#include "hybrid.h"
|
||||
|
||||
/* don't need device locking for mkhybrid */
|
||||
#ifndef NODEVLOCKS
|
||||
#define NODEVLOCKS
|
||||
#endif /* NODEVLOCKS */
|
||||
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
# define HFS_BLOCKSZ 512
|
||||
# define HFS_MAX_FLEN 31
|
||||
# define HFS_MAX_VLEN 27
|
||||
|
||||
typedef struct _hfsvol_ hfsvol;
|
||||
typedef struct _hfsfile_ hfsfile;
|
||||
typedef struct _hfsdir_ hfsdir;
|
||||
|
||||
typedef struct {
|
||||
char name[HFS_MAX_VLEN + 1]; /* name of volume */
|
||||
int flags; /* volume flags */
|
||||
unsigned long totbytes; /* total bytes on volume */
|
||||
unsigned long freebytes; /* free bytes on volume */
|
||||
time_t crdate; /* volume creation date */
|
||||
time_t mddate; /* last volume modification date */
|
||||
} hfsvolent;
|
||||
|
||||
typedef struct {
|
||||
char name[HFS_MAX_FLEN + 1]; /* catalog name */
|
||||
int flags; /* bit flags */
|
||||
long cnid; /* catalog node id (CNID) */
|
||||
long parid; /* CNID of parent directory */
|
||||
time_t crdate; /* date of creation */
|
||||
time_t mddate; /* date of last modification */
|
||||
unsigned long dsize; /* size of data fork */
|
||||
unsigned long rsize; /* size of resource fork */
|
||||
char type[5]; /* file type code (plus null) */
|
||||
char creator[5]; /* file creator code (plus null) */
|
||||
short fdflags; /* Macintosh Finder flags */
|
||||
} hfsdirent;
|
||||
|
||||
# define HFS_ISDIR 0x01
|
||||
# define HFS_ISLOCKED 0x02
|
||||
|
||||
# define HFS_CNID_ROOTPAR 1
|
||||
# define HFS_CNID_ROOTDIR 2
|
||||
# define HFS_CNID_EXT 3
|
||||
# define HFS_CNID_CAT 4
|
||||
# define HFS_CNID_BADALLOC 5
|
||||
|
||||
# define HFS_FNDR_ISONDESK (1 << 0)
|
||||
# define HFS_FNDR_COLOR 0x0e
|
||||
# define HFS_FNDR_COLORRESERVED (1 << 4)
|
||||
# define HFS_FNDR_REQUIRESSWITCHLAUNCH (1 << 5)
|
||||
# define HFS_FNDR_ISSHARED (1 << 6)
|
||||
# define HFS_FNDR_HASNOINITS (1 << 7)
|
||||
# define HFS_FNDR_HASBEENINITED (1 << 8)
|
||||
# define HFS_FNDR_RESERVED (1 << 9)
|
||||
# define HFS_FNDR_HASCUSTOMICON (1 << 10)
|
||||
# define HFS_FNDR_ISSTATIONERY (1 << 11)
|
||||
# define HFS_FNDR_NAMELOCKED (1 << 12)
|
||||
# define HFS_FNDR_HASBUNDLE (1 << 13)
|
||||
# define HFS_FNDR_ISINVISIBLE (1 << 14)
|
||||
# define HFS_FNDR_ISALIAS (1 << 15)
|
||||
|
||||
extern char *hfs_error;
|
||||
extern unsigned char hfs_charorder[];
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
hfsvol *hfs_mount(hce_mem *, int, int);
|
||||
#else
|
||||
hfsvol *hfs_mount(char *, int, int);
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
int hfs_flush(hfsvol *);
|
||||
void hfs_flushall(void);
|
||||
#ifdef APPLE_HYB
|
||||
int hfs_umount(hfsvol *, long);
|
||||
#else
|
||||
int hfs_umount(hfsvol *);
|
||||
#endif /* APPLE_HYB */
|
||||
void hfs_umountall(void);
|
||||
hfsvol *hfs_getvol(char *);
|
||||
void hfs_setvol(hfsvol *);
|
||||
|
||||
int hfs_vstat(hfsvol *, hfsvolent *);
|
||||
#ifdef APPLE_HYB
|
||||
int hfs_format(hce_mem *, int, char *);
|
||||
#else
|
||||
int hfs_format(char *, int, char *);
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
int hfs_chdir(hfsvol *, char *);
|
||||
long hfs_getcwd(hfsvol *);
|
||||
int hfs_setcwd(hfsvol *, long);
|
||||
int hfs_dirinfo(hfsvol *, long *, char *);
|
||||
|
||||
hfsdir *hfs_opendir(hfsvol *, char *);
|
||||
int hfs_readdir(hfsdir *, hfsdirent *);
|
||||
int hfs_closedir(hfsdir *);
|
||||
|
||||
hfsfile *hfs_open(hfsvol *, char *);
|
||||
int hfs_setfork(hfsfile *, int);
|
||||
int hfs_getfork(hfsfile *);
|
||||
long hfs_read(hfsfile *, void *, unsigned long);
|
||||
long hfs_write(hfsfile *, void *, unsigned long);
|
||||
int hfs_truncate(hfsfile *, unsigned long);
|
||||
long hfs_lseek(hfsfile *, long, int);
|
||||
#ifdef APPLE_HYB
|
||||
int hfs_close(hfsfile *, long, long);
|
||||
#else
|
||||
int hfs_close(hfsfile *);
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
int hfs_stat(hfsvol *, char *, hfsdirent *);
|
||||
int hfs_fstat(hfsfile *, hfsdirent *);
|
||||
int hfs_setattr(hfsvol *, char *, hfsdirent *);
|
||||
int hfs_fsetattr(hfsfile *, hfsdirent *);
|
||||
|
||||
int hfs_mkdir(hfsvol *, char *);
|
||||
int hfs_rmdir(hfsvol *, char *);
|
||||
|
||||
int hfs_create(hfsvol *, char *, char *, char *);
|
||||
int hfs_delete(hfsvol *, char *);
|
||||
|
||||
int hfs_rename(hfsvol *, char *, char *);
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
unsigned short hfs_get_drAllocPtr(hfsfile *);
|
||||
int hfs_set_drAllocPtr(hfsfile *, unsigned short, int size);
|
||||
#endif /* APPLE_HYB */
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
** hybrid.h: extra info needed by libhfs and mkisofs
|
||||
**
|
||||
** James Pearson 15/9/97
|
||||
*/
|
||||
|
||||
#ifndef _HYBRID_H
|
||||
|
||||
#define CTC 2 /* factor to increase initial Catalog file
|
||||
size to prevent the file growing */
|
||||
#define CTC_LOOP 4 /* number of attemps before we give up
|
||||
trying to create the volume */
|
||||
|
||||
#define HCE_ERROR -9999 /* dummy errno value for Catalog file
|
||||
size problems */
|
||||
|
||||
#define HFS_MAP_SIZE 16 /* size of HFS partition maps (8Kb) */
|
||||
|
||||
typedef struct {
|
||||
int hfs_ce_size; /* extents/catalog size in HFS blks */
|
||||
int hfs_hdr_size; /* vol header size in HFS blks */
|
||||
int hfs_dt_size; /* Desktop file size in HFS blks */
|
||||
int hfs_tot_size; /* extents/catalog/dt size in HFS blks */
|
||||
int hfs_map_size; /* size of partition maps in HFS blks */
|
||||
int hfs_vol_size; /* size of volume in bytes */
|
||||
unsigned char *hfs_ce; /* mem copy of extents/catalog files */
|
||||
unsigned char *hfs_hdr; /* mem copy of vol header */
|
||||
unsigned char *hfs_alt_mdb; /* location of alternate MDB */
|
||||
unsigned char *hfs_map; /* location of partiton_maps */
|
||||
int Csize; /* size of allocation unit */
|
||||
int XTCsize; /* default size of catalog/extents files */
|
||||
int ctc_size; /* factor to increase Catalog file size */
|
||||
char *error; /* HFS error message */
|
||||
} hce_mem;
|
||||
|
||||
#define ERROR_SIZE 1024
|
||||
|
||||
#define _HYBRID_H
|
||||
#endif /* _HYBRID_H */
|
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
# include <time.h>
|
||||
|
||||
# include "hfs.h"
|
||||
|
||||
# define ERROR(code, str) (hfs_error = (str), errno = (code))
|
||||
|
||||
# define SIZE(type, n) ((size_t) (sizeof(type) * (n)))
|
||||
# define ALLOC(type, n) ((type *) malloc(SIZE(type, n)))
|
||||
# define ALLOCX(type, n) ((n) ? ALLOC(type, n) : (type *) 0)
|
||||
# define FREE(ptr) ((ptr) ? (void) free((void *) ptr) : (void) 0)
|
||||
|
||||
# define REALLOC(ptr, type, n) \
|
||||
((type *) ((ptr) ? realloc(ptr, SIZE(type, n)) : malloc(SIZE(type, n))))
|
||||
# define REALLOCX(ptr, type, n) \
|
||||
((n) ? REALLOC(type, n) : (FREE(ptr), (type *) 0))
|
||||
|
||||
# define BMTST(bm, num) \
|
||||
(((char *) (bm))[(num) >> 3] & (0x80 >> ((num) & 0x07)))
|
||||
# define BMSET(bm, num) \
|
||||
(((char *) (bm))[(num) >> 3] |= (0x80 >> ((num) & 0x07)))
|
||||
# define BMCLR(bm, num) \
|
||||
(((char *) (bm))[(num) >> 3] &= ~(0x80 >> ((num) & 0x07)))
|
||||
|
||||
typedef unsigned char block[HFS_BLOCKSZ];
|
||||
|
||||
typedef signed char Char;
|
||||
typedef unsigned char UChar;
|
||||
typedef signed char SignedByte;
|
||||
typedef signed short Integer;
|
||||
typedef unsigned short UInteger;
|
||||
typedef signed long LongInt;
|
||||
typedef unsigned long ULongInt;
|
||||
typedef char Str15[16];
|
||||
typedef char Str31[32];
|
||||
typedef long OSType;
|
||||
|
||||
typedef struct {
|
||||
UInteger xdrStABN; /* first allocation block */
|
||||
UInteger xdrNumABlks; /* number of allocation blocks */
|
||||
} ExtDescriptor;
|
||||
|
||||
typedef ExtDescriptor ExtDataRec[3];
|
||||
|
||||
typedef struct {
|
||||
SignedByte xkrKeyLen; /* key length */
|
||||
SignedByte xkrFkType; /* fork type (0x00/0xff == data/resource */
|
||||
ULongInt xkrFNum; /* file number */
|
||||
UInteger xkrFABN; /* starting file allocation block */
|
||||
} ExtKeyRec;
|
||||
|
||||
typedef struct {
|
||||
SignedByte ckrKeyLen; /* key length */
|
||||
SignedByte ckrResrv1; /* reserved */
|
||||
ULongInt ckrParID; /* parent directory ID */
|
||||
Str31 ckrCName; /* catalog node name */
|
||||
} CatKeyRec;
|
||||
|
||||
# define HFS_MAP1SZ 256
|
||||
# define HFS_MAPXSZ 492
|
||||
|
||||
# define HFS_NODEREC(nd, rnum) ((nd).data + (nd).roff[rnum])
|
||||
|
||||
# define HFS_RECKEYLEN(ptr) (*(unsigned char *) (ptr))
|
||||
# define HFS_RECKEYSKIP(ptr) ((1 + HFS_RECKEYLEN(ptr) + 1) & ~1)
|
||||
# define HFS_RECDATA(ptr) ((ptr) + HFS_RECKEYSKIP(ptr))
|
||||
|
||||
# define HFS_CATDATALEN sizeof(CatDataRec)
|
||||
# define HFS_EXTDATALEN sizeof(ExtDataRec)
|
||||
|
||||
# define HFS_CATKEYLEN sizeof(CatKeyRec)
|
||||
# define HFS_EXTKEYLEN sizeof(ExtKeyRec)
|
||||
|
||||
# define HFS_CATRECMAXLEN (HFS_CATKEYLEN + HFS_CATDATALEN)
|
||||
# define HFS_EXTRECMAXLEN (HFS_EXTKEYLEN + HFS_EXTDATALEN)
|
||||
|
||||
# define HFS_MAXRECLEN HFS_CATRECMAXLEN
|
||||
|
||||
typedef struct {
|
||||
Integer v; /* vertical coordinate */
|
||||
Integer h; /* horizontal coordinate */
|
||||
} Point;
|
||||
|
||||
typedef struct {
|
||||
Integer top; /* top edge of rectangle */
|
||||
Integer left; /* left edge */
|
||||
Integer bottom; /* bottom edge */
|
||||
Integer right; /* rightmost edge */
|
||||
} Rect;
|
||||
|
||||
typedef struct {
|
||||
Rect frRect; /* folder's rectangle */
|
||||
Integer frFlags; /* flags */
|
||||
Point frLocation; /* folder's location */
|
||||
Integer frView; /* folder's view */
|
||||
} DInfo;
|
||||
|
||||
typedef struct {
|
||||
Point frScroll; /* scroll position */
|
||||
LongInt frOpenChain; /* directory ID chain of open folders */
|
||||
Integer frUnused; /* reserved */
|
||||
Integer frComment; /* comment ID */
|
||||
LongInt frPutAway; /* directory ID */
|
||||
} DXInfo;
|
||||
|
||||
typedef struct {
|
||||
OSType fdType; /* file type */
|
||||
OSType fdCreator; /* file's creator */
|
||||
Integer fdFlags; /* flags */
|
||||
Point fdLocation; /* file's location */
|
||||
Integer fdFldr; /* file's window */
|
||||
} FInfo;
|
||||
|
||||
typedef struct {
|
||||
Integer fdIconID; /* icon ID */
|
||||
Integer fdUnused[4]; /* reserved */
|
||||
Integer fdComment; /* comment ID */
|
||||
LongInt fdPutAway; /* home directory ID */
|
||||
} FXInfo;
|
||||
|
||||
typedef struct {
|
||||
Integer drSigWord; /* volume signature (0x4244 for HFS) */
|
||||
LongInt drCrDate; /* date and time of volume creation */
|
||||
LongInt drLsMod; /* date and time of last modification */
|
||||
Integer drAtrb; /* volume attributes */
|
||||
UInteger drNmFls; /* number of files in root directory */
|
||||
UInteger drVBMSt; /* first block of volume bit map (always 3) */
|
||||
UInteger drAllocPtr; /* start of next allocation search */
|
||||
UInteger drNmAlBlks; /* number of allocation blocks in volume */
|
||||
ULongInt drAlBlkSiz; /* size (in bytes) of allocation blocks */
|
||||
ULongInt drClpSiz; /* default clump size */
|
||||
UInteger drAlBlSt; /* first allocation block in volume */
|
||||
LongInt drNxtCNID; /* next unused catalog node ID (dir/file ID) */
|
||||
UInteger drFreeBks; /* number of unused allocation blocks */
|
||||
char drVN[28]; /* volume name (1-27 chars) */
|
||||
LongInt drVolBkUp; /* date and time of last backup */
|
||||
Integer drVSeqNum; /* volume backup sequence number */
|
||||
ULongInt drWrCnt; /* volume write count */
|
||||
ULongInt drXTClpSiz; /* clump size for extents overflow file */
|
||||
ULongInt drCTClpSiz; /* clump size for catalog file */
|
||||
UInteger drNmRtDirs; /* number of directories in root directory */
|
||||
ULongInt drFilCnt; /* number of files in volume */
|
||||
ULongInt drDirCnt; /* number of directories in volume */
|
||||
LongInt drFndrInfo[8]; /* information used by the Finder */
|
||||
UInteger drVCSize; /* size (in blocks) of volume cache */
|
||||
UInteger drVBMCSize; /* size (in blocks) of volume bitmap cache */
|
||||
UInteger drCtlCSize; /* size (in blocks) of common volume cache */
|
||||
ULongInt drXTFlSize; /* size (in bytes) of extents overflow file */
|
||||
ExtDataRec drXTExtRec; /* first extent record for extents file */
|
||||
ULongInt drCTFlSize; /* size (in bytes) of catalog file */
|
||||
ExtDataRec drCTExtRec; /* first extent record for catalog file */
|
||||
} MDB;
|
||||
|
||||
# define HFS_ATRB_BUSY (1 << 6)
|
||||
# define HFS_ATRB_HLOCKED (1 << 7)
|
||||
# define HFS_ATRB_UMOUNTED (1 << 8)
|
||||
# define HFS_ATRB_BBSPARED (1 << 9)
|
||||
# define HFS_ATRB_COPYPROT (1 << 14)
|
||||
# define HFS_ATRB_SLOCKED (1 << 15)
|
||||
|
||||
typedef enum {
|
||||
cdrDirRec = 1,
|
||||
cdrFilRec = 2,
|
||||
cdrThdRec = 3,
|
||||
cdrFThdRec = 4
|
||||
} CatDataType;
|
||||
|
||||
typedef struct {
|
||||
SignedByte cdrType; /* record type */
|
||||
SignedByte cdrResrv2; /* reserved */
|
||||
union {
|
||||
struct { /* cdrDirRec */
|
||||
Integer dirFlags; /* directory flags */
|
||||
UInteger dirVal; /* directory valence */
|
||||
ULongInt dirDirID; /* directory ID */
|
||||
LongInt dirCrDat; /* date and time of creation */
|
||||
LongInt dirMdDat; /* date and time of last modification */
|
||||
LongInt dirBkDat; /* date and time of last backup */
|
||||
DInfo dirUsrInfo; /* Finder information */
|
||||
DXInfo dirFndrInfo; /* additional Finder information */
|
||||
LongInt dirResrv[4]; /* reserved */
|
||||
} dir;
|
||||
struct { /* cdrFilRec */
|
||||
SignedByte
|
||||
filFlags; /* file flags */
|
||||
SignedByte
|
||||
filTyp; /* file type */
|
||||
FInfo filUsrWds; /* Finder information */
|
||||
ULongInt filFlNum; /* file ID */
|
||||
UInteger filStBlk; /* first alloc block of data fork */
|
||||
ULongInt filLgLen; /* logical EOF of data fork */
|
||||
ULongInt filPyLen; /* physical EOF of data fork */
|
||||
UInteger filRStBlk; /* first alloc block of resource fork */
|
||||
ULongInt filRLgLen; /* logical EOF of resource fork */
|
||||
ULongInt filRPyLen; /* physical EOF of resource fork */
|
||||
LongInt filCrDat; /* date and time of creation */
|
||||
LongInt filMdDat; /* date and time of last modification */
|
||||
LongInt filBkDat; /* date and time of last backup */
|
||||
FXInfo filFndrInfo; /* additional Finder information */
|
||||
UInteger filClpSize; /* file clump size */
|
||||
ExtDataRec
|
||||
filExtRec; /* first data fork extent record */
|
||||
ExtDataRec
|
||||
filRExtRec; /* first resource fork extent record */
|
||||
LongInt filResrv; /* reserved */
|
||||
} fil;
|
||||
struct { /* cdrThdRec */
|
||||
LongInt thdResrv[2]; /* reserved */
|
||||
ULongInt thdParID; /* parent ID for this directory */
|
||||
Str31 thdCName; /* name of this directory */
|
||||
} dthd;
|
||||
struct { /* cdrFThdRec */
|
||||
LongInt fthdResrv[2]; /* reserved */
|
||||
ULongInt fthdParID; /* parent ID for this file */
|
||||
Str31 fthdCName; /* name of this file */
|
||||
} fthd;
|
||||
} u;
|
||||
} CatDataRec;
|
||||
|
||||
struct _hfsfile_ {
|
||||
struct _hfsvol_ *vol; /* pointer to volume descriptor */
|
||||
long parid; /* parent directory ID of this file */
|
||||
char name[HFS_MAX_FLEN + 1]; /* catalog name of this file */
|
||||
CatDataRec cat; /* catalog information */
|
||||
ExtDataRec ext; /* current extent record */
|
||||
unsigned int fabn; /* starting file allocation block number */
|
||||
int fork; /* current selected fork for I/O */
|
||||
unsigned long pos; /* current file seek pointer */
|
||||
unsigned long clump; /* file's clump size, for allocation */
|
||||
int flags; /* bit flags */
|
||||
|
||||
struct _hfsfile_ *prev;
|
||||
struct _hfsfile_ *next;
|
||||
};
|
||||
|
||||
# define HFS_UPDATE_CATREC 0x01
|
||||
|
||||
typedef struct {
|
||||
ULongInt ndFLink; /* forward link */
|
||||
ULongInt ndBLink; /* backward link */
|
||||
SignedByte ndType; /* node type */
|
||||
SignedByte ndNHeight; /* node level */
|
||||
UInteger ndNRecs; /* number of records in node */
|
||||
Integer ndResv2; /* reserved */
|
||||
} NodeDescriptor;
|
||||
|
||||
# define HFS_MAXRECS 35 /* maximum based on minimum record size */
|
||||
|
||||
typedef struct _node_ {
|
||||
struct _btree_ *bt; /* btree to which this node belongs */
|
||||
unsigned long nnum; /* node index */
|
||||
NodeDescriptor nd; /* node descriptor */
|
||||
int rnum; /* current record index */
|
||||
UInteger roff[HFS_MAXRECS + 1]; /* record offsets */
|
||||
block data; /* raw contents of node */
|
||||
} node;
|
||||
|
||||
enum {
|
||||
ndIndxNode = 0x00,
|
||||
ndHdrNode = 0x01,
|
||||
ndMapNode = 0x02,
|
||||
ndLeafNode = 0xff
|
||||
};
|
||||
|
||||
struct _hfsdir_ {
|
||||
struct _hfsvol_ *vol; /* associated volume */
|
||||
long dirid; /* directory ID of interest (or 0) */
|
||||
|
||||
node n; /* current B*-tree node */
|
||||
struct _hfsvol_ *vptr; /* current volume pointer */
|
||||
|
||||
struct _hfsdir_ *prev;
|
||||
struct _hfsdir_ *next;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
UInteger bthDepth; /* current depth of tree */
|
||||
ULongInt bthRoot; /* number of root node */
|
||||
ULongInt bthNRecs; /* number of leaf records in tree */
|
||||
ULongInt bthFNode; /* number of first leaf node */
|
||||
ULongInt bthLNode; /* number of last leaf node */
|
||||
UInteger bthNodeSize; /* size of a node */
|
||||
UInteger bthKeyLen; /* maximum length of a key */
|
||||
ULongInt bthNNodes; /* total number of nodes in tree */
|
||||
ULongInt bthFree; /* number of free nodes */
|
||||
SignedByte bthResv[76]; /* reserved */
|
||||
} BTHdrRec;
|
||||
|
||||
typedef struct _btree_ {
|
||||
hfsfile f; /* subset file information */
|
||||
node hdrnd; /* header node */
|
||||
BTHdrRec hdr; /* header record */
|
||||
char *map; /* usage bitmap */
|
||||
unsigned long mapsz; /* number of bytes in bitmap */
|
||||
int flags; /* bit flags */
|
||||
|
||||
int (*compare)(unsigned char *, unsigned char *);
|
||||
/* key comparison function */
|
||||
} btree;
|
||||
|
||||
# define HFS_UPDATE_BTHDR 0x01
|
||||
|
||||
struct _hfsvol_ {
|
||||
int fd; /* volume's open file descriptor */
|
||||
int flags; /* bit flags */
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
hce_mem *hce; /* Extras needed by libhfs/mkisofs */
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
int pnum; /* ordinal HFS partition number */
|
||||
unsigned long vstart; /* logical block offset to start of volume */
|
||||
unsigned long vlen; /* number of logical blocks in volume */
|
||||
unsigned int lpa; /* number of logical blocks per allocation block */
|
||||
|
||||
MDB mdb; /* master directory block */
|
||||
block *vbm; /* volume bit map */
|
||||
btree ext; /* B*-tree control block for extents overflow file */
|
||||
btree cat; /* B*-tree control block for catalog file */
|
||||
long cwd; /* directory id of current working directory */
|
||||
|
||||
int refs; /* number of external references to this volume */
|
||||
hfsfile *files; /* list of open files */
|
||||
hfsdir *dirs; /* list of open directories */
|
||||
|
||||
struct _hfsvol_ *prev;
|
||||
struct _hfsvol_ *next;
|
||||
};
|
||||
|
||||
# define HFS_READONLY 0x01
|
||||
|
||||
# define HFS_UPDATE_MDB 0x10
|
||||
# define HFS_UPDATE_ALTMDB 0x20
|
||||
# define HFS_UPDATE_VBM 0x40
|
||||
|
||||
extern hfsvol *hfs_mounts;
|
||||
extern hfsvol *hfs_curvol;
|
|
@ -0,0 +1,515 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <errno.h>
|
||||
# include <unistd.h>
|
||||
# include <fcntl.h>
|
||||
|
||||
# include "internal.h"
|
||||
# include "data.h"
|
||||
# include "block.h"
|
||||
# include "low.h"
|
||||
# include "file.h"
|
||||
|
||||
/*
|
||||
* NAME: low->lockvol()
|
||||
* DESCRIPTION: prevent destructive simultaneous access
|
||||
*/
|
||||
int l_lockvol(hfsvol *vol)
|
||||
{
|
||||
# ifndef NODEVLOCKS
|
||||
|
||||
struct flock lock;
|
||||
|
||||
lock.l_type = (vol->flags & HFS_READONLY) ? F_RDLCK : F_WRLCK;
|
||||
lock.l_start = 0;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_len = 0;
|
||||
|
||||
if (fcntl(vol->fd, F_SETLK, &lock) < 0)
|
||||
{
|
||||
ERROR(errno, "unable to obtain lock for device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: low->readblock0()
|
||||
* DESCRIPTION: read the first sector and get bearings
|
||||
*/
|
||||
int l_readblock0(hfsvol *vol)
|
||||
{
|
||||
block b;
|
||||
unsigned char *ptr = b;
|
||||
Block0 rec;
|
||||
|
||||
if (b_readlb(vol, 0, &b) < 0)
|
||||
return -1;
|
||||
|
||||
d_fetchw(&ptr, &rec.sbSig);
|
||||
d_fetchw(&ptr, &rec.sbBlkSize);
|
||||
d_fetchl(&ptr, &rec.sbBlkCount);
|
||||
d_fetchw(&ptr, &rec.sbDevType);
|
||||
d_fetchw(&ptr, &rec.sbDevId);
|
||||
d_fetchl(&ptr, &rec.sbData);
|
||||
d_fetchw(&ptr, &rec.sbDrvrCount);
|
||||
d_fetchl(&ptr, &rec.ddBlock);
|
||||
d_fetchw(&ptr, &rec.ddSize);
|
||||
d_fetchw(&ptr, &rec.ddType);
|
||||
|
||||
switch (rec.sbSig)
|
||||
{
|
||||
case 0x4552: /* block device with a partition table */
|
||||
{
|
||||
if (rec.sbBlkSize != HFS_BLOCKSZ)
|
||||
{
|
||||
ERROR(EINVAL, "unsupported block size");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vol->vlen = rec.sbBlkCount;
|
||||
|
||||
if (l_readpm(vol) < 0)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x4c4b: /* bootable floppy */
|
||||
vol->pnum = 0;
|
||||
break;
|
||||
|
||||
default: /* non-bootable floppy or something else */
|
||||
|
||||
/* some miscreant media may also be partitioned;
|
||||
we attempt to read a partition map, but ignore any failure */
|
||||
|
||||
if (l_readpm(vol) < 0)
|
||||
vol->pnum = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: low->readpm()
|
||||
* DESCRIPTION: read the partition map and locate an HFS volume
|
||||
*/
|
||||
int l_readpm(hfsvol *vol)
|
||||
{
|
||||
block b;
|
||||
unsigned char *ptr;
|
||||
Partition map;
|
||||
unsigned long bnum;
|
||||
int pnum;
|
||||
|
||||
bnum = 1;
|
||||
pnum = vol->pnum;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (b_readlb(vol, bnum, &b) < 0)
|
||||
return -1;
|
||||
|
||||
ptr = b;
|
||||
|
||||
d_fetchw(&ptr, &map.pmSig);
|
||||
d_fetchw(&ptr, &map.pmSigPad);
|
||||
d_fetchl(&ptr, &map.pmMapBlkCnt);
|
||||
d_fetchl(&ptr, &map.pmPyPartStart);
|
||||
d_fetchl(&ptr, &map.pmPartBlkCnt);
|
||||
|
||||
memcpy(map.pmPartName, ptr, 32);
|
||||
map.pmPartName[32] = 0;
|
||||
ptr += 32;
|
||||
|
||||
memcpy(map.pmParType, ptr, 32);
|
||||
map.pmParType[32] = 0;
|
||||
ptr += 32;
|
||||
|
||||
d_fetchl(&ptr, &map.pmLgDataStart);
|
||||
d_fetchl(&ptr, &map.pmDataCnt);
|
||||
d_fetchl(&ptr, &map.pmPartStatus);
|
||||
d_fetchl(&ptr, &map.pmLgBootStart);
|
||||
d_fetchl(&ptr, &map.pmBootSize);
|
||||
d_fetchl(&ptr, &map.pmBootAddr);
|
||||
d_fetchl(&ptr, &map.pmBootAddr2);
|
||||
d_fetchl(&ptr, &map.pmBootEntry);
|
||||
d_fetchl(&ptr, &map.pmBootEntry2);
|
||||
d_fetchl(&ptr, &map.pmBootCksum);
|
||||
|
||||
memcpy(map.pmProcessor, ptr, 16);
|
||||
map.pmProcessor[16] = 0;
|
||||
ptr += 16;
|
||||
|
||||
if (map.pmSig == 0x5453)
|
||||
{
|
||||
/* old partition map sig */
|
||||
|
||||
ERROR(EINVAL, "unsupported partition map signature");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (map.pmSig != 0x504d)
|
||||
{
|
||||
ERROR(EINVAL, "bad partition map");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp((char *) map.pmParType, "Apple_HFS") == 0 && --pnum == 0)
|
||||
{
|
||||
if (map.pmLgDataStart != 0)
|
||||
{
|
||||
ERROR(EINVAL, "unsupported start of partition logical data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vol->vstart = map.pmPyPartStart;
|
||||
vol->vlen = map.pmPartBlkCnt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bnum >= map.pmMapBlkCnt)
|
||||
{
|
||||
ERROR(EINVAL, "can't find HFS partition");
|
||||
return -1;
|
||||
}
|
||||
|
||||
++bnum;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: low->readmdb()
|
||||
* DESCRIPTION: read the master directory block into memory
|
||||
*/
|
||||
int l_readmdb(hfsvol *vol)
|
||||
{
|
||||
block b;
|
||||
unsigned char *ptr = b;
|
||||
MDB *mdb = &vol->mdb;
|
||||
hfsfile *ext = &vol->ext.f;
|
||||
hfsfile *cat = &vol->cat.f;
|
||||
int i;
|
||||
|
||||
if (b_readlb(vol, 2, &b) < 0)
|
||||
return -1;
|
||||
|
||||
d_fetchw(&ptr, &mdb->drSigWord);
|
||||
d_fetchl(&ptr, &mdb->drCrDate);
|
||||
d_fetchl(&ptr, &mdb->drLsMod);
|
||||
d_fetchw(&ptr, &mdb->drAtrb);
|
||||
d_fetchw(&ptr, (short *) &mdb->drNmFls);
|
||||
d_fetchw(&ptr, (short *) &mdb->drVBMSt);
|
||||
d_fetchw(&ptr, (short *) &mdb->drAllocPtr);
|
||||
d_fetchw(&ptr, (short *) &mdb->drNmAlBlks);
|
||||
d_fetchl(&ptr, (long *) &mdb->drAlBlkSiz);
|
||||
d_fetchl(&ptr, (long *) &mdb->drClpSiz);
|
||||
d_fetchw(&ptr, (short *) &mdb->drAlBlSt);
|
||||
d_fetchl(&ptr, &mdb->drNxtCNID);
|
||||
d_fetchw(&ptr, (short *) &mdb->drFreeBks);
|
||||
|
||||
d_fetchs(&ptr, mdb->drVN, sizeof(mdb->drVN));
|
||||
|
||||
if (ptr - b != 64)
|
||||
abort();
|
||||
|
||||
d_fetchl(&ptr, &mdb->drVolBkUp);
|
||||
d_fetchw(&ptr, &mdb->drVSeqNum);
|
||||
d_fetchl(&ptr, (long *) &mdb->drWrCnt);
|
||||
d_fetchl(&ptr, (long *) &mdb->drXTClpSiz);
|
||||
d_fetchl(&ptr, (long *) &mdb->drCTClpSiz);
|
||||
d_fetchw(&ptr, (short *) &mdb->drNmRtDirs);
|
||||
d_fetchl(&ptr, (long *) &mdb->drFilCnt);
|
||||
d_fetchl(&ptr, (long *) &mdb->drDirCnt);
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
d_fetchl(&ptr, &mdb->drFndrInfo[i]);
|
||||
|
||||
if (ptr - b != 124)
|
||||
abort();
|
||||
|
||||
d_fetchw(&ptr, (short *) &mdb->drVCSize);
|
||||
d_fetchw(&ptr, (short *) &mdb->drVBMCSize);
|
||||
d_fetchw(&ptr, (short *) &mdb->drCtlCSize);
|
||||
|
||||
d_fetchl(&ptr, (long *) &mdb->drXTFlSize);
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
d_fetchw(&ptr, (short *) &mdb->drXTExtRec[i].xdrStABN);
|
||||
d_fetchw(&ptr, (short *) &mdb->drXTExtRec[i].xdrNumABlks);
|
||||
}
|
||||
|
||||
if (ptr - b != 146)
|
||||
abort();
|
||||
|
||||
d_fetchl(&ptr, (long *) &mdb->drCTFlSize);
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
d_fetchw(&ptr, (short *) &mdb->drCTExtRec[i].xdrStABN);
|
||||
d_fetchw(&ptr, (short *) &mdb->drCTExtRec[i].xdrNumABlks);
|
||||
}
|
||||
|
||||
if (ptr - b != 162)
|
||||
abort();
|
||||
|
||||
vol->lpa = mdb->drAlBlkSiz / HFS_BLOCKSZ;
|
||||
|
||||
/* extents pseudo-file structs */
|
||||
|
||||
ext->vol = vol;
|
||||
ext->parid = 0;
|
||||
strcpy(ext->name, "extents overflow");
|
||||
|
||||
ext->cat.cdrType = cdrFilRec;
|
||||
/* ext->cat.cdrResrv2 */
|
||||
ext->cat.u.fil.filFlags = 0;
|
||||
ext->cat.u.fil.filTyp = 0;
|
||||
/* ext->cat.u.fil.filUsrWds */
|
||||
ext->cat.u.fil.filFlNum = HFS_CNID_EXT;
|
||||
ext->cat.u.fil.filStBlk = mdb->drXTExtRec[0].xdrStABN;
|
||||
ext->cat.u.fil.filLgLen = mdb->drXTFlSize;
|
||||
ext->cat.u.fil.filPyLen = mdb->drXTFlSize;
|
||||
ext->cat.u.fil.filRStBlk = 0;
|
||||
ext->cat.u.fil.filRLgLen = 0;
|
||||
ext->cat.u.fil.filRPyLen = 0;
|
||||
ext->cat.u.fil.filCrDat = mdb->drCrDate;
|
||||
ext->cat.u.fil.filMdDat = mdb->drLsMod;
|
||||
ext->cat.u.fil.filBkDat = 0;
|
||||
/* ext->cat.u.fil.filFndrInfo */
|
||||
ext->cat.u.fil.filClpSize = 0;
|
||||
|
||||
memcpy(ext->cat.u.fil.filExtRec, mdb->drXTExtRec, sizeof(ExtDataRec));
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
ext->cat.u.fil.filRExtRec[i].xdrStABN = 0;
|
||||
ext->cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
|
||||
}
|
||||
f_selectfork(ext, 0);
|
||||
|
||||
ext->clump = mdb->drXTClpSiz;
|
||||
ext->flags = 0;
|
||||
|
||||
ext->prev = ext->next = 0;
|
||||
|
||||
/* catalog pseudo-file structs */
|
||||
|
||||
cat->vol = vol;
|
||||
cat->parid = 0;
|
||||
strcpy(cat->name, "catalog");
|
||||
|
||||
cat->cat.cdrType = cdrFilRec;
|
||||
/* cat->cat.cdrResrv2 */
|
||||
cat->cat.u.fil.filFlags = 0;
|
||||
cat->cat.u.fil.filTyp = 0;
|
||||
/* cat->cat.u.fil.filUsrWds */
|
||||
cat->cat.u.fil.filFlNum = HFS_CNID_CAT;
|
||||
cat->cat.u.fil.filStBlk = mdb->drCTExtRec[0].xdrStABN;
|
||||
cat->cat.u.fil.filLgLen = mdb->drCTFlSize;
|
||||
cat->cat.u.fil.filPyLen = mdb->drCTFlSize;
|
||||
cat->cat.u.fil.filRStBlk = 0;
|
||||
cat->cat.u.fil.filRLgLen = 0;
|
||||
cat->cat.u.fil.filRPyLen = 0;
|
||||
cat->cat.u.fil.filCrDat = mdb->drCrDate;
|
||||
cat->cat.u.fil.filMdDat = mdb->drLsMod;
|
||||
cat->cat.u.fil.filBkDat = 0;
|
||||
/* cat->cat.u.fil.filFndrInfo */
|
||||
cat->cat.u.fil.filClpSize = 0;
|
||||
|
||||
memcpy(cat->cat.u.fil.filExtRec, mdb->drCTExtRec, sizeof(ExtDataRec));
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
cat->cat.u.fil.filRExtRec[i].xdrStABN = 0;
|
||||
cat->cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
|
||||
}
|
||||
f_selectfork(cat, 0);
|
||||
|
||||
cat->clump = mdb->drCTClpSiz;
|
||||
cat->flags = 0;
|
||||
|
||||
cat->prev = cat->next = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: low->writemdb()
|
||||
* DESCRIPTION: write the master directory block to disk
|
||||
*/
|
||||
int l_writemdb(hfsvol *vol)
|
||||
{
|
||||
block b;
|
||||
unsigned char *ptr = b;
|
||||
MDB *mdb = &vol->mdb;
|
||||
hfsfile *ext = &vol->ext.f;
|
||||
hfsfile *cat = &vol->cat.f;
|
||||
int i;
|
||||
|
||||
memset(&b, 0, sizeof(b));
|
||||
|
||||
mdb->drXTFlSize = ext->cat.u.fil.filPyLen;
|
||||
mdb->drXTClpSiz = ext->clump;
|
||||
memcpy(mdb->drXTExtRec, ext->cat.u.fil.filExtRec, sizeof(ExtDataRec));
|
||||
|
||||
mdb->drCTFlSize = cat->cat.u.fil.filPyLen;
|
||||
mdb->drCTClpSiz = cat->clump;
|
||||
memcpy(mdb->drCTExtRec, cat->cat.u.fil.filExtRec, sizeof(ExtDataRec));
|
||||
|
||||
d_storew(&ptr, mdb->drSigWord);
|
||||
d_storel(&ptr, mdb->drCrDate);
|
||||
d_storel(&ptr, mdb->drLsMod);
|
||||
d_storew(&ptr, mdb->drAtrb);
|
||||
d_storew(&ptr, mdb->drNmFls);
|
||||
d_storew(&ptr, mdb->drVBMSt);
|
||||
d_storew(&ptr, mdb->drAllocPtr);
|
||||
d_storew(&ptr, mdb->drNmAlBlks);
|
||||
d_storel(&ptr, mdb->drAlBlkSiz);
|
||||
d_storel(&ptr, mdb->drClpSiz);
|
||||
d_storew(&ptr, mdb->drAlBlSt);
|
||||
d_storel(&ptr, mdb->drNxtCNID);
|
||||
d_storew(&ptr, mdb->drFreeBks);
|
||||
d_stores(&ptr, mdb->drVN, sizeof(mdb->drVN));
|
||||
|
||||
if (ptr - b != 64)
|
||||
abort();
|
||||
|
||||
d_storel(&ptr, mdb->drVolBkUp);
|
||||
d_storew(&ptr, mdb->drVSeqNum);
|
||||
d_storel(&ptr, mdb->drWrCnt);
|
||||
d_storel(&ptr, mdb->drXTClpSiz);
|
||||
d_storel(&ptr, mdb->drCTClpSiz);
|
||||
d_storew(&ptr, mdb->drNmRtDirs);
|
||||
d_storel(&ptr, mdb->drFilCnt);
|
||||
d_storel(&ptr, mdb->drDirCnt);
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
d_storel(&ptr, mdb->drFndrInfo[i]);
|
||||
|
||||
if (ptr - b != 124)
|
||||
abort();
|
||||
|
||||
d_storew(&ptr, mdb->drVCSize);
|
||||
d_storew(&ptr, mdb->drVBMCSize);
|
||||
d_storew(&ptr, mdb->drCtlCSize);
|
||||
d_storel(&ptr, mdb->drXTFlSize);
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
d_storew(&ptr, mdb->drXTExtRec[i].xdrStABN);
|
||||
d_storew(&ptr, mdb->drXTExtRec[i].xdrNumABlks);
|
||||
}
|
||||
|
||||
if (ptr - b != 146)
|
||||
abort();
|
||||
|
||||
d_storel(&ptr, mdb->drCTFlSize);
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
d_storew(&ptr, mdb->drCTExtRec[i].xdrStABN);
|
||||
d_storew(&ptr, mdb->drCTExtRec[i].xdrNumABlks);
|
||||
}
|
||||
|
||||
if (ptr - b != 162)
|
||||
abort();
|
||||
|
||||
if (b_writelb(vol, 2, &b) < 0)
|
||||
return -1;
|
||||
if (vol->flags & HFS_UPDATE_ALTMDB)
|
||||
{
|
||||
#ifdef APPLE_HYB
|
||||
/* "write" alternative MDB to memory copy */
|
||||
memcpy(vol->hce->hfs_alt_mdb, &b, sizeof(b));
|
||||
#else
|
||||
if (b_writelb(vol, vol->vlen - 2, &b) < 0)
|
||||
return -1;
|
||||
#endif /* APPLE_HYB */
|
||||
}
|
||||
vol->flags &= ~(HFS_UPDATE_MDB | HFS_UPDATE_ALTMDB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: low->readvbm()
|
||||
* DESCRIPTION: read the volume bit map into memory
|
||||
*/
|
||||
int l_readvbm(hfsvol *vol)
|
||||
{
|
||||
int vbmst = vol->mdb.drVBMSt;
|
||||
int vbmsz = (vol->mdb.drNmAlBlks + 4095) / 4096;
|
||||
block *bp;
|
||||
|
||||
if (vol->mdb.drAlBlSt - vbmst < vbmsz)
|
||||
{
|
||||
ERROR(EIO, "volume bitmap collides with volume data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bp = ALLOC(block, vbmsz);
|
||||
if (bp == 0)
|
||||
{
|
||||
ERROR(ENOMEM, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
vol->vbm = bp;
|
||||
|
||||
while (vbmsz--)
|
||||
{
|
||||
if (b_readlb(vol, vbmst++, bp++) < 0)
|
||||
{
|
||||
FREE(vol->vbm);
|
||||
vol->vbm = 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: low->writevbm()
|
||||
* DESCRIPTION: write the volume bit map to disk
|
||||
*/
|
||||
int l_writevbm(hfsvol *vol)
|
||||
{
|
||||
int vbmst = vol->mdb.drVBMSt;
|
||||
int vbmsz = (vol->mdb.drNmAlBlks + 4095) / 4096;
|
||||
block *bp = vol->vbm;
|
||||
|
||||
while (vbmsz--)
|
||||
{
|
||||
if (b_writelb(vol, vbmst++, bp++) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
vol->flags &= ~HFS_UPDATE_VBM;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
Integer sbSig; /* device signature (should be 0x4552) */
|
||||
Integer sbBlkSize; /* block size of the device (in bytes) */
|
||||
LongInt sbBlkCount; /* number of blocks on the device */
|
||||
Integer sbDevType; /* reserved */
|
||||
Integer sbDevId; /* reserved */
|
||||
LongInt sbData; /* reserved */
|
||||
Integer sbDrvrCount; /* number of driver descriptor entries */
|
||||
LongInt ddBlock; /* first driver's starting block */
|
||||
Integer ddSize; /* size of the driver, in 512-byte blocks */
|
||||
Integer ddType; /* driver operating system type (MacOS = 1) */
|
||||
Integer ddPad[243]; /* additional drivers, if any */
|
||||
} Block0;
|
||||
|
||||
typedef struct {
|
||||
Integer bbID; /* boot blocks signature */
|
||||
LongInt bbEntry; /* entry point to boot code */
|
||||
Integer bbVersion; /* boot blocks version number */
|
||||
Integer bbPageFlags; /* used internally */
|
||||
Str15 bbSysName; /* System filename */
|
||||
Str15 bbShellName; /* Finder filename */
|
||||
Str15 bbDbg1Name; /* debugger filename */
|
||||
Str15 bbDbg2Name; /* debugger filename */
|
||||
Str15 bbScreenName; /* name of startup screen */
|
||||
Str15 bbHelloName; /* name of startup program */
|
||||
Str15 bbScrapName; /* name of system scrap file */
|
||||
Integer bbCntFCBs; /* number of FCBs to allocate */
|
||||
Integer bbCntEvts; /* number of event queue elements */
|
||||
LongInt bb128KSHeap; /* system heap size on 128K Mac */
|
||||
LongInt bb256KSHeap; /* used internally */
|
||||
LongInt bbSysHeapSize; /* system heap size on all machines */
|
||||
Integer filler; /* reserved */
|
||||
LongInt bbSysHeapExtra; /* additional system heap space */
|
||||
LongInt bbSysHeapFract; /* fraction of RAM for system heap */
|
||||
} BootBlkHdr;
|
||||
|
||||
typedef struct {
|
||||
Integer pmSig; /* partition signature (0x504d or 0x5453) */
|
||||
Integer pmSigPad; /* reserved */
|
||||
LongInt pmMapBlkCnt; /* number of blocks in partition map */
|
||||
LongInt pmPyPartStart; /* first physical block of partition */
|
||||
LongInt pmPartBlkCnt; /* number of blocks in partition */
|
||||
Char pmPartName[33]; /* partition name */
|
||||
Char pmParType[33]; /* partition type */
|
||||
/*
|
||||
* Apple_partition_map partition map
|
||||
* Apple_Driver device driver
|
||||
* Apple_Driver43 SCSI Manager 4.3 device driver
|
||||
* Apple_MFS Macintosh 64K ROM filesystem
|
||||
* Apple_HFS Macintosh hierarchical filesystem
|
||||
* Apple_Unix_SVR2 Unix filesystem
|
||||
* Apple_PRODOS ProDOS filesystem
|
||||
* Apple_Free unused
|
||||
* Apple_Scratch empty
|
||||
*/
|
||||
LongInt pmLgDataStart; /* first logical block of data area */
|
||||
LongInt pmDataCnt; /* number of blocks in data area */
|
||||
LongInt pmPartStatus; /* partition status information */
|
||||
LongInt pmLgBootStart; /* first logical block of boot code */
|
||||
LongInt pmBootSize; /* size of boot code, in bytes */
|
||||
LongInt pmBootAddr; /* boot code load address */
|
||||
LongInt pmBootAddr2; /* reserved */
|
||||
LongInt pmBootEntry; /* boot code entry point */
|
||||
LongInt pmBootEntry2; /* reserved */
|
||||
LongInt pmBootCksum; /* boot code checksum */
|
||||
Char pmProcessor[17];/* processor type */
|
||||
Integer pmPad[188]; /* reserved */
|
||||
} Partition;
|
||||
|
||||
int l_lockvol(hfsvol *);
|
||||
|
||||
int l_readblock0(hfsvol *);
|
||||
int l_readpm(hfsvol *);
|
||||
|
||||
int l_readmdb(hfsvol *);
|
||||
int l_writemdb(hfsvol *);
|
||||
|
||||
int l_readvbm(hfsvol *);
|
||||
int l_writevbm(hfsvol *);
|
|
@ -0,0 +1,725 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <errno.h>
|
||||
# include <time.h>
|
||||
|
||||
# include "internal.h"
|
||||
# include "data.h"
|
||||
# include "low.h"
|
||||
# include "btree.h"
|
||||
# include "record.h"
|
||||
# include "volume.h"
|
||||
|
||||
/*
|
||||
* NAME: vol->catsearch()
|
||||
* DESCRIPTION: search catalog tree
|
||||
*/
|
||||
int v_catsearch(hfsvol *vol, long parid, char *name,
|
||||
CatDataRec *data, char *cname, node *np)
|
||||
{
|
||||
CatKeyRec key;
|
||||
unsigned char pkey[HFS_CATKEYLEN];
|
||||
node n;
|
||||
unsigned char *ptr;
|
||||
int found;
|
||||
|
||||
if (np == 0)
|
||||
np = &n;
|
||||
|
||||
r_makecatkey(&key, parid, name);
|
||||
r_packcatkey(&key, pkey, 0);
|
||||
|
||||
found = bt_search(&vol->cat, pkey, np);
|
||||
if (found <= 0)
|
||||
return found;
|
||||
|
||||
ptr = HFS_NODEREC(*np, np->rnum);
|
||||
|
||||
if (cname)
|
||||
{
|
||||
r_unpackcatkey(ptr, &key);
|
||||
strcpy(cname, key.ckrCName);
|
||||
}
|
||||
|
||||
if (data)
|
||||
r_unpackcatdata(HFS_RECDATA(ptr), data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->extsearch()
|
||||
* DESCRIPTION: search extents tree
|
||||
*/
|
||||
int v_extsearch(hfsfile *file, unsigned int fabn, ExtDataRec *data, node *np)
|
||||
{
|
||||
ExtKeyRec key;
|
||||
ExtDataRec extsave;
|
||||
unsigned int fabnsave;
|
||||
unsigned char pkey[HFS_EXTKEYLEN];
|
||||
node n;
|
||||
unsigned char *ptr;
|
||||
int found;
|
||||
|
||||
if (np == 0)
|
||||
np = &n;
|
||||
|
||||
r_makeextkey(&key, file->fork, file->cat.u.fil.filFlNum, fabn);
|
||||
r_packextkey(&key, pkey, 0);
|
||||
|
||||
/* in case bt_search() clobbers these */
|
||||
|
||||
memcpy(&extsave, &file->ext, sizeof(ExtDataRec));
|
||||
fabnsave = file->fabn;
|
||||
|
||||
found = bt_search(&file->vol->ext, pkey, np);
|
||||
|
||||
memcpy(&file->ext, &extsave, sizeof(ExtDataRec));
|
||||
file->fabn = fabnsave;
|
||||
|
||||
if (found <= 0)
|
||||
return found;
|
||||
|
||||
if (data)
|
||||
{
|
||||
ptr = HFS_NODEREC(*np, np->rnum);
|
||||
r_unpackextdata(HFS_RECDATA(ptr), data);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->getthread()
|
||||
* DESCRIPTION: retrieve catalog thread information for a file or directory
|
||||
*/
|
||||
int v_getthread(hfsvol *vol, long id, CatDataRec *thread, node *np, int type)
|
||||
{
|
||||
CatDataRec rec;
|
||||
int found;
|
||||
|
||||
if (thread == 0)
|
||||
thread = &rec;
|
||||
|
||||
found = v_catsearch(vol, id, "", thread, 0, np);
|
||||
if (found <= 0)
|
||||
return found;
|
||||
|
||||
if (thread->cdrType != type)
|
||||
{
|
||||
ERROR(EIO, "bad thread record");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->putcatrec()
|
||||
* DESCRIPTION: store catalog information
|
||||
*/
|
||||
int v_putcatrec(CatDataRec *data, node *np)
|
||||
{
|
||||
unsigned char pdata[HFS_CATDATALEN], *ptr;
|
||||
int len = 0;
|
||||
|
||||
r_packcatdata(data, pdata, &len);
|
||||
|
||||
ptr = HFS_NODEREC(*np, np->rnum);
|
||||
memcpy(HFS_RECDATA(ptr), pdata, len);
|
||||
|
||||
return bt_putnode(np);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->putextrec()
|
||||
* DESCRIPTION: store extent information
|
||||
*/
|
||||
int v_putextrec(ExtDataRec *data, node *np)
|
||||
{
|
||||
unsigned char pdata[HFS_EXTDATALEN], *ptr;
|
||||
int len = 0;
|
||||
|
||||
r_packextdata(data, pdata, &len);
|
||||
|
||||
ptr = HFS_NODEREC(*np, np->rnum);
|
||||
memcpy(HFS_RECDATA(ptr), pdata, len);
|
||||
|
||||
return bt_putnode(np);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->allocblocks()
|
||||
* DESCRIPTION: allocate a contiguous range of blocks
|
||||
*/
|
||||
int v_allocblocks(hfsvol *vol, ExtDescriptor *blocks)
|
||||
{
|
||||
unsigned int request, found, foundat, start, end, pt;
|
||||
block *vbm;
|
||||
int wrap = 0;
|
||||
|
||||
if (vol->mdb.drFreeBks == 0)
|
||||
{
|
||||
ERROR(ENOSPC, "volume full");
|
||||
return -1;
|
||||
}
|
||||
|
||||
request = blocks->xdrNumABlks;
|
||||
found = 0;
|
||||
foundat = 0;
|
||||
start = vol->mdb.drAllocPtr;
|
||||
end = vol->mdb.drNmAlBlks;
|
||||
pt = start;
|
||||
vbm = vol->vbm;
|
||||
|
||||
if (request == 0)
|
||||
abort();
|
||||
|
||||
while (1)
|
||||
{
|
||||
unsigned int mark;
|
||||
|
||||
/* skip blocks in use */
|
||||
|
||||
while (pt < end && BMTST(vbm, pt))
|
||||
++pt;
|
||||
|
||||
if (wrap && pt >= start)
|
||||
break;
|
||||
|
||||
/* count blocks not in use */
|
||||
|
||||
mark = pt;
|
||||
while (pt < end && pt - mark < request && ! BMTST(vbm, pt))
|
||||
++pt;
|
||||
|
||||
if (pt - mark > found)
|
||||
{
|
||||
found = pt - mark;
|
||||
foundat = mark;
|
||||
}
|
||||
|
||||
if (pt == end)
|
||||
pt = 0, wrap = 1;
|
||||
|
||||
if (found == request)
|
||||
break;
|
||||
}
|
||||
|
||||
if (found == 0 || found > vol->mdb.drFreeBks)
|
||||
{
|
||||
ERROR(EIO, "bad volume bitmap or free block count");
|
||||
return -1;
|
||||
}
|
||||
|
||||
blocks->xdrStABN = foundat;
|
||||
blocks->xdrNumABlks = found;
|
||||
|
||||
vol->mdb.drAllocPtr = pt;
|
||||
vol->mdb.drFreeBks -= found;
|
||||
|
||||
for (pt = foundat; pt < foundat + found; ++pt)
|
||||
BMSET(vbm, pt);
|
||||
|
||||
vol->flags |= HFS_UPDATE_MDB | HFS_UPDATE_VBM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->freeblocks()
|
||||
* DESCRIPTION: deallocate a contiguous range of blocks
|
||||
*/
|
||||
void v_freeblocks(hfsvol *vol, ExtDescriptor *blocks)
|
||||
{
|
||||
unsigned int start, len, pt;
|
||||
block *vbm;
|
||||
|
||||
start = blocks->xdrStABN;
|
||||
len = blocks->xdrNumABlks;
|
||||
vbm = vol->vbm;
|
||||
|
||||
vol->mdb.drFreeBks += len;
|
||||
|
||||
for (pt = start; pt < start + len; ++pt)
|
||||
BMCLR(vbm, pt);
|
||||
|
||||
vol->flags |= HFS_UPDATE_MDB | HFS_UPDATE_VBM;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->resolve()
|
||||
* DESCRIPTION: translate a pathname; return catalog information
|
||||
*/
|
||||
int v_resolve(hfsvol **vol, char *path, CatDataRec *data,
|
||||
long *parid, char *fname, node *np)
|
||||
{
|
||||
long dirid;
|
||||
char name[HFS_MAX_FLEN + 1], *nptr;
|
||||
int found;
|
||||
|
||||
if (*path == 0)
|
||||
{
|
||||
ERROR(ENOENT, "empty path");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (parid)
|
||||
*parid = 0;
|
||||
|
||||
nptr = strchr(path, ':');
|
||||
|
||||
if (*path == ':' || nptr == 0)
|
||||
{
|
||||
dirid = (*vol)->cwd; /* relative path */
|
||||
|
||||
if (*path == ':')
|
||||
++path;
|
||||
|
||||
if (*path == 0)
|
||||
{
|
||||
found = v_getdthread(*vol, dirid, data, 0);
|
||||
if (found <= 0)
|
||||
return found;
|
||||
|
||||
if (parid)
|
||||
*parid = data->u.dthd.thdParID;
|
||||
|
||||
return v_catsearch(*vol, data->u.dthd.thdParID,
|
||||
data->u.dthd.thdCName, data, fname, np);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hfsvol *check;
|
||||
|
||||
dirid = HFS_CNID_ROOTPAR; /* absolute path */
|
||||
|
||||
if (nptr - path > HFS_MAX_VLEN)
|
||||
{
|
||||
ERROR(ENAMETOOLONG, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(name, path, nptr - path);
|
||||
name[nptr - path] = 0;
|
||||
|
||||
for (check = hfs_mounts; check; check = check->next)
|
||||
{
|
||||
if (d_relstring(check->mdb.drVN, name) == 0)
|
||||
{
|
||||
*vol = check;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
while (*path == ':')
|
||||
{
|
||||
++path;
|
||||
|
||||
found = v_getdthread(*vol, dirid, data, 0);
|
||||
if (found <= 0)
|
||||
return found;
|
||||
|
||||
dirid = data->u.dthd.thdParID;
|
||||
}
|
||||
|
||||
if (*path == 0)
|
||||
{
|
||||
found = v_getdthread(*vol, dirid, data, 0);
|
||||
if (found <= 0)
|
||||
return found;
|
||||
|
||||
if (parid)
|
||||
*parid = data->u.dthd.thdParID;
|
||||
|
||||
return v_catsearch(*vol, data->u.dthd.thdParID,
|
||||
data->u.dthd.thdCName, data, fname, np);
|
||||
}
|
||||
|
||||
nptr = name;
|
||||
while (nptr < name + sizeof(name) - 1 && *path && *path != ':')
|
||||
*nptr++ = *path++;
|
||||
|
||||
if (*path && *path != ':')
|
||||
{
|
||||
ERROR(ENAMETOOLONG, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*nptr = 0;
|
||||
if (*path == ':')
|
||||
++path;
|
||||
|
||||
if (parid)
|
||||
*parid = dirid;
|
||||
|
||||
found = v_catsearch(*vol, dirid, name, data, fname, np);
|
||||
if (found < 0)
|
||||
return -1;
|
||||
|
||||
if (found == 0)
|
||||
{
|
||||
if (*path && parid)
|
||||
*parid = 0;
|
||||
|
||||
if (*path == 0 && fname)
|
||||
strcpy(fname, name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (data->cdrType)
|
||||
{
|
||||
case cdrDirRec:
|
||||
if (*path == 0)
|
||||
return 1;
|
||||
|
||||
dirid = data->u.dir.dirDirID;
|
||||
break;
|
||||
|
||||
case cdrFilRec:
|
||||
if (*path == 0)
|
||||
return 1;
|
||||
|
||||
ERROR(ENOTDIR, "invalid pathname");
|
||||
return -1;
|
||||
|
||||
default:
|
||||
ERROR(EIO, "unexpected catalog record");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->destruct()
|
||||
* DESCRIPTION: free memory consumed by a volume descriptor
|
||||
*/
|
||||
void v_destruct(hfsvol *vol)
|
||||
{
|
||||
FREE(vol->vbm);
|
||||
|
||||
FREE(vol->ext.map);
|
||||
FREE(vol->cat.map);
|
||||
|
||||
FREE(vol);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->getvol()
|
||||
* DESCRIPTION: validate a volume reference
|
||||
*/
|
||||
int v_getvol(hfsvol **vol)
|
||||
{
|
||||
if (*vol == 0)
|
||||
{
|
||||
if (hfs_curvol == 0)
|
||||
{
|
||||
ERROR(EINVAL, "no volume is current");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*vol = hfs_curvol;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->flush()
|
||||
* DESCRIPTION: flush all pending changes (B*-tree, MDB, VBM) to disk
|
||||
*/
|
||||
int v_flush(hfsvol *vol, int umounting)
|
||||
{
|
||||
if (! (vol->flags & HFS_READONLY))
|
||||
{
|
||||
if ((vol->ext.flags & HFS_UPDATE_BTHDR) &&
|
||||
bt_writehdr(&vol->ext) < 0)
|
||||
return -1;
|
||||
|
||||
if ((vol->cat.flags & HFS_UPDATE_BTHDR) &&
|
||||
bt_writehdr(&vol->cat) < 0)
|
||||
return -1;
|
||||
|
||||
if ((vol->flags & HFS_UPDATE_VBM) &&
|
||||
l_writevbm(vol) < 0)
|
||||
return -1;
|
||||
|
||||
if (umounting &&
|
||||
! (vol->mdb.drAtrb & HFS_ATRB_UMOUNTED))
|
||||
{
|
||||
vol->mdb.drAtrb |= HFS_ATRB_UMOUNTED;
|
||||
vol->flags |= HFS_UPDATE_MDB;
|
||||
}
|
||||
|
||||
if ((vol->flags & (HFS_UPDATE_MDB | HFS_UPDATE_ALTMDB)) &&
|
||||
l_writemdb(vol) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->adjvalence()
|
||||
* DESCRIPTION: update a volume's valence counts
|
||||
*/
|
||||
int v_adjvalence(hfsvol *vol, long parid, int isdir, int adj)
|
||||
{
|
||||
node n;
|
||||
CatDataRec data;
|
||||
|
||||
if (isdir)
|
||||
vol->mdb.drDirCnt += adj;
|
||||
else
|
||||
vol->mdb.drFilCnt += adj;
|
||||
|
||||
vol->flags |= HFS_UPDATE_MDB;
|
||||
|
||||
if (parid == HFS_CNID_ROOTDIR)
|
||||
{
|
||||
if (isdir)
|
||||
vol->mdb.drNmRtDirs += adj;
|
||||
else
|
||||
vol->mdb.drNmFls += adj;
|
||||
}
|
||||
else if (parid == HFS_CNID_ROOTPAR)
|
||||
return 0;
|
||||
|
||||
if (v_getdthread(vol, parid, &data, 0) <= 0 ||
|
||||
v_catsearch(vol, data.u.dthd.thdParID, data.u.dthd.thdCName,
|
||||
&data, 0, &n) <= 0 ||
|
||||
data.cdrType != cdrDirRec)
|
||||
{
|
||||
ERROR(EIO, "can't find parent directory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
data.u.dir.dirVal += adj;
|
||||
data.u.dir.dirMdDat = d_tomtime(time(0));
|
||||
|
||||
return v_putcatrec(&data, &n);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->newfolder()
|
||||
* DESCRIPTION: create a new HFS folder
|
||||
*/
|
||||
int v_newfolder(hfsvol *vol, long parid, char *name)
|
||||
{
|
||||
CatKeyRec key;
|
||||
CatDataRec data;
|
||||
long id;
|
||||
unsigned char record[HFS_CATRECMAXLEN];
|
||||
int i, reclen;
|
||||
|
||||
if (bt_space(&vol->cat, 2) < 0)
|
||||
return -1;
|
||||
|
||||
id = vol->mdb.drNxtCNID++;
|
||||
vol->flags |= HFS_UPDATE_MDB;
|
||||
|
||||
/* create directory record */
|
||||
|
||||
data.cdrType = cdrDirRec;
|
||||
data.cdrResrv2 = 0;
|
||||
|
||||
data.u.dir.dirFlags = 0;
|
||||
data.u.dir.dirVal = 0;
|
||||
data.u.dir.dirDirID = id;
|
||||
data.u.dir.dirCrDat = d_tomtime(time(0));
|
||||
data.u.dir.dirMdDat = data.u.dir.dirCrDat;
|
||||
data.u.dir.dirBkDat = 0;
|
||||
|
||||
memset(&data.u.dir.dirUsrInfo, 0, sizeof(data.u.dir.dirUsrInfo));
|
||||
memset(&data.u.dir.dirFndrInfo, 0, sizeof(data.u.dir.dirFndrInfo));
|
||||
for (i = 0; i < 4; ++i)
|
||||
data.u.dir.dirResrv[i] = 0;
|
||||
|
||||
r_makecatkey(&key, parid, name);
|
||||
r_packcatkey(&key, record, &reclen);
|
||||
r_packcatdata(&data, HFS_RECDATA(record), &reclen);
|
||||
|
||||
if (bt_insert(&vol->cat, record, reclen) < 0)
|
||||
return -1;
|
||||
|
||||
/* create thread record */
|
||||
|
||||
data.cdrType = cdrThdRec;
|
||||
data.cdrResrv2 = 0;
|
||||
|
||||
data.u.dthd.thdResrv[0] = 0;
|
||||
data.u.dthd.thdResrv[1] = 0;
|
||||
data.u.dthd.thdParID = parid;
|
||||
strcpy(data.u.dthd.thdCName, name);
|
||||
|
||||
r_makecatkey(&key, id, "");
|
||||
r_packcatkey(&key, record, &reclen);
|
||||
r_packcatdata(&data, HFS_RECDATA(record), &reclen);
|
||||
|
||||
if (bt_insert(&vol->cat, record, reclen) < 0 ||
|
||||
v_adjvalence(vol, parid, 1, 1) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: markexts()
|
||||
* DESCRIPTION: set bits from an extent record in the volume bitmap
|
||||
*/
|
||||
static
|
||||
void markexts(block *vbm, ExtDataRec *exts)
|
||||
{
|
||||
int i;
|
||||
unsigned int start, len;
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
for (start = (*exts)[i].xdrStABN,
|
||||
len = (*exts)[i].xdrNumABlks; len--; ++start)
|
||||
BMSET(vbm, start);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: vol->scavenge()
|
||||
* DESCRIPTION: safeguard blocks in the volume bitmap
|
||||
*/
|
||||
int v_scavenge(hfsvol *vol)
|
||||
{
|
||||
block *vbm = vol->vbm;
|
||||
node n;
|
||||
unsigned int pt, blks;
|
||||
|
||||
if (vbm == 0)
|
||||
return 0;
|
||||
|
||||
markexts(vbm, &vol->mdb.drXTExtRec);
|
||||
markexts(vbm, &vol->mdb.drCTExtRec);
|
||||
|
||||
vol->flags |= HFS_UPDATE_VBM;
|
||||
|
||||
/* scavenge the extents overflow file */
|
||||
|
||||
n.bt = &vol->ext;
|
||||
n.nnum = vol->ext.hdr.bthFNode;
|
||||
|
||||
if (n.nnum > 0)
|
||||
{
|
||||
if (bt_getnode(&n) < 0)
|
||||
return -1;
|
||||
|
||||
n.rnum = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
ExtDataRec data;
|
||||
unsigned char *ptr;
|
||||
|
||||
while (n.rnum >= n.nd.ndNRecs)
|
||||
{
|
||||
n.nnum = n.nd.ndFLink;
|
||||
if (n.nnum == 0)
|
||||
break;
|
||||
|
||||
if (bt_getnode(&n) < 0)
|
||||
return -1;
|
||||
|
||||
n.rnum = 0;
|
||||
}
|
||||
|
||||
if (n.nnum == 0)
|
||||
break;
|
||||
|
||||
ptr = HFS_NODEREC(n, n.rnum);
|
||||
r_unpackextdata(HFS_RECDATA(ptr), &data);
|
||||
|
||||
markexts(vbm, &data);
|
||||
|
||||
++n.rnum;
|
||||
}
|
||||
}
|
||||
|
||||
/* scavenge the catalog file */
|
||||
|
||||
n.bt = &vol->cat;
|
||||
n.nnum = vol->cat.hdr.bthFNode;
|
||||
|
||||
if (n.nnum > 0)
|
||||
{
|
||||
if (bt_getnode(&n) < 0)
|
||||
return -1;
|
||||
|
||||
n.rnum = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
CatDataRec data;
|
||||
unsigned char *ptr;
|
||||
|
||||
while (n.rnum >= n.nd.ndNRecs)
|
||||
{
|
||||
n.nnum = n.nd.ndFLink;
|
||||
if (n.nnum == 0)
|
||||
break;
|
||||
|
||||
if (bt_getnode(&n) < 0)
|
||||
return -1;
|
||||
|
||||
n.rnum = 0;
|
||||
}
|
||||
|
||||
if (n.nnum == 0)
|
||||
break;
|
||||
|
||||
ptr = HFS_NODEREC(n, n.rnum);
|
||||
r_unpackcatdata(HFS_RECDATA(ptr), &data);
|
||||
|
||||
if (data.cdrType == cdrFilRec)
|
||||
{
|
||||
markexts(vbm, &data.u.fil.filExtRec);
|
||||
markexts(vbm, &data.u.fil.filRExtRec);
|
||||
}
|
||||
|
||||
++n.rnum;
|
||||
}
|
||||
}
|
||||
|
||||
for (blks = 0, pt = vol->mdb.drNmAlBlks; pt--; )
|
||||
{
|
||||
if (! BMTST(vbm, pt))
|
||||
++blks;
|
||||
}
|
||||
|
||||
if (vol->mdb.drFreeBks != blks)
|
||||
{
|
||||
vol->mdb.drFreeBks = blks;
|
||||
vol->flags |= HFS_UPDATE_MDB;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,459 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <errno.h>
|
||||
|
||||
# include "internal.h"
|
||||
# include "data.h"
|
||||
# include "btree.h"
|
||||
# include "node.h"
|
||||
|
||||
# define NODESPACE(n) \
|
||||
(HFS_BLOCKSZ - (n).roff[(n).nd.ndNRecs] - 2 * ((n).nd.ndNRecs + 1))
|
||||
|
||||
/*
|
||||
* NAME: node->init()
|
||||
* DESCRIPTION: construct an empty node
|
||||
*/
|
||||
void n_init(node *np, btree *bt, int type, int height)
|
||||
{
|
||||
np->bt = bt;
|
||||
np->nnum = -1;
|
||||
|
||||
np->nd.ndFLink = 0;
|
||||
np->nd.ndBLink = 0;
|
||||
np->nd.ndType = type;
|
||||
np->nd.ndNHeight = height;
|
||||
np->nd.ndNRecs = 0;
|
||||
np->nd.ndResv2 = 0;
|
||||
|
||||
np->rnum = -1;
|
||||
np->roff[0] = 0x00e;
|
||||
|
||||
memset(np->data, 0, sizeof(np->data));
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: node->new()
|
||||
* DESCRIPTION: allocate a new b*-tree node
|
||||
*/
|
||||
int n_new(node *np)
|
||||
{
|
||||
btree *bt = np->bt;
|
||||
unsigned long num;
|
||||
|
||||
if (bt->hdr.bthFree == 0)
|
||||
{
|
||||
ERROR(EIO, "b*-tree full");
|
||||
return -1;
|
||||
}
|
||||
|
||||
num = 0;
|
||||
while (num < bt->hdr.bthNNodes && BMTST(bt->map, num))
|
||||
++num;
|
||||
|
||||
if (num == bt->hdr.bthNNodes)
|
||||
{
|
||||
ERROR(EIO, "free b*-tree node not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
np->nnum = num;
|
||||
|
||||
BMSET(bt->map, num);
|
||||
--bt->hdr.bthFree;
|
||||
|
||||
bt->flags |= HFS_UPDATE_BTHDR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: node->free()
|
||||
* DESCRIPTION: deallocate a b*-tree node
|
||||
*/
|
||||
void n_free(node *np)
|
||||
{
|
||||
btree *bt = np->bt;
|
||||
|
||||
BMCLR(bt->map, np->nnum);
|
||||
++bt->hdr.bthFree;
|
||||
|
||||
bt->flags |= HFS_UPDATE_BTHDR;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: node->compact()
|
||||
* DESCRIPTION: clean up a node, removing deleted records
|
||||
*/
|
||||
void n_compact(node *np)
|
||||
{
|
||||
unsigned char *ptr;
|
||||
int offset, nrecs, i;
|
||||
|
||||
offset = 0x00e;
|
||||
ptr = np->data + offset;
|
||||
nrecs = 0;
|
||||
|
||||
for (i = 0; i < np->nd.ndNRecs; ++i)
|
||||
{
|
||||
unsigned char *rec;
|
||||
int reclen;
|
||||
|
||||
rec = HFS_NODEREC(*np, i);
|
||||
reclen = np->roff[i + 1] - np->roff[i];
|
||||
|
||||
if (HFS_RECKEYLEN(rec) > 0)
|
||||
{
|
||||
np->roff[nrecs++] = offset;
|
||||
offset += reclen;
|
||||
|
||||
if (ptr == rec)
|
||||
ptr += reclen;
|
||||
else
|
||||
{
|
||||
while (reclen--)
|
||||
*ptr++ = *rec++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
np->roff[nrecs] = offset;
|
||||
np->nd.ndNRecs = nrecs;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: node->search()
|
||||
* DESCRIPTION: locate a record in a node, or the record it should follow
|
||||
*/
|
||||
int n_search(node *np, unsigned char *key)
|
||||
{
|
||||
btree *bt = np->bt;
|
||||
int i, comp = -1;
|
||||
|
||||
for (i = np->nd.ndNRecs; i--; )
|
||||
{
|
||||
unsigned char *rec;
|
||||
|
||||
rec = HFS_NODEREC(*np, i);
|
||||
|
||||
if (HFS_RECKEYLEN(rec) == 0)
|
||||
continue; /* deleted record */
|
||||
|
||||
comp = bt->compare(rec, key);
|
||||
|
||||
if (comp <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
np->rnum = i;
|
||||
|
||||
return comp == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: node->index()
|
||||
* DESCRIPTION: create an index record from a key and node pointer
|
||||
*/
|
||||
void n_index(btree *bt, unsigned char *key, unsigned long nnum,
|
||||
unsigned char *record, int *reclen)
|
||||
{
|
||||
if (bt == &bt->f.vol->cat)
|
||||
{
|
||||
/* force the key length to be 0x25 */
|
||||
|
||||
HFS_RECKEYLEN(record) = 0x25;
|
||||
memset(record + 1, 0, 0x25);
|
||||
memcpy(record + 1, key + 1, HFS_RECKEYLEN(key));
|
||||
}
|
||||
else
|
||||
memcpy(record, key, HFS_RECKEYSKIP(key));
|
||||
|
||||
d_putl(HFS_RECDATA(record), nnum);
|
||||
|
||||
if (reclen)
|
||||
*reclen = HFS_RECKEYSKIP(record) + 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: node->split()
|
||||
* DESCRIPTION: divide a node into two and insert a record
|
||||
*/
|
||||
int n_split(node *left, unsigned char *record, int *reclen)
|
||||
{
|
||||
node right;
|
||||
int nrecs, i, mid;
|
||||
unsigned char *rec;
|
||||
|
||||
right = *left;
|
||||
right.nd.ndBLink = left->nnum;
|
||||
|
||||
if (n_new(&right) < 0)
|
||||
return -1;
|
||||
|
||||
left->nd.ndFLink = right.nnum;
|
||||
nrecs = left->nd.ndNRecs;
|
||||
|
||||
/*
|
||||
* Ensure node split leaves enough room for new record.
|
||||
* The size calculations used are based on the NODESPACE() macro, but
|
||||
* I don't know what the extra 2's and 1's are needed for.
|
||||
* John Witford <jwitford@hutch.com.au>
|
||||
*/
|
||||
n_search(&right, record);
|
||||
mid = nrecs/2;
|
||||
for(;;)
|
||||
{
|
||||
if (right.rnum < mid)
|
||||
{
|
||||
if ( mid > 0
|
||||
&& left->roff[mid] + *reclen + 2 > HFS_BLOCKSZ - 2 * (mid + 1))
|
||||
{
|
||||
--mid;
|
||||
if (mid > 0)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mid < nrecs
|
||||
&& right.roff[nrecs] - right.roff[mid] + left->roff[0] + *reclen + 2 > HFS_BLOCKSZ - 2 * (mid + 1))
|
||||
{
|
||||
++mid;
|
||||
if (mid < nrecs)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < nrecs; ++i)
|
||||
{
|
||||
if (i < mid)
|
||||
rec = HFS_NODEREC(right, i);
|
||||
else
|
||||
rec = HFS_NODEREC(*left, i);
|
||||
|
||||
HFS_RECKEYLEN(rec) = 0;
|
||||
}
|
||||
|
||||
/* original code ...
|
||||
for (i = 0; i < nrecs; ++i)
|
||||
{
|
||||
if (i < nrecs / 2)
|
||||
rec = HFS_NODEREC(right, i);
|
||||
else
|
||||
rec = HFS_NODEREC(*left, i);
|
||||
|
||||
HFS_RECKEYLEN(rec) = 0;
|
||||
}
|
||||
*/
|
||||
n_compact(left);
|
||||
n_compact(&right);
|
||||
|
||||
n_search(&right, record);
|
||||
if (right.rnum >= 0)
|
||||
n_insertx(&right, record, *reclen);
|
||||
else
|
||||
{
|
||||
n_search(left, record);
|
||||
n_insertx(left, record, *reclen);
|
||||
}
|
||||
|
||||
/* store the new/modified nodes */
|
||||
|
||||
if (bt_putnode(left) < 0 ||
|
||||
bt_putnode(&right) < 0)
|
||||
return -1;
|
||||
|
||||
/* create an index record for the new node in the parent */
|
||||
|
||||
n_index(right.bt, HFS_NODEREC(right, 0), right.nnum, record, reclen);
|
||||
|
||||
/* update link pointers */
|
||||
|
||||
if (left->bt->hdr.bthLNode == left->nnum)
|
||||
{
|
||||
left->bt->hdr.bthLNode = right.nnum;
|
||||
left->bt->flags |= HFS_UPDATE_BTHDR;
|
||||
}
|
||||
|
||||
if (right.nd.ndFLink)
|
||||
{
|
||||
node n;
|
||||
|
||||
n.bt = right.bt;
|
||||
n.nnum = right.nd.ndFLink;
|
||||
|
||||
if (bt_getnode(&n) < 0)
|
||||
return -1;
|
||||
|
||||
n.nd.ndBLink = right.nnum;
|
||||
|
||||
if (bt_putnode(&n) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: node->insertx()
|
||||
* DESCRIPTION: insert a record into a node (which must already have room)
|
||||
*/
|
||||
void n_insertx(node *np, unsigned char *record, int reclen)
|
||||
{
|
||||
int rnum, i;
|
||||
unsigned char *ptr;
|
||||
|
||||
rnum = np->rnum + 1;
|
||||
|
||||
/* push other records down to make room */
|
||||
|
||||
for (ptr = HFS_NODEREC(*np, np->nd.ndNRecs) + reclen;
|
||||
ptr > HFS_NODEREC(*np, rnum) + reclen; --ptr)
|
||||
*(ptr - 1) = *(ptr - 1 - reclen);
|
||||
|
||||
++np->nd.ndNRecs;
|
||||
|
||||
for (i = np->nd.ndNRecs; i > rnum; --i)
|
||||
np->roff[i] = np->roff[i - 1] + reclen;
|
||||
|
||||
/* write the new record */
|
||||
|
||||
memcpy(HFS_NODEREC(*np, rnum), record, reclen);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: node->insert()
|
||||
* DESCRIPTION: insert a new record into a node; return a record for parent
|
||||
*/
|
||||
int n_insert(node *np, unsigned char *record, int *reclen)
|
||||
{
|
||||
n_compact(np);
|
||||
|
||||
/* check for free space */
|
||||
|
||||
if (np->nd.ndNRecs >= HFS_MAXRECS ||
|
||||
*reclen + 2 > NODESPACE(*np))
|
||||
return n_split(np, record, reclen);
|
||||
|
||||
n_insertx(np, record, *reclen);
|
||||
*reclen = 0;
|
||||
|
||||
return bt_putnode(np);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: node->merge()
|
||||
* DESCRIPTION: combine two nodes into a single node
|
||||
*/
|
||||
int n_merge(node *right, node *left, unsigned char *record, int *flag)
|
||||
{
|
||||
int i, offset;
|
||||
|
||||
/* copy records and offsets */
|
||||
|
||||
memcpy(HFS_NODEREC(*left, left->nd.ndNRecs), HFS_NODEREC(*right, 0),
|
||||
right->roff[right->nd.ndNRecs] - right->roff[0]);
|
||||
|
||||
offset = left->roff[left->nd.ndNRecs] - right->roff[0];
|
||||
|
||||
for (i = 1; i <= right->nd.ndNRecs; ++i)
|
||||
left->roff[++left->nd.ndNRecs] = offset + right->roff[i];
|
||||
|
||||
/* update link pointers */
|
||||
|
||||
left->nd.ndFLink = right->nd.ndFLink;
|
||||
|
||||
if (bt_putnode(left) < 0)
|
||||
return -1;
|
||||
|
||||
if (right->bt->hdr.bthLNode == right->nnum)
|
||||
{
|
||||
right->bt->hdr.bthLNode = left->nnum;
|
||||
right->bt->flags |= HFS_UPDATE_BTHDR;
|
||||
}
|
||||
|
||||
if (right->nd.ndFLink)
|
||||
{
|
||||
node n;
|
||||
|
||||
n.bt = right->bt;
|
||||
n.nnum = right->nd.ndFLink;
|
||||
|
||||
if (bt_getnode(&n) < 0)
|
||||
return -1;
|
||||
|
||||
n.nd.ndBLink = left->nnum;
|
||||
|
||||
if (bt_putnode(&n) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
n_free(right);
|
||||
|
||||
HFS_RECKEYLEN(record) = 0;
|
||||
*flag = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: node->delete()
|
||||
* DESCRIPTION: remove a record from a node
|
||||
*/
|
||||
int n_delete(node *np, unsigned char *record, int *flag)
|
||||
{
|
||||
node left;
|
||||
unsigned char *rec;
|
||||
|
||||
rec = HFS_NODEREC(*np, np->rnum);
|
||||
|
||||
HFS_RECKEYLEN(rec) = 0;
|
||||
n_compact(np);
|
||||
|
||||
/* see if we can merge with our left sibling */
|
||||
|
||||
left.bt = np->bt;
|
||||
left.nnum = np->nd.ndBLink;
|
||||
|
||||
if (left.nnum > 0)
|
||||
{
|
||||
if (bt_getnode(&left) < 0)
|
||||
return -1;
|
||||
|
||||
if (np->nd.ndNRecs + left.nd.ndNRecs <= HFS_MAXRECS &&
|
||||
np->roff[np->nd.ndNRecs] - np->roff[0] +
|
||||
2 * np->nd.ndNRecs <= NODESPACE(left))
|
||||
return n_merge(np, &left, record, flag);
|
||||
}
|
||||
|
||||
if (np->rnum == 0)
|
||||
{
|
||||
/* special case: first record changed; update parent record key */
|
||||
|
||||
n_index(np->bt, HFS_NODEREC(*np, 0), np->nnum, record, 0);
|
||||
*flag = 1;
|
||||
}
|
||||
|
||||
return bt_putnode(np);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
void n_init(node *, btree *, int, int);
|
||||
|
||||
int n_new(node *);
|
||||
void n_free(node *);
|
||||
|
||||
void n_compact(node *);
|
||||
int n_search(node *, unsigned char *);
|
||||
|
||||
void n_index(btree *, unsigned char *, unsigned long, unsigned char *, int *);
|
||||
int n_split(node *, unsigned char *, int *);
|
||||
|
||||
void n_insertx(node *, unsigned char *, int);
|
||||
int n_insert(node *, unsigned char *, int *);
|
||||
|
||||
int n_merge(node *, node *, unsigned char *, int *);
|
||||
int n_delete(node *, unsigned char *, int *);
|
|
@ -0,0 +1,492 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
# include <string.h>
|
||||
# include <errno.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
# include "internal.h"
|
||||
# include "data.h"
|
||||
# include "record.h"
|
||||
|
||||
/*
|
||||
* NAME: record->packcatkey()
|
||||
* DESCRIPTION: pack a catalog record key
|
||||
*/
|
||||
void r_packcatkey(CatKeyRec *key, unsigned char *pkey, int *len)
|
||||
{
|
||||
unsigned char *start = pkey;
|
||||
|
||||
d_storeb(&pkey, key->ckrKeyLen);
|
||||
d_storeb(&pkey, key->ckrResrv1);
|
||||
d_storel(&pkey, key->ckrParID);
|
||||
d_stores(&pkey, key->ckrCName, sizeof(key->ckrCName));
|
||||
|
||||
if (len)
|
||||
*len = HFS_RECKEYSKIP(start);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->unpackcatkey()
|
||||
* DESCRIPTION: unpack a catalog record key
|
||||
*/
|
||||
void r_unpackcatkey(unsigned char *pkey, CatKeyRec *key)
|
||||
{
|
||||
d_fetchb(&pkey, (char *) &key->ckrKeyLen);
|
||||
d_fetchb(&pkey, (char *) &key->ckrResrv1);
|
||||
d_fetchl(&pkey, (long *) &key->ckrParID);
|
||||
d_fetchs(&pkey, key->ckrCName, sizeof(key->ckrCName));
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->packextkey()
|
||||
* DESCRIPTION: pack an extents record key
|
||||
*/
|
||||
void r_packextkey(ExtKeyRec *key, unsigned char *pkey, int *len)
|
||||
{
|
||||
unsigned char *start = pkey;
|
||||
|
||||
d_storeb(&pkey, key->xkrKeyLen);
|
||||
d_storeb(&pkey, key->xkrFkType);
|
||||
d_storel(&pkey, key->xkrFNum);
|
||||
d_storew(&pkey, key->xkrFABN);
|
||||
|
||||
if (len)
|
||||
*len = HFS_RECKEYSKIP(start);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->unpackextkey()
|
||||
* DESCRIPTION: unpack an extents record key
|
||||
*/
|
||||
void r_unpackextkey(unsigned char *pkey, ExtKeyRec *key)
|
||||
{
|
||||
d_fetchb(&pkey, (char *) &key->xkrKeyLen);
|
||||
d_fetchb(&pkey, (char *) &key->xkrFkType);
|
||||
d_fetchl(&pkey, (long *) &key->xkrFNum);
|
||||
d_fetchw(&pkey, (short *) &key->xkrFABN);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->comparecatkeys()
|
||||
* DESCRIPTION: compare two (packed) catalog record keys
|
||||
*/
|
||||
int r_comparecatkeys(unsigned char *pkey1, unsigned char *pkey2)
|
||||
{
|
||||
CatKeyRec key1;
|
||||
CatKeyRec key2;
|
||||
int diff;
|
||||
|
||||
r_unpackcatkey(pkey1, &key1);
|
||||
r_unpackcatkey(pkey2, &key2);
|
||||
|
||||
diff = key1.ckrParID - key2.ckrParID;
|
||||
if (diff)
|
||||
return diff;
|
||||
|
||||
return d_relstring(key1.ckrCName, key2.ckrCName);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->compareextkeys()
|
||||
* DESCRIPTION: compare two (packed) extents record keys
|
||||
*/
|
||||
int r_compareextkeys(unsigned char *pkey1, unsigned char *pkey2)
|
||||
{
|
||||
ExtKeyRec key1;
|
||||
ExtKeyRec key2;
|
||||
int diff;
|
||||
|
||||
r_unpackextkey(pkey1, &key1);
|
||||
r_unpackextkey(pkey2, &key2);
|
||||
|
||||
diff = key1.xkrFNum - key2.xkrFNum;
|
||||
if (diff)
|
||||
return diff;
|
||||
|
||||
diff = (unsigned char) key1.xkrFkType -
|
||||
(unsigned char) key2.xkrFkType;
|
||||
if (diff)
|
||||
return diff;
|
||||
|
||||
return key1.xkrFABN - key2.xkrFABN;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->packcatdata()
|
||||
* DESCRIPTION: pack catalog record data
|
||||
*/
|
||||
void r_packcatdata(CatDataRec *data, unsigned char *pdata, int *len)
|
||||
{
|
||||
unsigned char *start = pdata;
|
||||
int i;
|
||||
|
||||
d_storeb(&pdata, data->cdrType);
|
||||
d_storeb(&pdata, data->cdrResrv2);
|
||||
|
||||
switch (data->cdrType)
|
||||
{
|
||||
case cdrDirRec:
|
||||
d_storew(&pdata, data->u.dir.dirFlags);
|
||||
d_storew(&pdata, data->u.dir.dirVal);
|
||||
d_storel(&pdata, data->u.dir.dirDirID);
|
||||
d_storel(&pdata, data->u.dir.dirCrDat);
|
||||
d_storel(&pdata, data->u.dir.dirMdDat);
|
||||
d_storel(&pdata, data->u.dir.dirBkDat);
|
||||
|
||||
d_storew(&pdata, data->u.dir.dirUsrInfo.frRect.top);
|
||||
d_storew(&pdata, data->u.dir.dirUsrInfo.frRect.left);
|
||||
d_storew(&pdata, data->u.dir.dirUsrInfo.frRect.bottom);
|
||||
d_storew(&pdata, data->u.dir.dirUsrInfo.frRect.right);
|
||||
d_storew(&pdata, data->u.dir.dirUsrInfo.frFlags);
|
||||
d_storew(&pdata, data->u.dir.dirUsrInfo.frLocation.v);
|
||||
d_storew(&pdata, data->u.dir.dirUsrInfo.frLocation.h);
|
||||
d_storew(&pdata, data->u.dir.dirUsrInfo.frView);
|
||||
|
||||
d_storew(&pdata, data->u.dir.dirFndrInfo.frScroll.v);
|
||||
d_storew(&pdata, data->u.dir.dirFndrInfo.frScroll.h);
|
||||
d_storel(&pdata, data->u.dir.dirFndrInfo.frOpenChain);
|
||||
d_storew(&pdata, data->u.dir.dirFndrInfo.frUnused);
|
||||
d_storew(&pdata, data->u.dir.dirFndrInfo.frComment);
|
||||
d_storel(&pdata, data->u.dir.dirFndrInfo.frPutAway);
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
d_storel(&pdata, data->u.dir.dirResrv[i]);
|
||||
|
||||
break;
|
||||
|
||||
case cdrFilRec:
|
||||
d_storeb(&pdata, data->u.fil.filFlags);
|
||||
d_storeb(&pdata, data->u.fil.filTyp);
|
||||
|
||||
d_storel(&pdata, data->u.fil.filUsrWds.fdType);
|
||||
d_storel(&pdata, data->u.fil.filUsrWds.fdCreator);
|
||||
d_storew(&pdata, data->u.fil.filUsrWds.fdFlags);
|
||||
d_storew(&pdata, data->u.fil.filUsrWds.fdLocation.v);
|
||||
d_storew(&pdata, data->u.fil.filUsrWds.fdLocation.h);
|
||||
d_storew(&pdata, data->u.fil.filUsrWds.fdFldr);
|
||||
|
||||
d_storel(&pdata, data->u.fil.filFlNum);
|
||||
|
||||
d_storew(&pdata, data->u.fil.filStBlk);
|
||||
d_storel(&pdata, data->u.fil.filLgLen);
|
||||
d_storel(&pdata, data->u.fil.filPyLen);
|
||||
|
||||
d_storew(&pdata, data->u.fil.filRStBlk);
|
||||
d_storel(&pdata, data->u.fil.filRLgLen);
|
||||
d_storel(&pdata, data->u.fil.filRPyLen);
|
||||
|
||||
d_storel(&pdata, data->u.fil.filCrDat);
|
||||
d_storel(&pdata, data->u.fil.filMdDat);
|
||||
d_storel(&pdata, data->u.fil.filBkDat);
|
||||
|
||||
d_storew(&pdata, data->u.fil.filFndrInfo.fdIconID);
|
||||
for (i = 0; i < 4; ++i)
|
||||
d_storew(&pdata, data->u.fil.filFndrInfo.fdUnused[i]);
|
||||
d_storew(&pdata, data->u.fil.filFndrInfo.fdComment);
|
||||
d_storel(&pdata, data->u.fil.filFndrInfo.fdPutAway);
|
||||
|
||||
d_storew(&pdata, data->u.fil.filClpSize);
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
d_storew(&pdata, data->u.fil.filExtRec[i].xdrStABN);
|
||||
d_storew(&pdata, data->u.fil.filExtRec[i].xdrNumABlks);
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
d_storew(&pdata, data->u.fil.filRExtRec[i].xdrStABN);
|
||||
d_storew(&pdata, data->u.fil.filRExtRec[i].xdrNumABlks);
|
||||
}
|
||||
|
||||
d_storel(&pdata, data->u.fil.filResrv);
|
||||
break;
|
||||
|
||||
case cdrThdRec:
|
||||
for (i = 0; i < 2; ++i)
|
||||
d_storel(&pdata, data->u.dthd.thdResrv[i]);
|
||||
|
||||
d_storel(&pdata, data->u.dthd.thdParID);
|
||||
d_stores(&pdata, data->u.dthd.thdCName, sizeof(data->u.dthd.thdCName));
|
||||
break;
|
||||
|
||||
case cdrFThdRec:
|
||||
for (i = 0; i < 2; ++i)
|
||||
d_storel(&pdata, data->u.fthd.fthdResrv[i]);
|
||||
|
||||
d_storel(&pdata, data->u.fthd.fthdParID);
|
||||
d_stores(&pdata, data->u.fthd.fthdCName, sizeof(data->u.fthd.fthdCName));
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
if (len)
|
||||
*len += pdata - start;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->unpackcatdata()
|
||||
* DESCRIPTION: unpack catalog record data
|
||||
*/
|
||||
void r_unpackcatdata(unsigned char *pdata, CatDataRec *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
d_fetchb(&pdata, (char *) &data->cdrType);
|
||||
d_fetchb(&pdata, (char *) &data->cdrResrv2);
|
||||
|
||||
switch (data->cdrType)
|
||||
{
|
||||
case cdrDirRec:
|
||||
d_fetchw(&pdata, &data->u.dir.dirFlags);
|
||||
d_fetchw(&pdata, (short *) &data->u.dir.dirVal);
|
||||
d_fetchl(&pdata, (long *) &data->u.dir.dirDirID);
|
||||
d_fetchl(&pdata, &data->u.dir.dirCrDat);
|
||||
d_fetchl(&pdata, &data->u.dir.dirMdDat);
|
||||
d_fetchl(&pdata, &data->u.dir.dirBkDat);
|
||||
|
||||
d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frRect.top);
|
||||
d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frRect.left);
|
||||
d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frRect.bottom);
|
||||
d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frRect.right);
|
||||
d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frFlags);
|
||||
d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frLocation.v);
|
||||
d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frLocation.h);
|
||||
d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frView);
|
||||
|
||||
d_fetchw(&pdata, &data->u.dir.dirFndrInfo.frScroll.v);
|
||||
d_fetchw(&pdata, &data->u.dir.dirFndrInfo.frScroll.h);
|
||||
d_fetchl(&pdata, &data->u.dir.dirFndrInfo.frOpenChain);
|
||||
d_fetchw(&pdata, &data->u.dir.dirFndrInfo.frUnused);
|
||||
d_fetchw(&pdata, &data->u.dir.dirFndrInfo.frComment);
|
||||
d_fetchl(&pdata, &data->u.dir.dirFndrInfo.frPutAway);
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
d_fetchl(&pdata, &data->u.dir.dirResrv[i]);
|
||||
|
||||
break;
|
||||
|
||||
case cdrFilRec:
|
||||
d_fetchb(&pdata, (char *) &data->u.fil.filFlags);
|
||||
d_fetchb(&pdata, (char *) &data->u.fil.filTyp);
|
||||
|
||||
d_fetchl(&pdata, &data->u.fil.filUsrWds.fdType);
|
||||
d_fetchl(&pdata, &data->u.fil.filUsrWds.fdCreator);
|
||||
d_fetchw(&pdata, &data->u.fil.filUsrWds.fdFlags);
|
||||
d_fetchw(&pdata, &data->u.fil.filUsrWds.fdLocation.v);
|
||||
d_fetchw(&pdata, &data->u.fil.filUsrWds.fdLocation.h);
|
||||
d_fetchw(&pdata, &data->u.fil.filUsrWds.fdFldr);
|
||||
|
||||
d_fetchl(&pdata, (long *) &data->u.fil.filFlNum);
|
||||
|
||||
d_fetchw(&pdata, (short *) &data->u.fil.filStBlk);
|
||||
d_fetchl(&pdata, (long *) &data->u.fil.filLgLen);
|
||||
d_fetchl(&pdata, (long *) &data->u.fil.filPyLen);
|
||||
|
||||
d_fetchw(&pdata, (short *) &data->u.fil.filRStBlk);
|
||||
d_fetchl(&pdata, (long *) &data->u.fil.filRLgLen);
|
||||
d_fetchl(&pdata, (long *) &data->u.fil.filRPyLen);
|
||||
|
||||
d_fetchl(&pdata, &data->u.fil.filCrDat);
|
||||
d_fetchl(&pdata, &data->u.fil.filMdDat);
|
||||
d_fetchl(&pdata, &data->u.fil.filBkDat);
|
||||
|
||||
d_fetchw(&pdata, &data->u.fil.filFndrInfo.fdIconID);
|
||||
for (i = 0; i < 4; ++i)
|
||||
d_fetchw(&pdata, &data->u.fil.filFndrInfo.fdUnused[i]);
|
||||
d_fetchw(&pdata, &data->u.fil.filFndrInfo.fdComment);
|
||||
d_fetchl(&pdata, &data->u.fil.filFndrInfo.fdPutAway);
|
||||
|
||||
d_fetchw(&pdata, (short *) &data->u.fil.filClpSize);
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
d_fetchw(&pdata, (short *) &data->u.fil.filExtRec[i].xdrStABN);
|
||||
d_fetchw(&pdata, (short *) &data->u.fil.filExtRec[i].xdrNumABlks);
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
d_fetchw(&pdata, (short *) &data->u.fil.filRExtRec[i].xdrStABN);
|
||||
d_fetchw(&pdata, (short *) &data->u.fil.filRExtRec[i].xdrNumABlks);
|
||||
}
|
||||
|
||||
d_fetchl(&pdata, &data->u.fil.filResrv);
|
||||
break;
|
||||
|
||||
case cdrThdRec:
|
||||
for (i = 0; i < 2; ++i)
|
||||
d_fetchl(&pdata, &data->u.dthd.thdResrv[i]);
|
||||
|
||||
d_fetchl(&pdata, (long *) &data->u.dthd.thdParID);
|
||||
d_fetchs(&pdata, data->u.dthd.thdCName, sizeof(data->u.dthd.thdCName));
|
||||
break;
|
||||
|
||||
case cdrFThdRec:
|
||||
for (i = 0; i < 2; ++i)
|
||||
d_fetchl(&pdata, &data->u.fthd.fthdResrv[i]);
|
||||
|
||||
d_fetchl(&pdata, (long *) &data->u.fthd.fthdParID);
|
||||
d_fetchs(&pdata, data->u.fthd.fthdCName, sizeof(data->u.fthd.fthdCName));
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->packextdata()
|
||||
* DESCRIPTION: pack extent record data
|
||||
*/
|
||||
void r_packextdata(ExtDataRec *data, unsigned char *pdata, int *len)
|
||||
{
|
||||
unsigned char *start = pdata;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
d_storew(&pdata, (*data)[i].xdrStABN);
|
||||
d_storew(&pdata, (*data)[i].xdrNumABlks);
|
||||
}
|
||||
|
||||
if (len)
|
||||
*len += pdata - start;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->unpackextdata()
|
||||
* DESCRIPTION: unpack extent record data
|
||||
*/
|
||||
void r_unpackextdata(unsigned char *pdata, ExtDataRec *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
d_fetchw(&pdata, (short *) &(*data)[i].xdrStABN);
|
||||
d_fetchw(&pdata, (short *) &(*data)[i].xdrNumABlks);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->makecatkey()
|
||||
* DESCRIPTION: construct a catalog record key
|
||||
*/
|
||||
void r_makecatkey(CatKeyRec *key, long parid, char *name)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = strlen(name) + 1;
|
||||
|
||||
key->ckrKeyLen = 0x05 + len + (len & 1);
|
||||
key->ckrResrv1 = 0;
|
||||
key->ckrParID = parid;
|
||||
|
||||
strcpy(key->ckrCName, name);
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->makeextkey()
|
||||
* DESCRIPTION: construct an extents record key
|
||||
*/
|
||||
void r_makeextkey(ExtKeyRec *key, int fork, long fnum, unsigned int fabn)
|
||||
{
|
||||
key->xkrKeyLen = 0x07;
|
||||
key->xkrFkType = fork;
|
||||
key->xkrFNum = fnum;
|
||||
key->xkrFABN = fabn;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->unpackdirent()
|
||||
* DESCRIPTION: unpack catalog information into hfsdirent structure
|
||||
*/
|
||||
void r_unpackdirent(long parid, char *name, CatDataRec *data, hfsdirent *ent)
|
||||
{
|
||||
strcpy(ent->name, name);
|
||||
ent->parid = parid;
|
||||
|
||||
switch (data->cdrType)
|
||||
{
|
||||
case cdrDirRec:
|
||||
ent->flags = HFS_ISDIR;
|
||||
ent->cnid = data->u.dir.dirDirID;
|
||||
ent->crdate = d_toutime(data->u.dir.dirCrDat);
|
||||
ent->mddate = d_toutime(data->u.dir.dirMdDat);
|
||||
ent->dsize = data->u.dir.dirVal;
|
||||
ent->rsize = 0;
|
||||
|
||||
ent->type[0] = ent->creator[0] = 0;
|
||||
|
||||
ent->fdflags = data->u.dir.dirUsrInfo.frFlags;
|
||||
break;
|
||||
|
||||
case cdrFilRec:
|
||||
ent->flags = (data->u.fil.filFlags & (1 << 0)) ? HFS_ISLOCKED : 0;
|
||||
ent->cnid = data->u.fil.filFlNum;
|
||||
ent->crdate = d_toutime(data->u.fil.filCrDat);
|
||||
ent->mddate = d_toutime(data->u.fil.filMdDat);
|
||||
ent->dsize = data->u.fil.filLgLen;
|
||||
ent->rsize = data->u.fil.filRLgLen;
|
||||
|
||||
d_putl((unsigned char *) ent->type, data->u.fil.filUsrWds.fdType);
|
||||
d_putl((unsigned char *) ent->creator, data->u.fil.filUsrWds.fdCreator);
|
||||
|
||||
ent->type[4] = ent->creator[4] = 0;
|
||||
|
||||
ent->fdflags = data->u.fil.filUsrWds.fdFlags;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NAME: record->packdirent()
|
||||
* DESCRIPTION: make changes to a catalog record
|
||||
*/
|
||||
void r_packdirent(CatDataRec *data, hfsdirent *ent)
|
||||
{
|
||||
switch (data->cdrType)
|
||||
{
|
||||
case cdrDirRec:
|
||||
data->u.dir.dirCrDat = d_tomtime(ent->crdate);
|
||||
data->u.dir.dirMdDat = d_tomtime(ent->mddate);
|
||||
|
||||
data->u.dir.dirUsrInfo.frFlags = ent->fdflags;
|
||||
break;
|
||||
|
||||
case cdrFilRec:
|
||||
if (ent->flags & HFS_ISLOCKED)
|
||||
data->u.fil.filFlags |= (1 << 0);
|
||||
else
|
||||
data->u.fil.filFlags &= ~(1 << 0);
|
||||
|
||||
data->u.fil.filCrDat = d_tomtime(ent->crdate);
|
||||
data->u.fil.filMdDat = d_tomtime(ent->mddate);
|
||||
|
||||
data->u.fil.filUsrWds.fdType = d_getl((unsigned char *) ent->type);
|
||||
data->u.fil.filUsrWds.fdCreator = d_getl((unsigned char *) ent->creator);
|
||||
|
||||
data->u.fil.filUsrWds.fdFlags = ent->fdflags;
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
void r_packcatkey(CatKeyRec *, unsigned char *, int *);
|
||||
void r_unpackcatkey(unsigned char *, CatKeyRec *);
|
||||
|
||||
void r_packextkey(ExtKeyRec *, unsigned char *, int *);
|
||||
void r_unpackextkey(unsigned char *, ExtKeyRec *);
|
||||
|
||||
int r_comparecatkeys(unsigned char *, unsigned char *);
|
||||
int r_compareextkeys(unsigned char *, unsigned char *);
|
||||
|
||||
void r_packcatdata(CatDataRec *, unsigned char *, int *);
|
||||
void r_unpackcatdata(unsigned char *, CatDataRec *);
|
||||
|
||||
void r_packextdata(ExtDataRec *, unsigned char *, int *);
|
||||
void r_unpackextdata(unsigned char *, ExtDataRec *);
|
||||
|
||||
void r_makecatkey(CatKeyRec *, long, char *);
|
||||
void r_makeextkey(ExtKeyRec *, int, long, unsigned int);
|
||||
|
||||
void r_unpackdirent(long, char *, CatDataRec *, hfsdirent *);
|
||||
void r_packdirent(CatDataRec *, hfsdirent *);
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* hfsutils - tools for reading and writing Macintosh HFS volumes
|
||||
* Copyright (C) 1996, 1997 Robert Leslie
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
int v_catsearch(hfsvol *, long, char *, CatDataRec *, char *, node *);
|
||||
int v_extsearch(hfsfile *, unsigned int, ExtDataRec *, node *);
|
||||
|
||||
int v_getthread(hfsvol *, long, CatDataRec *, node *, int);
|
||||
|
||||
# define v_getdthread(vol, id, thread, np) \
|
||||
v_getthread(vol, id, thread, np, cdrThdRec)
|
||||
# define v_getfthread(vol, id, thread, np) \
|
||||
v_getthread(vol, id, thread, np, cdrFThdRec)
|
||||
|
||||
int v_putcatrec(CatDataRec *, node *);
|
||||
int v_putextrec(ExtDataRec *, node *);
|
||||
|
||||
int v_allocblocks(hfsvol *, ExtDescriptor *);
|
||||
void v_freeblocks(hfsvol *, ExtDescriptor *);
|
||||
|
||||
int v_resolve(hfsvol **, char *, CatDataRec *, long *, char *, node *);
|
||||
|
||||
void v_destruct(hfsvol *);
|
||||
int v_getvol(hfsvol **);
|
||||
int v_flush(hfsvol *, int);
|
||||
|
||||
int v_adjvalence(hfsvol *, long, int, int);
|
||||
int v_newfolder(hfsvol *, long, char *);
|
||||
|
||||
int v_scavenge(hfsvol *);
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
** mac_label.c: generate Mactintosh partition maps and label
|
||||
**
|
||||
** Taken from "mkisofs 1.05 PLUS" by Andy Polyakov <appro@fy.chalmers.se>
|
||||
** (see http://fy.chalmers.se/~appro/mkisofs_plus.html for details)
|
||||
**
|
||||
** The format of the HFS driver file:
|
||||
**
|
||||
** HFS CD Label Block 512 bytes
|
||||
** Driver Partition Map (for 2048 byte blocks) 512 bytes
|
||||
** Driver Partition Map (for 512 byte blocks) 512 bytes
|
||||
** Empty 512 bytes
|
||||
** Driver Partition N x 2048 bytes
|
||||
** HFS Partition Boot Block 1024 bytes
|
||||
**
|
||||
** File of the above format can be extracted from a CD using
|
||||
** apple_driver.c
|
||||
**
|
||||
** James Pearson 16/5/98
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <mkisofs.h>
|
||||
#include "mac_label_proto.h"
|
||||
#include <mac_label.h>
|
||||
|
||||
int
|
||||
gen_mac_label(defer *mac_boot)
|
||||
{
|
||||
FILE *fp;
|
||||
MacLabel *mac_label;
|
||||
MacPart *mac_part;
|
||||
char *buffer = hce->hfs_map;
|
||||
int block_size;
|
||||
int have_hfs_boot = 0;
|
||||
char tmp[SECTOR_SIZE];
|
||||
struct stat stat_buf;
|
||||
mac_partition_table mpm[2];
|
||||
int mpc = 0;
|
||||
int i;
|
||||
|
||||
/* If we have a boot file, then open and check it */
|
||||
if (mac_boot->name) {
|
||||
if (stat(mac_boot->name, &stat_buf) < 0) {
|
||||
snprintf(hce->error, ERROR_SIZE,
|
||||
"unable to stat HFS boot file %s", mac_boot->name);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
if ((fp = fopen(mac_boot->name, "rb")) == NULL) {
|
||||
snprintf(hce->error, ERROR_SIZE,
|
||||
"unable to open HFS boot file %s", mac_boot->name);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (fread(tmp, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) {
|
||||
snprintf(hce->error, ERROR_SIZE,
|
||||
"unable to read HFS boot file %s", mac_boot->name);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
/* check we have a bootable partition */
|
||||
mac_part = (MacPart*)(tmp+HFS_BLOCKSZ);
|
||||
|
||||
if (!(IS_MAC_PART(mac_part) && !strncmp(mac_part->pmPartType, pmPartType_2, 12))) {
|
||||
snprintf(hce->error, ERROR_SIZE, "%s is not a HFS boot file",
|
||||
mac_boot->name);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* check we have a boot block as well - last 2 blocks of file */
|
||||
|
||||
if (fseek(fp, -2 * HFS_BLOCKSZ, 2) != 0) {
|
||||
snprintf(hce->error, ERROR_SIZE,
|
||||
"unable to seek HFS boot file %s", mac_boot->name);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* overwrite (empty) boot block for our HFS volume */
|
||||
if (fread(hce->hfs_hdr, 2, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ) {
|
||||
snprintf(hce->error, ERROR_SIZE,
|
||||
"unable to read HFS boot block %s", mac_boot->name);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
|
||||
/* check boot block is valid */
|
||||
if (d_getw((unsigned char *)hce->hfs_hdr) != HFS_BB_SIGWORD) {
|
||||
snprintf(hce->error, ERROR_SIZE,
|
||||
"%s does not contain a valid boot block", mac_boot->name);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* collect info about boot file for later user - skip over the boot
|
||||
file header */
|
||||
mac_boot->size = stat_buf.st_size - SECTOR_SIZE - 2*HFS_BLOCKSZ;
|
||||
mac_boot->off = SECTOR_SIZE;
|
||||
mac_boot->pad = 0;
|
||||
|
||||
/* get size in SECTOR_SIZE blocks - shouldn't need to round up */
|
||||
mpm[mpc].size = ROUND_UP(mac_boot->size)/SECTOR_SIZE;
|
||||
|
||||
mpm[mpc].ntype = PM2;
|
||||
mpm[mpc].type = mac_part->pmPartType;
|
||||
mpm[mpc].start = mac_boot->extent = last_extent;
|
||||
mpm[mpc].name = 0;
|
||||
|
||||
/* flag that we have a boot file */
|
||||
have_hfs_boot++;
|
||||
|
||||
/* add boot file size to the total size */
|
||||
last_extent += mpm[mpc].size;
|
||||
hfs_extra += mpm[mpc].size;
|
||||
|
||||
mpc++;
|
||||
}
|
||||
|
||||
/* set info about our hybrid volume */
|
||||
mpm[mpc].ntype = PM4;
|
||||
mpm[mpc].type = pmPartType_4;
|
||||
mpm[mpc].start = hce->hfs_map_size / BLK_CONV;
|
||||
mpm[mpc].size = last_extent - mpm[mpc].start;
|
||||
mpm[mpc].name = volume_id;
|
||||
|
||||
mpc++;
|
||||
|
||||
if (verbose > 1)
|
||||
fprintf(stderr, "Creating HFS Label %s %s\n", mac_boot->name ?
|
||||
"with boot file" : "", mac_boot->name ? mac_boot->name : "" );
|
||||
|
||||
/* for a bootable CD, block size is SECTOR_SIZE */
|
||||
block_size = have_hfs_boot ? SECTOR_SIZE : HFS_BLOCKSZ;
|
||||
|
||||
/* create the CD label */
|
||||
mac_label = (MacLabel *)buffer;
|
||||
mac_label->sbSig [0] = 'E';
|
||||
mac_label->sbSig [1] = 'R';
|
||||
set_722 (mac_label->sbBlkSize,block_size);
|
||||
set_732 (mac_label->sbBlkCount,last_extent*(SECTOR_SIZE/block_size));
|
||||
set_722 (mac_label->sbDevType,1);
|
||||
set_722 (mac_label->sbDevId,1);
|
||||
|
||||
/* create the partition map entry */
|
||||
mac_part = (MacPart*)(buffer+block_size);
|
||||
mac_part->pmSig [0] = 'P';
|
||||
mac_part->pmSig [1] = 'M';
|
||||
set_732 (mac_part->pmMapBlkCnt,mpc+1);
|
||||
set_732 (mac_part->pmPyPartStart,1);
|
||||
set_732 (mac_part->pmPartBlkCnt,mpc+1);
|
||||
strncpy (mac_part->pmPartName,"Apple",sizeof(mac_part->pmPartName));
|
||||
strncpy (mac_part->pmPartType,"Apple_partition_map",sizeof(mac_part->pmPartType));
|
||||
set_732 (mac_part->pmLgDataStart,0);
|
||||
set_732 (mac_part->pmDataCnt,mpc+1);
|
||||
set_732 (mac_part->pmPartStatus,PM_STAT_DEFAULT);
|
||||
|
||||
/* create partition map entries for our partitions */
|
||||
for (i=0;i<mpc;i++) {
|
||||
mac_part = (MacPart*)(buffer + (i+2)*block_size);
|
||||
if (mpm[i].ntype == PM2) {
|
||||
/* get driver label and patch it */
|
||||
memcpy (mac_label, tmp, HFS_BLOCKSZ);
|
||||
set_732 (mac_label->sbBlkCount,last_extent*(SECTOR_SIZE/block_size));
|
||||
set_732 (mac_label->ddBlock,(mpm[i].start)*(SECTOR_SIZE/block_size));
|
||||
memcpy (mac_part, tmp+HFS_BLOCKSZ, HFS_BLOCKSZ);
|
||||
set_732 (mac_part->pmMapBlkCnt,mpc+1);
|
||||
set_732 (mac_part->pmPyPartStart,(mpm[i].start)*(SECTOR_SIZE/block_size));
|
||||
}
|
||||
else {
|
||||
mac_part->pmSig [0] = 'P';
|
||||
mac_part->pmSig [1] = 'M';
|
||||
set_732 (mac_part->pmMapBlkCnt,mpc+1);
|
||||
set_732 (mac_part->pmPyPartStart,mpm[i].start*(SECTOR_SIZE/HFS_BLOCKSZ));
|
||||
set_732 (mac_part->pmPartBlkCnt,mpm[i].size*(SECTOR_SIZE/HFS_BLOCKSZ));
|
||||
strncpy (mac_part->pmPartName,mpm[i].name,sizeof(mac_part->pmPartName));
|
||||
strncpy (mac_part->pmPartType,mpm[i].type,sizeof(mac_part->pmPartType));
|
||||
set_732 (mac_part->pmLgDataStart,0);
|
||||
set_732 (mac_part->pmDataCnt,mpm[i].size*(SECTOR_SIZE/HFS_BLOCKSZ));
|
||||
set_732 (mac_part->pmPartStatus,PM_STAT_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
if (have_hfs_boot) { /* generate 512 partition table as well */
|
||||
mac_part = (MacPart*)(buffer+HFS_BLOCKSZ);
|
||||
if (mpc<3) { /* don't have to interleave with 2048 table */
|
||||
mac_part->pmSig [0] = 'P';
|
||||
mac_part->pmSig [1] = 'M';
|
||||
set_732 (mac_part->pmMapBlkCnt,mpc+1);
|
||||
set_732 (mac_part->pmPyPartStart,1);
|
||||
set_732 (mac_part->pmPartBlkCnt,mpc+1);
|
||||
strncpy (mac_part->pmPartName,"Apple",sizeof(mac_part->pmPartName));
|
||||
strncpy (mac_part->pmPartType,"Apple_partition_map",sizeof(mac_part->pmPartType));
|
||||
set_732 (mac_part->pmLgDataStart,0);
|
||||
set_732 (mac_part->pmDataCnt,mpc+1);
|
||||
set_732 (mac_part->pmPartStatus,PM_STAT_DEFAULT);
|
||||
mac_part++; /* +HFS_BLOCKSZ */
|
||||
}
|
||||
for (i=0;i<mpc;i++,mac_part++) {
|
||||
if (mac_part == (MacPart*)(buffer+SECTOR_SIZE)) mac_part++; /* jump over 2048 partition entry */
|
||||
if (mpm[i].ntype == PM2) {
|
||||
memcpy (mac_part, tmp+HFS_BLOCKSZ*2, HFS_BLOCKSZ);
|
||||
if (!IS_MAC_PART(mac_part)) { mac_part--; continue; }
|
||||
set_732 (mac_part->pmMapBlkCnt,mpc+1);
|
||||
set_732 (mac_part->pmPyPartStart,(mpm[i].start)*(SECTOR_SIZE/HFS_BLOCKSZ));
|
||||
}
|
||||
else {
|
||||
mac_part->pmSig [0] = 'P';
|
||||
mac_part->pmSig [1] = 'M';
|
||||
set_732 (mac_part->pmMapBlkCnt,mpc+1);
|
||||
set_732 (mac_part->pmPyPartStart,mpm[i].start*(SECTOR_SIZE/HFS_BLOCKSZ));
|
||||
set_732 (mac_part->pmPartBlkCnt,mpm[i].size*(SECTOR_SIZE/HFS_BLOCKSZ));
|
||||
strncpy (mac_part->pmPartName,mpm[i].name,sizeof(mac_part->pmPartName));
|
||||
strncpy (mac_part->pmPartType,mpm[i].type,sizeof(mac_part->pmPartType));
|
||||
set_732 (mac_part->pmLgDataStart,0);
|
||||
set_732 (mac_part->pmDataCnt,mpm[i].size*(SECTOR_SIZE/HFS_BLOCKSZ));
|
||||
set_732 (mac_part->pmPartStatus,PM_STAT_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
** autostart: make the HFS CD use the QuickTime 2.0 Autostart feature.
|
||||
**
|
||||
** based on information from Eric Eisenhart <eric@sonic.net> and
|
||||
** http://developer.apple.com/qa/qtpc/qtpc12.html and
|
||||
** http://developer.apple.com/dev/techsupport/develop/issue26/macqa.html
|
||||
**
|
||||
** The name of the AutoStart file is stored in the area allocated for
|
||||
** the Clipboard name. This area begins 106 bytes into the sector of
|
||||
** block 0, with the first four bytes at that offset containing the
|
||||
** hex value 0x006A7068. This value indicates that an AutoStart
|
||||
** filename follows. After this 4-byte tag, 12 bytes remain, starting
|
||||
** at offset 110. In these 12 bytes, the name of the AutoStart file is
|
||||
** stored as a Pascal string, giving you up to 11 characters to identify
|
||||
** the file. The file must reside in the root directory of the HFS
|
||||
** volume or partition.
|
||||
*/
|
||||
|
||||
int
|
||||
autostart()
|
||||
{
|
||||
int len, i;
|
||||
|
||||
if((len = strlen(autoname)) > 11)
|
||||
return (-1);
|
||||
|
||||
hce->hfs_hdr[106] = 0x00;
|
||||
hce->hfs_hdr[107] = 0x6A;
|
||||
hce->hfs_hdr[108] = 0x70;
|
||||
hce->hfs_hdr[109] = 0x68;
|
||||
hce->hfs_hdr[110] = len;
|
||||
|
||||
for(i=0;i<len;i++)
|
||||
hce->hfs_hdr[111+i] = autoname[i];
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
** mac_label.h: defines Macintosh partition maps and label
|
||||
**
|
||||
** Taken from "mkisofs 1.05 PLUS" by Andy Polyakov <appro@fy.chalmers.se>
|
||||
** (see http://fy.chalmers.se/~appro/mkisofs_plus.html for details)
|
||||
**
|
||||
** Much of this is already defined in the libhfs code, but to keep
|
||||
** things simple we stick with these.
|
||||
*/
|
||||
|
||||
#ifndef __MAC_LABEL__
|
||||
#define __MAC_LABEL__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Driver Descriptor Map */
|
||||
#define sbSigMagic "ER"
|
||||
struct MacLabel {
|
||||
unsigned char sbSig[2]; /* unique value for SCSI block 0 */
|
||||
unsigned char sbBlkSize[2]; /* block size of device */
|
||||
unsigned char sbBlkCount[4]; /* number of blocks on device */
|
||||
unsigned char sbDevType[2]; /* device type */
|
||||
unsigned char sbDevId[2]; /* device id */
|
||||
unsigned char sbData[4]; /* not used */
|
||||
unsigned char sbDrvrCount[2]; /* driver descriptor count */
|
||||
unsigned char ddBlock[4]; /* 1st driver's starting block */
|
||||
unsigned char ddSize[2]; /* size of 1st driver (512-byte blks) */
|
||||
unsigned char ddType[2]; /* system type (1 for Mac+) */
|
||||
unsigned char ddPad[486]; /* ARRAY[0..242] OF INTEGER; not used */
|
||||
};
|
||||
typedef struct MacLabel MacLabel;
|
||||
|
||||
#define IS_MAC_LABEL(d) (((MacLabel*)(d))->sbSig[0]=='E'&&((MacLabel*)(d))->sbSig[1]=='R')
|
||||
|
||||
/* Partition Map Entry */
|
||||
#define pmSigMagic "PM"
|
||||
|
||||
#define pmPartType_1 "Apple_partition_map"
|
||||
# define pmPartName_11 "Apple"
|
||||
|
||||
#define pmPartType_2 "Apple_Driver"
|
||||
#define pmPartType_21 "Apple_Driver43"
|
||||
|
||||
#define pmPartType_3 "Apple_UNIX_SVR2"
|
||||
# define pmPartName_31 "A/UX Root"
|
||||
# define pmPartName_32 "A/UX Usr"
|
||||
# define pmPartName_33 "Random A/UX fs"
|
||||
# define pmPartName_34 "Swap"
|
||||
|
||||
#define pmPartType_4 "Apple_HFS"
|
||||
# define pmPartName_41 "MacOS"
|
||||
|
||||
#define pmPartType_5 "Apple_Free"
|
||||
# define pmPartName_51 "Extra"
|
||||
|
||||
#define PM2 2
|
||||
#define PM4 4
|
||||
|
||||
struct MacPart {
|
||||
unsigned char pmSig[2]; /* unique value for map entry blk */
|
||||
unsigned char pmSigPad[2]; /* currently unused */
|
||||
unsigned char pmMapBlkCnt[4]; /* # of blks in partition map */
|
||||
unsigned char pmPyPartStart[4];/* physical start blk of partition */
|
||||
unsigned char pmPartBlkCnt[4];/* # of blks in this partition */
|
||||
unsigned char pmPartName[32]; /* ASCII partition name */
|
||||
unsigned char pmPartType[32]; /* ASCII partition type */
|
||||
unsigned char pmLgDataStart[4];/* log. # of partition's 1st data blk */
|
||||
unsigned char pmDataCnt[4]; /* # of blks in partition's data area */
|
||||
unsigned char pmPartStatus[4];/* bit field for partition status */
|
||||
unsigned char pmLgBootStart[4];/* log. blk of partition's boot code */
|
||||
unsigned char pmBootSize[4]; /* number of bytes in boot code */
|
||||
unsigned char pmBootAddr[4]; /* memory load address of boot code */
|
||||
unsigned char pmBootAddr2[4]; /* currently unused */
|
||||
unsigned char pmBootEntry[4]; /* entry point of boot code */
|
||||
unsigned char pmBootEntry2[4];/* currently unused */
|
||||
unsigned char pmBootCksum[4]; /* checksum of boot code */
|
||||
unsigned char pmProcessor[16];/* ASCII for the processor type */
|
||||
unsigned char pmPad[376]; /* ARRAY[0..187] OF INTEGER; not used */
|
||||
};
|
||||
typedef struct MacPart MacPart;
|
||||
|
||||
#define IS_MAC_PART(d) (((MacPart*)(d))->pmSig[0]=='P'&&((MacPart*)(d))->pmSig[1]=='M')
|
||||
|
||||
#define PM_STAT_VALID 0x01 /* Set if a valid partition map entry */
|
||||
#define PM_STAT_ALLOC 0x02 /* Set if partition is already allocated; clear if available */
|
||||
#define PM_STAT_INUSE 0x04 /* Set if partition is in use; may be cleared after a system reset */
|
||||
#define PM_STAT_BOOTABLE 0x08 /* Set if partition contains valid boot information */
|
||||
#define PM_STAT_READABLE 0x10 /* Set if partition allows reading */
|
||||
#define PM_STAT_WRITABLE 0x20 /* Set if partition allows writing */
|
||||
#define PM_STAT_BOOT_PIC 0x40 /* Set if boot code is position-independent */
|
||||
#define PM_STAT_UNUSED 0x80 /* Unused */
|
||||
#define PM_STAT_DEFAULT PM_STAT_VALID|PM_STAT_ALLOC|PM_STAT_READABLE|PM_STAT_WRITABLE
|
||||
|
||||
typedef struct {
|
||||
char *name; /* Partition name */
|
||||
char *type; /* Partition type */
|
||||
int ntype; /* Partition type (numeric) */
|
||||
int start; /* start extent (SECTOR_SIZE blocks) */
|
||||
int size; /* extents (SECTOR_SIZE blocks) */
|
||||
} mac_partition_table;
|
||||
|
||||
/* from libhfs */
|
||||
#define HFS_BB_SIGWORD 0x4c4b
|
||||
|
||||
/* borrowed from write.c - we just need parts of this */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MAC_LABEL__ */
|
|
@ -0,0 +1,40 @@
|
|||
/* mac_label_proto.h */
|
||||
/* $OpenBSD: mac_label_proto.h,v 1.1 2008/03/08 15:36:12 espie Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008 Marc Espie <espie@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MAC_LABEL_PROTO_H
|
||||
#define MAC_LABEL_PROTO_H
|
||||
|
||||
struct deferred_write {
|
||||
struct deferred_write * next;
|
||||
char * table;
|
||||
unsigned int extent;
|
||||
unsigned int size;
|
||||
char * name;
|
||||
#ifdef APPLE_HYB
|
||||
struct directory_entry *s_entry;
|
||||
unsigned int pad;
|
||||
unsigned int off;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct deferred_write defer;
|
||||
|
||||
extern int gen_mac_label(defer *);
|
||||
extern int autostart(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
/* Various types of HFS files stored on Unix systems */
|
||||
#define TYPE_NONE 0 /* Unknown file type (ordinary Unix file) */
|
||||
#define TYPE_CAP 1 /* AUFS CAP */
|
||||
#define TYPE_NETA 2 /* Netatalk */
|
||||
#define TYPE_DBL 3 /* AppleDouble */
|
||||
#define TYPE_ESH 4 /* Helios EtherShare */
|
||||
#define TYPE_FEU 5 /* PC Exchange (Upper case) */
|
||||
#define TYPE_FEL 6 /* PC Exchange (Lower case) */
|
||||
#define TYPE_SGI 7 /* SGI */
|
||||
#define TYPE_MBIN 8 /* MacBinary */
|
||||
#define TYPE_SGL 9 /* AppleSingle */
|
||||
|
||||
/* above encoded in a bit map */
|
||||
#define DO_NONE (1 << TYPE_NONE)
|
||||
#define DO_CAP (1 << TYPE_CAP)
|
||||
#define DO_NETA (1 << TYPE_NETA)
|
||||
#define DO_DBL (1 << TYPE_DBL)
|
||||
#define DO_ESH (1 << TYPE_ESH)
|
||||
#define DO_FEU (1 << TYPE_FEU)
|
||||
#define DO_FEL (1 << TYPE_FEL)
|
||||
#define DO_SGI (1 << TYPE_SGI)
|
||||
#define DO_MBIN (1 << TYPE_MBIN)
|
||||
#define DO_SGL (1 << TYPE_SGL)
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
#
|
||||
# Example magic file for mkhybrid
|
||||
#
|
||||
# The "message" for the offset MUST be 4 characters for the CREATOR
|
||||
# and 4 characters for the TYPE - white space is optional between them.
|
||||
# Any other characters on this line are ignored. Continuation lines (starting
|
||||
# with '>') are also ignored i.e. only the initial offset lines are used.
|
||||
#
|
||||
# The continuation lines are given here, but they do not need to exist.
|
||||
|
||||
#
|
||||
# James Pearson 20/5/98
|
||||
|
||||
# off type test message
|
||||
|
||||
# GIF
|
||||
0 string GIF8 8BIM GIFf
|
||||
>4 string 7a \b, version 8%s,
|
||||
>4 string 9a \b, version 8%s,
|
||||
>6 leshort >0 %hd x
|
||||
>8 leshort >0 %hd,
|
||||
#>10 byte &0x80 color mapped,
|
||||
#>10 byte&0x07 =0x00 2 colors
|
||||
#>10 byte&0x07 =0x01 4 colors
|
||||
#>10 byte&0x07 =0x02 8 colors
|
||||
#>10 byte&0x07 =0x03 16 colors
|
||||
#>10 byte&0x07 =0x04 32 colors
|
||||
#>10 byte&0x07 =0x05 64 colors
|
||||
#>10 byte&0x07 =0x06 128 colors
|
||||
#>10 byte&0x07 =0x07 256 colors
|
||||
|
||||
# JPEG images
|
||||
#
|
||||
0 ubeshort 0xffd8 8BIM JPEG image data
|
||||
|
||||
# StuffIt
|
||||
#
|
||||
0 string SIT! SIT!SIT!
|
||||
|
||||
# standard unix compress
|
||||
0 string \037\235 LZIV ZIVU
|
||||
>2 byte&0x80 >0 block compressed
|
||||
>2 byte&0x1f x %d bits
|
||||
|
||||
# gzip (GNU zip, not to be confused with Info-ZIP or PKWARE zip archiver)
|
||||
0 string \037\213 GNUz ZIVU gzip compressed data
|
||||
>2 byte <8 \b, reserved method,
|
||||
>2 byte 8 \b, deflated,
|
||||
>3 byte &0x01 ASCII,
|
||||
>3 byte &0x02 continuation,
|
||||
>3 byte &0x04 extra field,
|
||||
>3 byte &0x08 original filename,
|
||||
>3 byte &0x10 comment,
|
||||
>3 byte &0x20 encrypted,
|
||||
>4 ledate x last modified: %s,
|
||||
>8 byte 2 max compression,
|
||||
>8 byte 4 max speed,
|
||||
>9 byte =0x00 os: MS-DOS
|
||||
>9 byte =0x01 os: Amiga
|
||||
>9 byte =0x02 os: VMS
|
||||
>9 byte =0x03 os: Unix
|
||||
>9 byte =0x05 os: Atari
|
||||
>9 byte =0x06 os: OS/2
|
||||
>9 byte =0x07 os: MacOS
|
||||
>9 byte =0x0A os: Tops/20
|
||||
>9 byte =0x0B os: Win/32
|
||||
|
||||
# Postscript
|
||||
0 string %! ASPSTEXT
|
||||
>2 string PS-Adobe- conforming
|
||||
>>11 string >\0 at level %.3s
|
||||
>>>15 string EPS - type %s
|
||||
>>>15 string Query - type %s
|
||||
>>>15 string ExitServer - type %s
|
||||
# Some PCs have the annoying habit of adding a ^D as a document separator
|
||||
0 string \004%! ASPS TEXT PostScript document text
|
||||
>3 string PS-Adobe- conforming
|
||||
>>12 string >\0 at level %.3s
|
||||
>>>16 string EPS - type %s
|
||||
>>>16 string Query - type %s
|
||||
>>>16 string ExitServer - type %s
|
|
@ -0,0 +1,8 @@
|
|||
# Example filename mapping file
|
||||
#
|
||||
# EXTN XLate CREATOR TYPE Comment
|
||||
.tif Raw '8BIM' 'TIFF' "Photoshop TIFF image"
|
||||
.hqx Ascii 'BnHq' 'TEXT' "BinHex file"
|
||||
.doc Raw 'MSWD' 'WDBN' "Word file"
|
||||
.mov Raw 'TVOD' 'MooV' "QuickTime Movie"
|
||||
* Ascii 'ttxt' 'TEXT' "Text file"
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* 27-Mar-96: Jan-Piet Mens <jpm@mens.de>
|
||||
* added 'match' option (-m) to specify regular expressions NOT to be included
|
||||
* in the CD image.
|
||||
*/
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
/*
|
||||
* Added a number of routines to create lists of files to hidden from
|
||||
* the ISO9660 and/or Joliet trees. James Pearson (j.pearson@ge.ucl.ac.uk)
|
||||
* January 1999 (these will probably appear in mkisofs in the future)
|
||||
*/
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
#include "config.h"
|
||||
#include <prototyp.h>
|
||||
#include <stdio.h>
|
||||
#include <fnmatch.h>
|
||||
#ifndef VMS
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include "match.h"
|
||||
|
||||
#define MAXMATCH 1000
|
||||
static char *mat[MAXMATCH];
|
||||
|
||||
int add_match(fn)
|
||||
char * fn;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i=0; mat[i] && i<MAXMATCH; i++);
|
||||
if (i == MAXMATCH) {
|
||||
fprintf(stderr,"Can't exclude RE '%s' - too many entries in table\n",fn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
mat[i] = (char *) malloc(strlen(fn)+1);
|
||||
if (! mat[i]) {
|
||||
fprintf(stderr,"Can't allocate memory for excluded filename\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
strcpy(mat[i],fn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int matches(fn)
|
||||
char * fn;
|
||||
{
|
||||
/* very dumb search method ... */
|
||||
register int i;
|
||||
|
||||
for (i=0; mat[i] && i<MAXMATCH; i++) {
|
||||
if (fnmatch(mat[i], fn, FNM_PATHNAME) != FNM_NOMATCH) {
|
||||
return 1; /* found -> excluded filenmae */
|
||||
}
|
||||
}
|
||||
return 0; /* not found -> not excluded */
|
||||
}
|
||||
|
||||
/* ISO9660/RR hide */
|
||||
|
||||
static char *i_mat[MAXMATCH];
|
||||
|
||||
int i_add_match(fn)
|
||||
char * fn;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i=0; i_mat[i] && i<MAXMATCH; i++);
|
||||
if (i == MAXMATCH) {
|
||||
fprintf(stderr,"Can't exclude RE '%s' - too many entries in table\n",fn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
i_mat[i] = (char *) malloc(strlen(fn)+1);
|
||||
if (! i_mat[i]) {
|
||||
fprintf(stderr,"Can't allocate memory for excluded filename\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
strcpy(i_mat[i],fn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i_matches(fn)
|
||||
char * fn;
|
||||
{
|
||||
/* very dumb search method ... */
|
||||
register int i;
|
||||
|
||||
for (i=0; i_mat[i] && i<MAXMATCH; i++) {
|
||||
if (fnmatch(i_mat[i], fn, FNM_PATHNAME) != FNM_NOMATCH) {
|
||||
return 1; /* found -> excluded filenmae */
|
||||
}
|
||||
}
|
||||
return 0; /* not found -> not excluded */
|
||||
}
|
||||
|
||||
intptr_t i_ishidden()
|
||||
{
|
||||
return((intptr_t)i_mat[0]);
|
||||
}
|
||||
|
||||
/* Joliet hide */
|
||||
|
||||
static char *j_mat[MAXMATCH];
|
||||
|
||||
int j_add_match(fn)
|
||||
char * fn;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i=0; j_mat[i] && i<MAXMATCH; i++);
|
||||
if (i == MAXMATCH) {
|
||||
fprintf(stderr,"Can't exclude RE '%s' - too many entries in table\n",fn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
j_mat[i] = (char *) malloc(strlen(fn)+1);
|
||||
if (! j_mat[i]) {
|
||||
fprintf(stderr,"Can't allocate memory for excluded filename\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
strcpy(j_mat[i],fn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int j_matches(fn)
|
||||
char * fn;
|
||||
{
|
||||
/* very dumb search method ... */
|
||||
register int i;
|
||||
|
||||
for (i=0; j_mat[i] && i<MAXMATCH; i++) {
|
||||
if (fnmatch(j_mat[i], fn, FNM_PATHNAME) != FNM_NOMATCH) {
|
||||
return 1; /* found -> excluded filenmae */
|
||||
}
|
||||
}
|
||||
return 0; /* not found -> not excluded */
|
||||
}
|
||||
|
||||
intptr_t j_ishidden()
|
||||
{
|
||||
return((intptr_t)j_mat[0]);
|
||||
}
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
|
||||
/* HFS hide */
|
||||
|
||||
static char *hfs_mat[MAXMATCH];
|
||||
|
||||
int hfs_add_match(fn)
|
||||
char * fn;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i=0; hfs_mat[i] && i<MAXMATCH; i++);
|
||||
if (i == MAXMATCH) {
|
||||
fprintf(stderr,"Can't exclude RE '%s' - too many entries in table\n",fn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
hfs_mat[i] = (char *) malloc(strlen(fn)+1);
|
||||
if (! hfs_mat[i]) {
|
||||
fprintf(stderr,"Can't allocate memory for excluded filename\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
strcpy(hfs_mat[i],fn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hfs_add_list(file)
|
||||
char *file;
|
||||
{
|
||||
FILE *fp;
|
||||
char name[1024];
|
||||
|
||||
if ((fp = fopen(file, "r")) == NULL) {
|
||||
fprintf(stderr,"Can't open hidden file list %s\n", file);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
while (fscanf(fp, "%s", name) != EOF) {
|
||||
if (hfs_add_match(name)) {
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
int hfs_matches(fn)
|
||||
char * fn;
|
||||
{
|
||||
/* very dumb search method ... */
|
||||
register int i;
|
||||
|
||||
for (i=0; hfs_mat[i] && i<MAXMATCH; i++) {
|
||||
if (fnmatch(hfs_mat[i], fn, FNM_PATHNAME) != FNM_NOMATCH) {
|
||||
return 1; /* found -> excluded filenmae */
|
||||
}
|
||||
}
|
||||
return 0; /* not found -> not excluded */
|
||||
}
|
||||
|
||||
intptr_t hfs_ishidden()
|
||||
{
|
||||
return((intptr_t)hfs_mat[0]);
|
||||
}
|
||||
|
||||
/* These will probably appear in mkisofs in the future */
|
||||
|
||||
void add_list(file)
|
||||
char *file;
|
||||
{
|
||||
FILE *fp;
|
||||
char name[1024];
|
||||
|
||||
if ((fp = fopen(file, "r")) == NULL) {
|
||||
fprintf(stderr,"Can't open exclude file list %s\n", file);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
while (fscanf(fp, "%s", name) != EOF) {
|
||||
if (add_match(name)) {
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void i_add_list(file)
|
||||
char *file;
|
||||
{
|
||||
FILE *fp;
|
||||
char name[1024];
|
||||
|
||||
if ((fp = fopen(file, "r")) == NULL) {
|
||||
fprintf(stderr,"Can't open hidden file list %s\n", file);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
while (fscanf(fp, "%s", name) != EOF) {
|
||||
if (i_add_match(name)) {
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void j_add_list(file)
|
||||
char *file;
|
||||
{
|
||||
FILE *fp;
|
||||
char name[1024];
|
||||
|
||||
if ((fp = fopen(file, "r")) == NULL) {
|
||||
fprintf(stderr,"Can't open hidden file list %s\n", file);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
while (fscanf(fp, "%s", name) != EOF) {
|
||||
if (j_add_match(name)) {
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
#endif /* APPLE_HYB */
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 27th March 1996. Added by Jan-Piet Mens for matching regular expressions
|
||||
* in paths.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Id: match.h,v 1.5 2008/04/18 20:52:34 millert Exp
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
int matches __PR((char *fn));
|
||||
|
||||
int i_matches __PR((char *fn));
|
||||
intptr_t i_ishidden __PR((void));
|
||||
|
||||
int j_matches __PR((char *fn));
|
||||
intptr_t j_ishidden __PR((void));
|
||||
|
||||
int add_match __PR((char *fn));
|
||||
int i_add_match __PR((char *fn));
|
||||
int j_add_match __PR((char *fn));
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
int hfs_add_match __PR((char *fn));
|
||||
void hfs_add_list __PR((char *fn));
|
||||
int hfs_matches __PR((char *fn));
|
||||
intptr_t hfs_ishidden __PR((void));
|
||||
|
||||
void add_list __PR((char *fn));
|
||||
void i_add_list __PR((char *fn));
|
||||
void j_add_list __PR((char *fn));
|
||||
#endif /* APPLE_HYB */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,689 @@
|
|||
.\" -*- nroff -*-
|
||||
.\"
|
||||
.\" Id: mkisofs.8,v 1.1 2000/10/10 20:40:19 beck Exp
|
||||
.\"
|
||||
.TH MKISOFS 8 "17 Feb 1998" "Version 1.12b5"
|
||||
.SH NAME
|
||||
mkisofs \- create a iso9660 filesystem with optional Rock Ridge attributes.
|
||||
.SH SYNOPSIS
|
||||
.B mkisofs
|
||||
[
|
||||
.B \-a
|
||||
]
|
||||
[
|
||||
.B \-abstract
|
||||
.I FILE
|
||||
]
|
||||
[
|
||||
.B \-biblio
|
||||
.I FILE
|
||||
]
|
||||
[
|
||||
.B \-b
|
||||
.I boot_image
|
||||
]
|
||||
[
|
||||
.B \-c
|
||||
.I boot_catalog
|
||||
]
|
||||
[
|
||||
.B \-copyright
|
||||
.I FILE
|
||||
]
|
||||
[
|
||||
.B \-A
|
||||
.I application_id
|
||||
]
|
||||
[
|
||||
.B \-f
|
||||
]
|
||||
[
|
||||
.B \-d
|
||||
]
|
||||
[
|
||||
.B \-D
|
||||
]
|
||||
[
|
||||
.B \-hide
|
||||
.I glob
|
||||
]
|
||||
[
|
||||
.B \-hide-joliet
|
||||
.I glob
|
||||
]
|
||||
[
|
||||
.B \-J
|
||||
]
|
||||
[
|
||||
.B \-l
|
||||
]
|
||||
[
|
||||
.B \-L
|
||||
]
|
||||
[
|
||||
.B \-log-file
|
||||
.I log_file
|
||||
]
|
||||
[
|
||||
.B -no-split-symlink-components
|
||||
]
|
||||
[
|
||||
.B -no-split-symlink-fields
|
||||
]
|
||||
[
|
||||
.B \-p
|
||||
.I preparer
|
||||
]
|
||||
[
|
||||
.B \-print-size
|
||||
]
|
||||
[
|
||||
.B \-P
|
||||
.I publisher
|
||||
]
|
||||
[
|
||||
.B \-quiet
|
||||
]
|
||||
[
|
||||
.B \-r
|
||||
]
|
||||
[
|
||||
.B \-R
|
||||
]
|
||||
[
|
||||
.B \-sysid
|
||||
.I ID
|
||||
]
|
||||
[
|
||||
.B \-T
|
||||
]
|
||||
[
|
||||
.B \-v
|
||||
]
|
||||
[
|
||||
.B \-V
|
||||
.I volid
|
||||
]
|
||||
[
|
||||
.B \-volset
|
||||
.I ID
|
||||
]
|
||||
[
|
||||
.B \-volset-size
|
||||
.I #
|
||||
]
|
||||
[
|
||||
.B \-volset-seqno
|
||||
.I #
|
||||
]
|
||||
[
|
||||
.B \-x
|
||||
.I path
|
||||
]
|
||||
[
|
||||
.B \-z
|
||||
]
|
||||
[
|
||||
.B \-m
|
||||
.I glob
|
||||
]
|
||||
.B \-o
|
||||
.I filename
|
||||
.I pathspec [pathspec]
|
||||
.SH DESCRIPTION
|
||||
.B mkisofs
|
||||
is effectively a pre-mastering program to generate the iso9660 filesystem - it
|
||||
takes a snapshot of a given directory tree, and generates a binary image which
|
||||
will correspond to an iso9660 filesystem when written to a block device.
|
||||
.PP
|
||||
.B mkisofs
|
||||
is also capable of generating the System Use Sharing Protocol records specified
|
||||
by the Rock Ridge Interchange Protocol. This is used to further describe the
|
||||
files in the iso9660 filesystem to a unix host, and provides information such
|
||||
as longer filenames, uid/gid, posix permissions, and block and character
|
||||
devices.
|
||||
.PP
|
||||
Each file written to the iso9660 filesystem must have a filename in the 8.3
|
||||
format (8 characters, period, 3 characters, all upper case), even if Rock Ridge
|
||||
is in use. This filename is used on systems that are not able to make use of
|
||||
the Rock Ridge extensions (such as MS-DOS), and each filename in each directory
|
||||
must be different from the other filenames in the same directory.
|
||||
.B mkisofs
|
||||
generally tries to form correct names by forcing the unix filename to upper
|
||||
case and truncating as required, but often times this yields unsatisfactory
|
||||
results when there are cases where the
|
||||
truncated names are not all unique.
|
||||
.B mkisofs
|
||||
assigns weightings to each filename, and if two names that are otherwise the
|
||||
same are found the name with the lower priority is renamed to have a 3 digit
|
||||
number as an extension (where the number is guaranteed to be unique). An
|
||||
example of this would be the files foo.bar and
|
||||
foo.bar.~1~ - the file foo.bar.~1~ would be written as FOO.000;1 and the file
|
||||
foo.bar would be written as FOO.BAR;1
|
||||
.PP
|
||||
Note that
|
||||
.B mkisofs
|
||||
is not designed to communicate with the writer directly. Most writers
|
||||
have proprietary command sets which vary from one manufacturer to
|
||||
another, and you need a specialized tool to actually burn the disk.
|
||||
The
|
||||
.B cdwrite
|
||||
utility is one such tool that runs under Linux and performs this task.
|
||||
The latest version of
|
||||
.B cdwrite
|
||||
is capable of communicating with the Phillips/IMS/Kodak, HP and Yamaha drives
|
||||
that have been manufactured before 1997.
|
||||
Most writers come with some version of DOS software that allows a direct image
|
||||
copy of an iso9660 image to the writer. The current version of
|
||||
.B cdwrite
|
||||
is available from sunsite.unc.edu: /utils/disk-management/cdwrite-2.0.tar.gz
|
||||
Note that cdwrite has not been actively maintained since 1995.
|
||||
.PP
|
||||
The
|
||||
.B
|
||||
cdrecord
|
||||
utility is another utility capable of burning an actual disc. The latest version
|
||||
of
|
||||
.B cdrecord
|
||||
is available from
|
||||
ftp://ftp.fokus.gmd.de/pub/unix/cdrecord
|
||||
Cdrecord is under constant development.
|
||||
.PP
|
||||
Also you should know that most cd writers are very particular about timing.
|
||||
Once you start to burn a disc, you cannot let their buffer empty before you
|
||||
are done, or you will end up with a corrupt disc. Thus it is critical
|
||||
that you be able to maintain an uninterrupted data stream to the writer
|
||||
for the entire time that the disc is being written.
|
||||
.PP
|
||||
.br
|
||||
.B path
|
||||
is the path of the directory tree to be copied into the iso9660 filesystem.
|
||||
Multiple paths can be specified, and
|
||||
.B
|
||||
mkisofs
|
||||
will merge the files found in all of the specified path components to form the cdrom
|
||||
image.
|
||||
.PP
|
||||
It is possible to graft the paths at points other than the root
|
||||
directory, and it is possible to graft files or directories onto the
|
||||
cdrom image with names different than what they have in the source filesystem. This is
|
||||
easiest to illustrate with a couple of examples. Let's start by assuming that a local
|
||||
file ../old.lis exists, and you wish to include it in the cdrom image.
|
||||
|
||||
|
||||
foo/bar/=../old.lis
|
||||
|
||||
will include the file old.lis in the cdrom image at /foo/bar/old.lis, while
|
||||
|
||||
foo/bar/xxx=../old.lis
|
||||
|
||||
will include the file old.lis in the cdrom image at /foo/bar/xxx. The
|
||||
same sort of syntax can be used with directories as well.
|
||||
.B
|
||||
mkisofs will create any directories required such that the graft
|
||||
points exist on the cdrom image - the directories do not need to
|
||||
appear in one of the paths. Any directories that are created on the
|
||||
fly like this will have permissions 0555 and appear to be owned by the
|
||||
person running mkisofs. If you wish other permissions or owners of
|
||||
the intermediate directories, the easiest solution is to create real
|
||||
directories in the path such that mkisofs doesn't have to invent them.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-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
|
||||
.BI \-abstract " FILE
|
||||
Specifies the abstract file name.
|
||||
This parameter can also be set in the file
|
||||
.B \&.mkisofsrc
|
||||
with ABST=filename.
|
||||
If specified in both places, the command line version is used.
|
||||
.TP
|
||||
.BI \-A " application_id
|
||||
Specifies a text string that will be written into the volume header.
|
||||
This should describe the application that will be on the disc. There
|
||||
is space on the disc for 128 characters of information. This parameter can
|
||||
also be set in the file
|
||||
.B \&.mkisofsrc
|
||||
with APPI=id.
|
||||
If specified in both places, the command line version is used.
|
||||
.TP
|
||||
.BI \-biblio " FILE
|
||||
Specifies the bibliographic file name.
|
||||
This parameter can also be set in the file
|
||||
.B \&.mkisofsrc
|
||||
with BIBLO=filename.
|
||||
If specified in both places, the command line version is used.
|
||||
.TP
|
||||
.BI \-b " boot_image
|
||||
Specifies the path and filename of the boot image to be used when making
|
||||
an "El Torito" bootable CD. The pathname must be relative to the source
|
||||
path specified to
|
||||
.B mkisofs.
|
||||
This option is required to make a bootable CD.
|
||||
The boot image must be exactly the size of either a 1.2, 1.44, or a 2.88
|
||||
meg floppy, and
|
||||
.B mkisofs
|
||||
will use this size when creating the output iso9660
|
||||
filesystem. It is assumed that the first 512 byte sector should be read
|
||||
from the boot image (it is essentially emulating a normal floppy drive).
|
||||
This will work, for example, if the boot image is a LILO based boot floppy.
|
||||
.TP
|
||||
.BI \-C " last_sess_start,next_sess_start
|
||||
This option is needed when
|
||||
.B mkisofs
|
||||
is used to create the image of a second session or a higher level session
|
||||
for a multi session disk.
|
||||
The option
|
||||
.B \-C
|
||||
takes a pair of two numbers separated by a comma. The first number is the
|
||||
sector number of the first sector in the last session of the disk
|
||||
that should be appended to.
|
||||
The second number is the starting sector number of the new session.
|
||||
The expected pair of numbers may be retrieved by calling
|
||||
.B "cdrecord -msinfo ...
|
||||
the
|
||||
.B \-C
|
||||
option may only be uses in conjunction with the
|
||||
.B \-M
|
||||
option.
|
||||
.TP
|
||||
.BI \-c " boot_catalog
|
||||
Specifies the path and filename of the boot catalog to be used when making
|
||||
an "El Torito" bootable CD. The pathname must be relative to the source
|
||||
path specified to
|
||||
.B mkisofs.
|
||||
This option is required to make a bootable CD.
|
||||
This file will be created by
|
||||
.B mkisofs
|
||||
in the source filesystem, so be
|
||||
sure the specified filename does not conflict with an existing file, as
|
||||
it will be quietly overwritten! Usually a name like "boot.catalog" is
|
||||
chosen.
|
||||
.TP
|
||||
.BI \-copyright " FILE
|
||||
Specifies the Copyright file name.
|
||||
This parameter can also be set in the file
|
||||
.B \&.mkisofsrc
|
||||
with COPY=filename.
|
||||
If specified in both places, the command line version is used.
|
||||
.TP
|
||||
.B \-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
|
||||
.B \-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
|
||||
.B \-f
|
||||
Follow symbolic links when generating the filesystem. When this option is not
|
||||
in use, symbolic links will be entered using Rock Ridge if enabled, otherwise
|
||||
the file will be ignored.
|
||||
.TP
|
||||
.BI \-hide " glob
|
||||
Hide
|
||||
.I glob
|
||||
from being seen on the ISO9660 or Rock Ridge directory.
|
||||
.I glob
|
||||
is a shell wild-card-style pattern that must match any part of the filename
|
||||
or path.
|
||||
Multiple globs may be hidden (up to 1000).
|
||||
If
|
||||
.I glob
|
||||
matches a directory, then the contents of that directory will be hidden.
|
||||
All the hidden files will still be written to the output CD image file.
|
||||
Should be used with the
|
||||
.B \-hide-joliet
|
||||
option.
|
||||
.TP
|
||||
.BI \-hide-joliet " glob
|
||||
Hide
|
||||
.I glob
|
||||
from being seen on the Joliet directory.
|
||||
.I glob
|
||||
is a shell wild-card-style pattern that must match any part of the filename
|
||||
or path.
|
||||
Multiple globs may be hidden (up to 1000).
|
||||
If
|
||||
.I glob
|
||||
matches a directory, then the contents of that directory will be hidden.
|
||||
All the hidden files will still be written to the output CD image file.
|
||||
Should be used with the
|
||||
.B \-hide
|
||||
option.
|
||||
.TP
|
||||
.B \-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
|
||||
.B \-J
|
||||
Generate Joliet directory records in addition to regular iso9660 file
|
||||
names. This is primarily useful when the discs are to be used on Windows-NT
|
||||
or Windows-95 machines. The Joliet filenames are specified in Unicode and
|
||||
each path component can be up to 64 Unicode characters long.
|
||||
.TP
|
||||
.B \-L
|
||||
Allow filenames to begin with a period. Usually, a leading dot is
|
||||
replaced with an underscore in order to maintain MS-DOS compatibility.
|
||||
.TP
|
||||
.BI \-log-file " log_file
|
||||
Redirect all error, warning and informational messages to
|
||||
.I log_file
|
||||
instead of the standard error.
|
||||
.TP
|
||||
.BI \-m " glob
|
||||
Exclude
|
||||
.I glob
|
||||
from being written to CDROM.
|
||||
.I glob
|
||||
is a shell wild-card-style pattern that must match part of the filename (not
|
||||
the path as with option
|
||||
.BR -x ).
|
||||
Technically
|
||||
.I glob
|
||||
is matched against the
|
||||
.I d->d_name
|
||||
part of the directory entry.
|
||||
Multiple globs may be excluded (up to 1000).
|
||||
Example:
|
||||
|
||||
mkisofs \-o rom \-m '*.o' \-m core \-m foobar
|
||||
|
||||
would exclude all files ending in ".o", called "core" or "foobar" to be
|
||||
copied to CDROM. Note that if you had a directory called "foobar" it too (and
|
||||
of course all its descendants) would be excluded.
|
||||
.sp
|
||||
NOTE: The \-m and \-x option description should both be updated, they are wrong.
|
||||
Both now work identical and use filename globbing. A file is exluded if either
|
||||
the last component matches or the whole path matches.
|
||||
.TP
|
||||
.BI \-M " path
|
||||
or
|
||||
.TP
|
||||
.BI \-M " device
|
||||
Specifies path to existing iso9660 image to be merged. The alternate form
|
||||
takes a SCSI device specifier that uses the same syntax as the
|
||||
.B "dev=
|
||||
parameter of
|
||||
.B cdrecord.
|
||||
The output of
|
||||
.B mkisofs
|
||||
will be a new session which should get written to the end of the
|
||||
image specified in -M. Typically this requires multi-session capability
|
||||
for the recorder and cdrom drive that you are attempting to write this
|
||||
image to.
|
||||
This option may only be used in conjunction with the
|
||||
.B \-C
|
||||
option.
|
||||
.TP
|
||||
.B \-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
|
||||
.B \-no-split-symlink-components
|
||||
Don't split the SL components, but begin a new Continuation Area (CE)
|
||||
instead. This may waste some space, but the SunOS 4.1.4 cdrom driver
|
||||
has a bug in reading split SL components (link_size = component_size
|
||||
instead of link_size += component_size).
|
||||
.TP
|
||||
.B \-no-split-symlink-fields
|
||||
Don't split the SL fields, but begin a new Continuation Area (CE)
|
||||
instead. This may waste some space, but the SunOS 4.1.4 and
|
||||
Solaris 2.5.1 cdrom driver have a bug in reading split SL fields
|
||||
(a `/' can be dropped).
|
||||
.TP
|
||||
.BI \-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
|
||||
.BI \-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
|
||||
.B \&.mkisofsrc
|
||||
with PUBL=.
|
||||
If specified in both places, the command line version is used.
|
||||
.TP
|
||||
.BI \-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
|
||||
.B \&.mkisofsrc
|
||||
with PREP=.
|
||||
If specified in both places, the command line version is used.
|
||||
.TP
|
||||
.B \-print-size
|
||||
Print estimated filesystem size and exit. This option is needed for
|
||||
Disk At Once mode and with some CD-R drives when piping directly into
|
||||
.B cdrecord.
|
||||
In this case it is needed to know the size of the filesustem before the
|
||||
actual CD-creation is done.
|
||||
The option \-print-size allows to get this size from a "dry-run" before
|
||||
the CD is actually written.
|
||||
.TP
|
||||
.B \-R
|
||||
Generate SUSP and RR records using the Rock Ridge protocol to further describe
|
||||
the files on the iso9660 filesystem.
|
||||
.TP
|
||||
.B \-r
|
||||
This is like the \-R option, but file ownership and modes are set to
|
||||
more useful values. The uid and gid are set to zero, because they are
|
||||
usually only useful on the author's system, and not useful to the
|
||||
client. All the file read bits are set true, so that files and
|
||||
directories are globally readable on the client. If any execute bit is
|
||||
set for a file, set all of the execute bits, so that executables are
|
||||
globally executable on the client. If any search bit is set for a
|
||||
directory, set all of the search bits, so that directories are globally
|
||||
searchable on the client. All write bits are cleared, because the
|
||||
CD-Rom will be mounted read-only in any case. If any of the special
|
||||
mode bits are set, clear them, because file locks are not useful on a
|
||||
read-only file system, and set-id bits are not desirable for uid 0 or
|
||||
gid 0.
|
||||
.TP
|
||||
.BI \-sysid " ID
|
||||
Specifies the system ID.
|
||||
This parameter can also be set in the file
|
||||
.B \&.mkisofsrc
|
||||
with SYSI=system_id.
|
||||
If specified in both places, the command line version is used.
|
||||
.TP
|
||||
.B \-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
|
||||
.BI \-V " volid
|
||||
Specifies the volume ID to be written into the master block. This
|
||||
parameter can also be set in the file
|
||||
.B \&.mkisofsrc
|
||||
with VOLI=id.
|
||||
If specified in both places, the command line version is used. Note that
|
||||
if you assign a volume ID, this is the name that will be used as the mount
|
||||
point used by the Solaris volume management system and the name that is
|
||||
assigned to the disc on a Windows or Mac platform.
|
||||
.TP
|
||||
.BI \-volset " ID
|
||||
Specifies the volset ID.
|
||||
This parameter can also be set in the file
|
||||
.B \&.mkisofsrc
|
||||
with VOLS=volset_id.
|
||||
If specified in both places, the command line version is used.
|
||||
.TP
|
||||
.BI \-volset-size " #
|
||||
Sets the volume set size to #.
|
||||
The volume set size is the number of CD's that are in a CD set.
|
||||
The
|
||||
.B \-volset-size
|
||||
option may be used to create CD's that are part of e.g. a Operation
|
||||
System installation set of CD's.
|
||||
The option
|
||||
.B \-volset-size
|
||||
must be specified before
|
||||
.B \-volset-seqno
|
||||
on each command line.
|
||||
.TP
|
||||
.BI \-volset-seqno " #
|
||||
Sets the volume set sequence number to #.
|
||||
The volume set sequence number is the index number of the current
|
||||
CD in a CD set.
|
||||
The option
|
||||
.B \-volset-size
|
||||
must be specified before
|
||||
.B \-volset-seqno
|
||||
on each command line.
|
||||
.TP
|
||||
.B \-v
|
||||
Verbose execution.
|
||||
.TP
|
||||
.BI \-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
|
||||
.sp
|
||||
NOTE: The \-m and \-x option description should both be updated, they are wrong.
|
||||
Both now work identical and use filename globbing. A file is exluded if either
|
||||
the last component matches or the whole path matches.
|
||||
.TP
|
||||
.B \-z
|
||||
Generate special SUSP records for transparently compressed files. This is
|
||||
only of use and interest for hosts that support transparent decompression.
|
||||
This is an experimental feature, and no hosts yet support this, but there
|
||||
are ALPHA patches for Linux that can make use of this feature.
|
||||
.SH CONFIGURATION
|
||||
.B mkisofs
|
||||
looks for the
|
||||
.B \&.mkisofsrc
|
||||
file,
|
||||
first in the current working directory,
|
||||
then in the user's home directory,
|
||||
and then in the directory in which the
|
||||
.B mkisofs
|
||||
binary is stored. This file is assumed to contain a series of lines
|
||||
of the form
|
||||
.BI TAG= value,
|
||||
and in this way you can specify certain options.
|
||||
The case of the tag is not significant.
|
||||
Some fields in the volume header
|
||||
are not settable on the command line, but can be altered through this
|
||||
facility.
|
||||
Comments may be placed in this file,
|
||||
using lines which start with a hash (#) character.
|
||||
.TP
|
||||
.B APPI
|
||||
The application identifier
|
||||
should describe the application that will be on the disc.
|
||||
There is space on the disc for 128 characters of information.
|
||||
May be overridden using the
|
||||
.B \-A
|
||||
command line option.
|
||||
.TP
|
||||
.B COPY
|
||||
The copyright information,
|
||||
often the name of a file on the disc containing the copyright notice.
|
||||
There is space in the disc for 37 characters of information.
|
||||
May be overridden using the
|
||||
.B \-copyright
|
||||
command line option.
|
||||
.TP
|
||||
.B ABST
|
||||
The abstract information,
|
||||
often the name of a file on the disc containing an abstract.
|
||||
There is space in the disc for 37 characters of information.
|
||||
May be overridden using the
|
||||
.B \-abstract
|
||||
command line option.
|
||||
.TP
|
||||
.B BIBL
|
||||
The bibliographic information,
|
||||
often the name of a file on the disc containing a bibliography.
|
||||
There is space in the disc for 37 characters of information.
|
||||
May be overridden using the
|
||||
.B \-bilio
|
||||
command line option.
|
||||
.TP
|
||||
.B PREP
|
||||
This should describe the preparer of the CDROM,
|
||||
usually with a mailing address and phone number.
|
||||
There is space on the disc for 128 characters of information.
|
||||
May be overridden using the
|
||||
.B \-p
|
||||
command line option.
|
||||
.TP
|
||||
.B PUBL
|
||||
This should describe the publisher of the CDROM,
|
||||
usually with a mailing address and phone number.
|
||||
There is space on the disc for 128 characters of information.
|
||||
May be overridden using the
|
||||
.B \-P
|
||||
command line option.
|
||||
.TP
|
||||
.B SYSI
|
||||
The System Identifier.
|
||||
There is space on the disc for 32 characters of information.
|
||||
May be overridden using the
|
||||
.B \-sysid
|
||||
command line option.
|
||||
.TP
|
||||
.B VOLI
|
||||
The Volume Identifier.
|
||||
There is space on the disc for 32 characters of information.
|
||||
May be overridden using the
|
||||
.B \-V
|
||||
command line option.
|
||||
.TP
|
||||
.B VOLS
|
||||
The Volume Set Name.
|
||||
There is space on the disc for 128 characters of information.
|
||||
May be overridden using the
|
||||
.B \-volset
|
||||
command line option.
|
||||
.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@gnu.ai.mit.edu> or <eric@andante.jic.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
|
||||
Some sort of gui interface.
|
||||
.SH AVAILABILITY
|
||||
.B mkisofs
|
||||
is available for anonymous ftp from tsx-11.mit.edu in
|
||||
/pub/linux/packages/mkisofs and many other mirror sites.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,532 @@
|
|||
/*
|
||||
* 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. */
|
||||
|
||||
/*
|
||||
* Id: mkisofs.h,v 1.4 2015/09/09 20:02:31 miod Exp
|
||||
*/
|
||||
|
||||
/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 12/3/99 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <prototyp.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
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NON_UNIXFS
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(HAVE_DIRENT_H)
|
||||
# include <dirent.h>
|
||||
# define NAMLEN(dirent) strlen((dirent)->d_name)
|
||||
#else
|
||||
# define dirent direct
|
||||
# define NAMLEN(dirent) (dirent)->d_namlen
|
||||
# if defined(HAVE_SYS_NDIR_H)
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if defined(HAVE_SYS_DIR_H)
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if defined(HAVE_NDIR_H)
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_STRING_H)
|
||||
#include <string.h>
|
||||
#else
|
||||
#if defined(HAVE_STRINGS_H)
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#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"
|
||||
#ifdef APPLE_HYB
|
||||
#include <mactypes.h>
|
||||
#include <hfs.h>
|
||||
struct hfs_info {
|
||||
hfsdirent hfs_ent;
|
||||
char *keyname;
|
||||
struct hfs_info *next;
|
||||
};
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
struct directory_entry{
|
||||
struct directory_entry * next;
|
||||
struct directory_entry * jnext;
|
||||
struct iso_directory_record isorec;
|
||||
unsigned int starting_block;
|
||||
unsigned int size;
|
||||
unsigned short priority;
|
||||
unsigned char jreclen; /* Joliet record len */
|
||||
char * name;
|
||||
char * table;
|
||||
char * whole_name;
|
||||
struct directory * filedir;
|
||||
struct directory_entry * parent_rec;
|
||||
unsigned int de_flags;
|
||||
ino_t inode; /* Used in the hash table */
|
||||
dev_t dev; /* Used in the hash table */
|
||||
unsigned char * rr_attributes;
|
||||
unsigned int rr_attr_size;
|
||||
unsigned int total_rr_attr_size;
|
||||
unsigned int got_rr_name;
|
||||
#ifdef APPLE_HYB
|
||||
struct directory_entry * assoc; /* entry has a resource fork */
|
||||
hfsdirent *hfs_ent; /* HFS parameters */
|
||||
unsigned int hfs_off; /* offset to real start of fork */
|
||||
unsigned int hfs_type; /* type of HFS Unix file */
|
||||
#endif /* APPLE_HYB */
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This structure is used to control the output of fragments to the cdrom
|
||||
* image. Everything that will be written to the output image will eventually
|
||||
* go through this structure. There are two pieces - first is the sizing where
|
||||
* we establish extent numbers for everything, and the second is when we actually
|
||||
* generate the contents and write it to the output image.
|
||||
*
|
||||
* This makes it trivial to extend mkisofs to write special things in the image.
|
||||
* All you need to do is hook an additional structure in the list, and the rest
|
||||
* works like magic.
|
||||
*
|
||||
* The three passes each do the following:
|
||||
*
|
||||
* The 'size' pass determines the size of each component and assigns the extent number
|
||||
* for that component.
|
||||
*
|
||||
* The 'generate' pass will adjust the contents and pointers as required now that extent
|
||||
* numbers are assigned. In some cases, the contents of the record are also generated.
|
||||
*
|
||||
* The 'write' pass actually writes the data to the disc.
|
||||
*/
|
||||
struct output_fragment
|
||||
{
|
||||
struct output_fragment * of_next;
|
||||
#ifdef __STDC__
|
||||
int (*of_size)(int);
|
||||
int (*of_generate)(void);
|
||||
int (*of_write)(FILE *);
|
||||
#else
|
||||
int (*of_size)();
|
||||
int (*of_generate)();
|
||||
int (*of_write)();
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct output_fragment * out_list;
|
||||
extern struct output_fragment * out_tail;
|
||||
|
||||
extern struct output_fragment padblock_desc;
|
||||
extern struct output_fragment voldesc_desc;
|
||||
extern struct output_fragment joliet_desc;
|
||||
extern struct output_fragment torito_desc;
|
||||
extern struct output_fragment end_vol;
|
||||
extern struct output_fragment pathtable_desc;
|
||||
extern struct output_fragment jpathtable_desc;
|
||||
extern struct output_fragment dirtree_desc;
|
||||
extern struct output_fragment dirtree_clean;
|
||||
extern struct output_fragment jdirtree_desc;
|
||||
extern struct output_fragment extension_desc;
|
||||
extern struct output_fragment files_desc;
|
||||
|
||||
/*
|
||||
* This structure describes one complete directory. It has pointers
|
||||
* to other directories in the overall tree so that it is clear where
|
||||
* this directory lives in the tree, and it also must contain pointers
|
||||
* to the contents of the directory. Note that subdirectories of this
|
||||
* directory exist twice in this stucture. Once in the subdir chain,
|
||||
* and again in the contents chain.
|
||||
*/
|
||||
struct directory{
|
||||
struct directory * next; /* Next directory at same level as this one */
|
||||
struct directory * subdir; /* First subdirectory in this directory */
|
||||
struct directory * parent;
|
||||
struct directory_entry * contents;
|
||||
struct directory_entry * jcontents;
|
||||
struct directory_entry * self;
|
||||
char * whole_name; /* Entire path */
|
||||
char * de_name; /* Entire path */
|
||||
unsigned int ce_bytes; /* Number of bytes of CE entries reqd for this dir */
|
||||
unsigned int depth;
|
||||
unsigned int size;
|
||||
unsigned int extent;
|
||||
unsigned int jsize;
|
||||
unsigned int jextent;
|
||||
unsigned short path_index;
|
||||
unsigned short jpath_index;
|
||||
unsigned short dir_flags;
|
||||
unsigned short dir_nlink;
|
||||
#ifdef APPLE_HYB
|
||||
hfsdirent *hfs_ent; /* HFS parameters */
|
||||
struct hfs_info *hfs_info; /* list of info for all entries in dir */
|
||||
#endif /* APPLE_HYB */
|
||||
};
|
||||
|
||||
struct deferred{
|
||||
struct deferred * next;
|
||||
unsigned int starting_block;
|
||||
char * name;
|
||||
struct directory * filedir;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
extern int goof;
|
||||
extern struct directory * root;
|
||||
extern struct directory * reloc_dir;
|
||||
extern unsigned int next_extent;
|
||||
extern unsigned int last_extent;
|
||||
extern unsigned int last_extent_written;
|
||||
extern unsigned int session_start;
|
||||
|
||||
extern unsigned int path_table_size;
|
||||
extern unsigned int path_table[4];
|
||||
extern unsigned int path_blocks;
|
||||
extern char * path_table_l;
|
||||
extern char * path_table_m;
|
||||
|
||||
extern unsigned int jpath_table_size;
|
||||
extern unsigned int jpath_table[4];
|
||||
extern unsigned int jpath_blocks;
|
||||
extern char * jpath_table_l;
|
||||
extern char * jpath_table_m;
|
||||
|
||||
extern struct iso_directory_record root_record;
|
||||
extern struct iso_directory_record jroot_record;
|
||||
|
||||
extern int use_eltorito;
|
||||
extern int use_RockRidge;
|
||||
extern int use_Joliet;
|
||||
extern int rationalize;
|
||||
extern int follow_links;
|
||||
extern int verbose;
|
||||
extern int all_files;
|
||||
extern int generate_tables;
|
||||
extern int print_size;
|
||||
extern int split_output;
|
||||
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 split_SL_component;
|
||||
extern int split_SL_field;
|
||||
#ifdef APPLE_HYB
|
||||
extern int apple_hyb; /* create HFS hybrid */
|
||||
extern int apple_ext; /* use Apple extensions */
|
||||
extern int apple_both; /* common flag (for above) */
|
||||
extern int hfs_extra; /* extra ISO extents (hfs_ce_size) */
|
||||
extern hce_mem *hce; /* libhfs/mkisofs extras */
|
||||
extern int mac_name; /* use Mac name for ISO9660/Joliet/RR */
|
||||
extern int create_dt; /* create the Desktp files */
|
||||
extern char *hfs_boot_file; /* name of HFS boot file */
|
||||
extern char *magic_file; /* magic file for CREATOR/TYPE matching */
|
||||
extern int hfs_last; /* order in which to process map/magic files */
|
||||
extern char *deftype; /* default Apple TYPE */
|
||||
extern char *defcreator; /* default Apple CREATOR */
|
||||
extern char *trans_tbl; /* translation table name */
|
||||
extern int gen_pt; /* generate HFS partition table */
|
||||
extern char *autoname; /* Autostart filename */
|
||||
extern int bsize; /* Apple File Exchange block size */
|
||||
extern char *hfs_volume_id; /* HFS volume ID */
|
||||
#define ASSOC_FLAG 4 /* ISO flag for "associated" file */
|
||||
#define MAP_LAST 1 /* process magic then map file */
|
||||
#define MAG_LAST 2 /* process map then magic file */
|
||||
extern char *hfs_bless; /* name of folder to 'bless' (System Folder) */
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
/* tree.c */
|
||||
extern int DECL(stat_filter, (char *, struct stat *));
|
||||
extern int DECL(lstat_filter, (char *, struct stat *));
|
||||
extern int DECL(sort_tree,(struct directory *));
|
||||
extern struct directory *
|
||||
DECL(find_or_create_directory,(struct directory *, const char *,
|
||||
struct directory_entry * self, int));
|
||||
extern void DECL (finish_cl_pl_entries, (void));
|
||||
extern int DECL(scan_directory_tree,(struct directory * this_dir,
|
||||
char * path,
|
||||
struct directory_entry * self));
|
||||
#ifdef APPLE_HYB
|
||||
extern int DECL(insert_file_entry,(struct directory *, char *,
|
||||
char *, int));
|
||||
#else
|
||||
extern int DECL(insert_file_entry,(struct directory *, char *,
|
||||
char *));
|
||||
#endif /* APPLE_HYB */
|
||||
extern void DECL(generate_iso9660_directories,(struct directory *, FILE*));
|
||||
extern void DECL(dump_tree,(struct directory * node));
|
||||
extern struct directory_entry * DECL(search_tree_file, (struct
|
||||
directory * node,char * filename));
|
||||
extern void DECL(update_nlink_field,(struct directory * node));
|
||||
extern void DECL (init_fstatbuf, (void));
|
||||
extern struct stat root_statbuf;
|
||||
|
||||
/* eltorito.c */
|
||||
extern void DECL(init_boot_catalog, (const char * path ));
|
||||
extern void DECL(get_torito_desc, (struct eltorito_boot_descriptor * path ));
|
||||
|
||||
/* write.c */
|
||||
extern int DECL(get_733,(char *));
|
||||
extern int DECL(isonum_733,(unsigned char *));
|
||||
extern void DECL(set_723,(char *, unsigned int));
|
||||
extern void DECL(set_731,(char *, unsigned int));
|
||||
extern void DECL(set_721,(char *, unsigned int));
|
||||
extern void DECL(set_733,(char *, unsigned int));
|
||||
extern int DECL(sort_directory,(struct directory_entry **));
|
||||
extern void DECL(generate_one_directory,(struct directory *, FILE*));
|
||||
extern void DECL(memcpy_max, (char *, char *, int));
|
||||
extern int DECL(oneblock_size, (int starting_extent));
|
||||
extern struct iso_primary_descriptor vol_desc;
|
||||
extern void DECL(xfwrite, (void * buffer, int count, int size, FILE * file));
|
||||
extern void DECL(set_732, (char * pnt, unsigned int i));
|
||||
extern void DECL(set_722, (char * pnt, unsigned int i));
|
||||
extern void DECL(outputlist_insert, (struct output_fragment * frag));
|
||||
|
||||
/* multi.c */
|
||||
|
||||
extern FILE * in_image;
|
||||
extern struct iso_directory_record *
|
||||
DECL(merge_isofs,(char * path));
|
||||
|
||||
extern int DECL(free_mdinfo, (struct directory_entry **, int len));
|
||||
|
||||
extern struct directory_entry **
|
||||
DECL(read_merging_directory,(struct iso_directory_record *, int*));
|
||||
extern void
|
||||
DECL(merge_remaining_entries, (struct directory *,
|
||||
struct directory_entry **, int));
|
||||
extern int
|
||||
DECL(merge_previous_session, (struct directory *,
|
||||
struct iso_directory_record *));
|
||||
|
||||
extern int DECL(get_session_start, (int *));
|
||||
|
||||
/* joliet.c */
|
||||
int DECL(joliet_sort_tree, (struct directory * node));
|
||||
|
||||
/* match.c */
|
||||
extern int DECL(matches, (char *));
|
||||
#ifdef APPLE_HYB
|
||||
extern int DECL(add_match, (char *));
|
||||
#else
|
||||
extern void DECL(add_match, (char *));
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
/* files.c */
|
||||
struct dirent * DECL(readdir_add_files, (char **, char *, DIR *));
|
||||
|
||||
/* */
|
||||
|
||||
extern int DECL(iso9660_file_length,(const char* name,
|
||||
struct directory_entry * sresult, int flag));
|
||||
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));
|
||||
#ifdef APPLE_HYB
|
||||
extern void flush_hash();
|
||||
#endif /* APPLE_HYB */
|
||||
extern void DECL(add_directory_hash,(dev_t, ino_t));
|
||||
extern struct file_hash * DECL(find_directory_hash,(dev_t, ino_t));
|
||||
extern void DECL (flush_file_hash, (void));
|
||||
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 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 int DECL(check_prev_session, (struct directory_entry **, int len,
|
||||
struct directory_entry *,
|
||||
struct stat *,
|
||||
struct stat *,
|
||||
struct directory_entry **));
|
||||
|
||||
#ifdef USE_SCG
|
||||
/* scsi.c */
|
||||
#ifdef __STDC__
|
||||
extern int readsecs(int startsecno, void *buffer, int sectorcount);
|
||||
extern int scsidev_open(char *path);
|
||||
#else
|
||||
extern int readsecs();
|
||||
extern int scsidev_open();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern char * extension_record;
|
||||
extern int extension_record_extent;
|
||||
extern int n_data_extents;
|
||||
|
||||
/* These are a few goodies that can be specified on the command line, and are
|
||||
filled into the root record */
|
||||
|
||||
extern char * preparer;
|
||||
extern char * publisher;
|
||||
extern char * copyright;
|
||||
extern char * biblio;
|
||||
extern char * abstract;
|
||||
extern char * appid;
|
||||
extern char * volset_id;
|
||||
extern char * system_id;
|
||||
extern char * volume_id;
|
||||
extern char * boot_catalog;
|
||||
extern char * boot_image;
|
||||
extern int volume_set_size;
|
||||
extern int volume_sequence_number;
|
||||
|
||||
extern void * DECL(e_malloc,(size_t));
|
||||
|
||||
|
||||
#define SECTOR_SIZE (2048)
|
||||
#define ROUND_UP(X) ((X + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
|
||||
#ifdef APPLE_HYB
|
||||
#define V_ROUND_UP(X,Y) (((X + (Y - 1)) / Y) * Y)
|
||||
#define H_ROUND_UP(X) ROUND_UP(((X)*HFS_BLOCKSZ))
|
||||
/* ISO blocks == 2048, HFS blocks == 512 */
|
||||
#define BLK_CONV (SECTOR_SIZE/HFS_BLOCKSZ)
|
||||
|
||||
#define USE_MAC_NAME(N,E) ((N) && ((E)->hfs_ent != NULL) && (E)->hfs_type)
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
#define NEED_RE 1
|
||||
#define NEED_PL 2
|
||||
#define NEED_CL 4
|
||||
#define NEED_CE 8
|
||||
#define NEED_SP 16
|
||||
|
||||
#define PREV_SESS_DEV (sizeof(dev_t) >= 4 ? 0x7ffffffd : 0x7ffd)
|
||||
#define TABLE_INODE (sizeof(ino_t) >= 8 ? 0x7ffffffffffffffeLL : 0x7ffffffe)
|
||||
#define UNCACHED_INODE (sizeof(ino_t) >= 8 ? 0x7fffffffffffffffLL : 0x7fffffff)
|
||||
#define UNCACHED_DEVICE (sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff)
|
||||
|
||||
#ifdef VMS
|
||||
#define STAT_INODE(X) (X.st_ino[0])
|
||||
#define PATH_SEPARATOR ']'
|
||||
#define SPATH_SEPARATOR ""
|
||||
#else
|
||||
#define STAT_INODE(X) (X.st_ino)
|
||||
#define PATH_SEPARATOR '/'
|
||||
#define SPATH_SEPARATOR "/"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When using multi-session, indicates that we can reuse the
|
||||
* TRANS.TBL information for this directory entry. If this flag
|
||||
* is set for all entries in a directory, it means we can just
|
||||
* reuse the TRANS.TBL and not generate a new one.
|
||||
*/
|
||||
#define SAFE_TO_REUSE_TABLE_ENTRY 0x01
|
||||
#define DIR_HAS_DOT 0x02
|
||||
#define DIR_HAS_DOTDOT 0x04
|
||||
#define INHIBIT_JOLIET_ENTRY 0x08
|
||||
#define INHIBIT_RR_ENTRY 0x10
|
||||
#define RELOCATED_DIRECTORY 0x20
|
||||
#define INHIBIT_ISO9660_ENTRY 0x40
|
||||
|
||||
/*
|
||||
* Volume sequence number to use in all of the iso directory records.
|
||||
*/
|
||||
#define DEF_VSN 1
|
||||
|
||||
/*
|
||||
* Make sure we have a definition for this. If not, take a very conservative
|
||||
* guess. From what I can tell SunOS is the only one with this trouble.
|
||||
*/
|
||||
#ifndef NAME_MAX
|
||||
#ifdef FILENAME_MAX
|
||||
#define NAME_MAX FILENAME_MAX
|
||||
#else
|
||||
#define NAME_MAX 128
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,44 @@
|
|||
# Id: mkisofs.spec,v 1.1 2000/10/10 20:40:19 beck Exp
|
||||
Summary: Creates a ISO9660 filesystem image
|
||||
Name: mkisofs
|
||||
Version: 1.12b5
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Utilities/System
|
||||
Source: tsx-11.mit.edu:/pub/linux/packages/mkisofs/mkisofs-1.12b5.tar.gz
|
||||
|
||||
%description
|
||||
This is the mkisofs package. It is used to create ISO 9660
|
||||
file system images for creating CD-ROMs. Now includes support
|
||||
for making bootable "El Torito" CD-ROMs.
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make
|
||||
|
||||
%install
|
||||
make install
|
||||
strip /usr/bin/mkisofs
|
||||
|
||||
%changelog
|
||||
|
||||
* Tue Feb 25 1997 Michael Fulbright <msf@redhat.com>
|
||||
|
||||
Updated to 1.10b7.
|
||||
|
||||
* Wed Feb 12 1997 Michael Fulbright <msf@redhat.com>
|
||||
|
||||
Updated to 1.10b3.
|
||||
|
||||
* Wed Feb 12 1997 Michael Fulbright <msf@redhat.com>
|
||||
|
||||
Added %doc line to spec file (was missing all docs before).
|
||||
|
||||
%files
|
||||
%doc COPYING ChangeLog README README.eltorito TODO
|
||||
/usr/bin/mkisofs
|
||||
/usr/man/man8/mkisofs.8
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,394 @@
|
|||
/*
|
||||
* File name.c - map full Unix file names to unique 8.3 names that
|
||||
* would be valid on DOS.
|
||||
*
|
||||
|
||||
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 "mkisofs.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
extern int allow_leading_dots;
|
||||
|
||||
/*
|
||||
* Function: iso9660_file_length
|
||||
*
|
||||
* Purpose: Map file name to 8.3 format, return length
|
||||
* of result.
|
||||
*
|
||||
* Arguments: name file name we need to map.
|
||||
* sresult directory entry structure to contain mapped name.
|
||||
* dirflag flag indicating whether this is a directory or not.
|
||||
*
|
||||
* Notes: This procedure probably needs to be rationalized somehow.
|
||||
* New options to affect the behavior of this function
|
||||
* would also be nice to have.
|
||||
*/
|
||||
int FDECL3(iso9660_file_length,
|
||||
const char*, name,
|
||||
struct directory_entry *, sresult,
|
||||
int, dirflag)
|
||||
{
|
||||
char * c;
|
||||
int chars_after_dot = 0;
|
||||
int chars_before_dot = 0;
|
||||
int current_length = 0;
|
||||
int extra = 0;
|
||||
int ignore = 0;
|
||||
char * last_dot;
|
||||
const char * pnt;
|
||||
int priority = 32767;
|
||||
char * result;
|
||||
int seen_dot = 0;
|
||||
int seen_semic = 0;
|
||||
int tildes = 0;
|
||||
|
||||
result = sresult->isorec.name;
|
||||
|
||||
/*
|
||||
* For the '.' entry, generate the correct record, and return
|
||||
* 1 for the length.
|
||||
*/
|
||||
if(strcmp(name,".") == 0)
|
||||
{
|
||||
if(result)
|
||||
{
|
||||
*result = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* For the '..' entry, generate the correct record, and return
|
||||
* 1 for the length.
|
||||
*/
|
||||
if(strcmp(name,"..") == 0)
|
||||
{
|
||||
if(result)
|
||||
{
|
||||
*result++ = 1;
|
||||
*result++ = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now scan the directory one character at a time, and figure out
|
||||
* what to do.
|
||||
*/
|
||||
pnt = name;
|
||||
|
||||
/*
|
||||
* Find the '.' that we intend to use for the extension. Usually this
|
||||
* is the last dot, but if we have . followed by nothing or a ~, we
|
||||
* would consider this to be unsatisfactory, and we keep searching.
|
||||
*/
|
||||
last_dot = strrchr (pnt,'.');
|
||||
if( (last_dot != NULL)
|
||||
&& ( (last_dot[1] == '~')
|
||||
|| (last_dot[1] == '\0')) )
|
||||
{
|
||||
c = last_dot;
|
||||
*c = '\0';
|
||||
last_dot = strrchr (pnt,'.');
|
||||
*c = '.';
|
||||
}
|
||||
|
||||
while(*pnt)
|
||||
{
|
||||
#ifdef VMS
|
||||
if( strcmp(pnt,".DIR;1") == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This character indicates a Unix style of backup file
|
||||
* generated by some editors. Lower the priority of
|
||||
* the file.
|
||||
*/
|
||||
if(*pnt == '#')
|
||||
{
|
||||
priority = 1;
|
||||
pnt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* This character indicates a Unix style of backup file
|
||||
* generated by some editors. Lower the priority of
|
||||
* the file.
|
||||
*/
|
||||
if(*pnt == '~')
|
||||
{
|
||||
priority = 1;
|
||||
tildes++;
|
||||
pnt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* This might come up if we had some joker already try and put
|
||||
* iso9660 version numbers into the file names. This would be
|
||||
* a silly thing to do on a Unix box, but we check for it
|
||||
* anyways. If we see this, then we don't have to add our
|
||||
* own version number at the end.
|
||||
* UNLESS the ';' is part of the filename and no version
|
||||
* number is following. [VK]
|
||||
*/
|
||||
if(*pnt == ';')
|
||||
{
|
||||
/* [VK] */
|
||||
if (pnt[1] != '\0' && (pnt[1] < '0' || pnt[1] > '9'))
|
||||
{
|
||||
pnt++;
|
||||
ignore++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a name with multiple '.' characters, we ignore everything
|
||||
* after we have gotten the extension.
|
||||
*/
|
||||
if(ignore)
|
||||
{
|
||||
pnt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Spin past any iso9660 version number we might have.
|
||||
*/
|
||||
if(seen_semic)
|
||||
{
|
||||
if(*pnt >= '0' && *pnt <= '9')
|
||||
{
|
||||
*result++ = *pnt;
|
||||
}
|
||||
extra++;
|
||||
pnt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have full names, the names we generate will not
|
||||
* work on a DOS machine, since they are not guaranteed
|
||||
* to be 8.3. Nonetheless, in many cases this is a useful
|
||||
* option. We still only allow one '.' character in the
|
||||
* name, however.
|
||||
*/
|
||||
if(full_iso9660_filenames)
|
||||
{
|
||||
/* Here we allow a more relaxed syntax. */
|
||||
if(*pnt == '.')
|
||||
{
|
||||
if (seen_dot)
|
||||
{
|
||||
ignore++;
|
||||
continue;
|
||||
}
|
||||
seen_dot++;
|
||||
}
|
||||
if(current_length < 30)
|
||||
{
|
||||
if(!isascii((unsigned char)*pnt))
|
||||
{
|
||||
*result++ = '_';
|
||||
}
|
||||
else
|
||||
{
|
||||
*result++ = (islower((unsigned char)*pnt) ? toupper((unsigned char)*pnt) : *pnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Dos style filenames. We really restrict the
|
||||
* names here.
|
||||
*/
|
||||
/* It would be nice to have .tar.gz transform to .tgz,
|
||||
* .ps.gz to .psz, ...
|
||||
*/
|
||||
if(*pnt == '.')
|
||||
{
|
||||
if (!chars_before_dot && !allow_leading_dots)
|
||||
{
|
||||
/* DOS can't read files with dot first */
|
||||
chars_before_dot++;
|
||||
if (result)
|
||||
{
|
||||
*result++ = '_'; /* Substitute underscore */
|
||||
}
|
||||
}
|
||||
else if( pnt != last_dot )
|
||||
{
|
||||
/*
|
||||
* If this isn't the dot that we use for the extension,
|
||||
* then change the character into a '_' instead.
|
||||
*/
|
||||
if(chars_before_dot < 8)
|
||||
{
|
||||
chars_before_dot++;
|
||||
if(result)
|
||||
{
|
||||
*result++ = '_';
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (seen_dot)
|
||||
{
|
||||
ignore++; continue;
|
||||
}
|
||||
if(result)
|
||||
{
|
||||
*result++ = '.';
|
||||
}
|
||||
seen_dot++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (seen_dot && (chars_after_dot < 3) && ++chars_after_dot)
|
||||
|| (!seen_dot && (chars_before_dot < 8) && ++chars_before_dot) )
|
||||
{
|
||||
if(result)
|
||||
{
|
||||
switch (*pnt)
|
||||
{
|
||||
default:
|
||||
if(!isascii((unsigned char)*pnt))
|
||||
{
|
||||
*result++ = '_';
|
||||
}
|
||||
else
|
||||
{
|
||||
*result++ = islower((unsigned char)*pnt) ? toupper((unsigned char)*pnt) : *pnt;
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
* Descriptions of DOS's 'Parse Filename'
|
||||
* (function 29H) describes V1 and V2.0+
|
||||
* separator and terminator characters.
|
||||
* These characters in a DOS name make
|
||||
* the file visible but un-manipulable
|
||||
* (all useful operations error off.
|
||||
*/
|
||||
/* separators */
|
||||
case '+':
|
||||
case '=':
|
||||
case '%': /* not legal DOS filename */
|
||||
case ':':
|
||||
case ';': /* already handled */
|
||||
case '.': /* already handled */
|
||||
case ',': /* already handled */
|
||||
case '\t':
|
||||
case ' ':
|
||||
/* V1 only separators */
|
||||
case '/':
|
||||
case '"':
|
||||
case '[':
|
||||
case ']':
|
||||
/* terminators */
|
||||
case '>':
|
||||
case '<':
|
||||
case '|':
|
||||
/* Hmm - what to do here? Skip?
|
||||
* Win95 looks like it substitutes '_'
|
||||
*/
|
||||
*result++ = '_';
|
||||
break;
|
||||
} /* switch (*pnt) */
|
||||
} /* if (result) */
|
||||
} /* if (chars_{after,before}_dot) ... */
|
||||
} /* else *pnt == '.' */
|
||||
} /* else DOS file names */
|
||||
current_length++;
|
||||
pnt++;
|
||||
} /* while (*pnt) */
|
||||
|
||||
/*
|
||||
* OK, that wraps up the scan of the name. Now tidy up a few other
|
||||
* things.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Look for emacs style of numbered backups, like foo.c.~3~. If
|
||||
* we see this, convert the version number into the priority
|
||||
* number. In case of name conflicts, this is what would end
|
||||
* up being used as the 'extension'.
|
||||
*/
|
||||
if(tildes == 2)
|
||||
{
|
||||
int prio1 = 0;
|
||||
pnt = name;
|
||||
while (*pnt && *pnt != '~')
|
||||
{
|
||||
pnt++;
|
||||
}
|
||||
if (*pnt)
|
||||
{
|
||||
pnt++;
|
||||
}
|
||||
while(*pnt && *pnt != '~')
|
||||
{
|
||||
prio1 = 10*prio1 + *pnt - '0';
|
||||
pnt++;
|
||||
}
|
||||
priority = prio1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is not a directory, force a '.' in case we haven't
|
||||
* seen one, and add a version number if we haven't seen one
|
||||
* of those either.
|
||||
*/
|
||||
if (!dirflag)
|
||||
{
|
||||
if (!seen_dot && !omit_period)
|
||||
{
|
||||
if (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);
|
||||
}
|
|
@ -0,0 +1,655 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef VMS
|
||||
#if defined(MAJOR_IN_SYSMACROS)
|
||||
#include <sys/sysmacros.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#if defined(MAJOR_IN_MKDEV)
|
||||
#include <sys/types.h>
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
|
||||
#include "mkisofs.h"
|
||||
#include "iso9660.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DOESNT_WORK
|
||||
|
||||
#ifdef NON_UNIXFS
|
||||
#define S_ISLNK(m) (0)
|
||||
#else
|
||||
#ifndef S_ISLNK
|
||||
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include <statdefs.h>
|
||||
#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 APPLE_HYB
|
||||
#define AA_SIZE 14 /* size of Apple extension */
|
||||
#endif /* APPLE_HYB */
|
||||
#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;
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
/* if we are using the HFS name, we don't want the '/' character */
|
||||
static void
|
||||
rstrncpy(char *t, char *f, int c)
|
||||
{
|
||||
while (c-- && *f) {
|
||||
switch (*f) {
|
||||
case '/':
|
||||
*t = '_';
|
||||
break;
|
||||
default:
|
||||
*t = *f;
|
||||
break;
|
||||
}
|
||||
t++; f++;
|
||||
}
|
||||
}
|
||||
#endif /* APPLE HYB */
|
||||
|
||||
static void add_CE_entry __PR((void));
|
||||
|
||||
static void 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;
|
||||
|
||||
/* no need to fill in the RR stuff if we won't see the file */
|
||||
if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
|
||||
return 0;
|
||||
|
||||
/* Obtain the amount of space that is currently used for the directory
|
||||
record. Assume max for name, since name conflicts may cause us
|
||||
to rename the file later on */
|
||||
currlen = sizeof(s_entry->isorec);
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
/* if we have regular file, then add Apple extensions */
|
||||
if (S_ISREG(lstatbuf->st_mode) && apple_ext && s_entry->hfs_ent) {
|
||||
Rock[ipnt++] ='A'; /* AppleSignature */
|
||||
Rock[ipnt++] ='A';
|
||||
Rock[ipnt++] = AA_SIZE; /* includes AppleSignature bytes */
|
||||
Rock[ipnt++] = 0x02; /* SystemUseID */
|
||||
Rock[ipnt++] = s_entry->hfs_ent->type[0];
|
||||
Rock[ipnt++] = s_entry->hfs_ent->type[1];
|
||||
Rock[ipnt++] = s_entry->hfs_ent->type[2];
|
||||
Rock[ipnt++] = s_entry->hfs_ent->type[3];
|
||||
Rock[ipnt++] = s_entry->hfs_ent->creator[0];
|
||||
Rock[ipnt++] = s_entry->hfs_ent->creator[1];
|
||||
Rock[ipnt++] = s_entry->hfs_ent->creator[2];
|
||||
Rock[ipnt++] = s_entry->hfs_ent->creator[3];
|
||||
Rock[ipnt++] = (s_entry->hfs_ent->fdflags >> 8) & 0xff;
|
||||
Rock[ipnt++] = s_entry->hfs_ent->fdflags & 0xff;
|
||||
}
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
/* 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;
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
/* use the HFS name if it exists */
|
||||
if (USE_MAC_NAME(mac_name, s_entry)) {
|
||||
remain = strlen(s_entry->hfs_ent->name);
|
||||
npnt = s_entry->hfs_ent->name;
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
|
||||
remain = strlen(name);
|
||||
npnt = name;
|
||||
#ifdef APPLE_HYB
|
||||
}
|
||||
#endif /* APPLE_HYB */
|
||||
|
||||
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);
|
||||
#ifdef APPLE_HYB
|
||||
/* filter out any '/' character in HFS filename */
|
||||
if (USE_MAC_NAME(mac_name, s_entry))
|
||||
rstrncpy((char *)&Rock[ipnt], npnt, use);
|
||||
else
|
||||
#endif /* APPLE_HYB */
|
||||
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 defined(MAJOR_IN_SYSMACROS) || defined(MAJOR_IN_MKDEV)
|
||||
set_733((char*)Rock + ipnt, major(lstatbuf->st_rdev ));
|
||||
ipnt += 8;
|
||||
set_733((char*)Rock + ipnt, minor(lstatbuf->st_rdev));
|
||||
ipnt += 8;
|
||||
#else
|
||||
/*
|
||||
* If we don't have sysmacros.h, then we have to guess as to how
|
||||
* best to pick apart the device number for major/minor.
|
||||
* Note: this may very well be wrong for many systems, so
|
||||
* it is always best to use the major/minor macros if the
|
||||
* system supports it.
|
||||
*/
|
||||
if(sizeof(dev_t) <= 2) {
|
||||
set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8));
|
||||
ipnt += 8;
|
||||
set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xff);
|
||||
ipnt += 8;
|
||||
}
|
||||
else if(sizeof(dev_t) <= 4) {
|
||||
set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8) >> 8);
|
||||
ipnt += 8;
|
||||
set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xffff);
|
||||
ipnt += 8;
|
||||
}
|
||||
else {
|
||||
set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 16) >> 16);
|
||||
ipnt += 8;
|
||||
set_733((char*)Rock + ipnt, lstatbuf->st_rdev);
|
||||
ipnt += 8;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
/*
|
||||
* Check for and symbolic links. VMS does not have these.
|
||||
*/
|
||||
if (S_ISLNK(lstatbuf->st_mode)){
|
||||
int lenpos, lenval, j0, j1;
|
||||
int nchar;
|
||||
unsigned char * cpnt, *cpnt1;
|
||||
nchar = readlink(whole_name, (char *)symlink_buff, sizeof(symlink_buff)-1);
|
||||
symlink_buff[nchar < 0 ? 0 : nchar] = 0;
|
||||
nchar = strlen((char *) symlink_buff);
|
||||
set_733(s_entry->isorec.size, 0);
|
||||
cpnt = &symlink_buff[0];
|
||||
flagval |= (1<<2);
|
||||
|
||||
if (! split_SL_field)
|
||||
{
|
||||
int sl_bytes = 0;
|
||||
for (cpnt1 = cpnt; *cpnt1 != '\0'; cpnt1++)
|
||||
{
|
||||
if (*cpnt1 == '/')
|
||||
{
|
||||
sl_bytes += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
sl_bytes += 1;
|
||||
}
|
||||
}
|
||||
if (sl_bytes > 250)
|
||||
{
|
||||
/*
|
||||
* the symbolic link won't fit into one SL System Use Field
|
||||
* print an error message and continue with splited one
|
||||
*/
|
||||
fprintf(stderr,"symbolic link ``%s'' to long for one SL System Use Field, splitting", cpnt);
|
||||
}
|
||||
if(MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes)) add_CE_entry();
|
||||
}
|
||||
|
||||
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(split_SL_component ? MAYBE_ADD_CE_ENTRY(6) :
|
||||
MAYBE_ADD_CE_ENTRY(6 + strlen ((char *) cpnt)))
|
||||
{
|
||||
add_CE_entry();
|
||||
if(cpnt1)
|
||||
{
|
||||
*cpnt1 = '/';
|
||||
nchar++;
|
||||
cpnt1 = NULL; /* A kluge so that we can restart properly */
|
||||
}
|
||||
break;
|
||||
}
|
||||
j0 = strlen((char *) cpnt);
|
||||
while(j0) {
|
||||
j1 = j0;
|
||||
if(j1 > 0xf8) j1 = 0xf8;
|
||||
need_ce = 0;
|
||||
if(j1 + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
|
||||
j1 = reclimit - currlen - CE_SIZE - (ipnt - recstart);
|
||||
need_ce++;
|
||||
}
|
||||
Rock[ipnt++] = (j1 != j0 ? SL_CONTINUE : 0);
|
||||
Rock[ipnt++] = j1;
|
||||
strncpy((char *) Rock + ipnt, (char *) cpnt, j1);
|
||||
ipnt += j1;
|
||||
lenval += j1 + 2;
|
||||
cpnt += j1;
|
||||
nchar -= j1; /* Number we processed this time */
|
||||
j0 -= j1;
|
||||
if(need_ce) {
|
||||
add_CE_entry();
|
||||
if(cpnt1) {
|
||||
*cpnt1 = '/';
|
||||
nchar++;
|
||||
cpnt1 = NULL; /* A kluge so that we can restart properly */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
if(cpnt1) {
|
||||
cpnt = cpnt1 + 1;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
Rock[lenpos] = lenval;
|
||||
if(nchar) Rock[lenpos + 2] = SL_CONTINUE; /* We need another SL entry */
|
||||
} /* while nchar */
|
||||
} /* Is a symbolic link */
|
||||
/*
|
||||
* Add in the Rock Ridge TF time field
|
||||
*/
|
||||
if(MAYBE_ADD_CE_ENTRY(TF_SIZE)) add_CE_entry();
|
||||
Rock[ipnt++] ='T';
|
||||
Rock[ipnt++] ='F';
|
||||
Rock[ipnt++] = TF_SIZE;
|
||||
Rock[ipnt++] = SU_VERSION;
|
||||
#ifdef __QNX__
|
||||
Rock[ipnt++] = 0x0f;
|
||||
#else
|
||||
Rock[ipnt++] = 0x0e;
|
||||
#endif
|
||||
flagval |= (1<<7);
|
||||
#ifdef __QNX__
|
||||
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime);
|
||||
ipnt += 7;
|
||||
#endif
|
||||
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime);
|
||||
ipnt += 7;
|
||||
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime);
|
||||
ipnt += 7;
|
||||
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime);
|
||||
ipnt += 7;
|
||||
|
||||
/*
|
||||
* Add in the Rock Ridge RE time field
|
||||
*/
|
||||
if(deep_opt & NEED_RE){
|
||||
if(MAYBE_ADD_CE_ENTRY(RE_SIZE)) add_CE_entry();
|
||||
Rock[ipnt++] ='R';
|
||||
Rock[ipnt++] ='E';
|
||||
Rock[ipnt++] = RE_SIZE;
|
||||
Rock[ipnt++] = SU_VERSION;
|
||||
flagval |= (1<<6);
|
||||
};
|
||||
/*
|
||||
* Add in the Rock Ridge PL record, if required.
|
||||
*/
|
||||
if(deep_opt & NEED_PL){
|
||||
if(MAYBE_ADD_CE_ENTRY(PL_SIZE)) add_CE_entry();
|
||||
Rock[ipnt++] ='P';
|
||||
Rock[ipnt++] ='L';
|
||||
Rock[ipnt++] = PL_SIZE;
|
||||
Rock[ipnt++] = SU_VERSION;
|
||||
set_733((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, "rb");
|
||||
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, "rb");
|
||||
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 lipnt = 0;
|
||||
char * pnt;
|
||||
int len_id, len_des, len_src;
|
||||
|
||||
len_id = strlen(id);
|
||||
len_des = strlen(descriptor);
|
||||
len_src = strlen(source);
|
||||
Rock[lipnt++] ='E';
|
||||
Rock[lipnt++] ='R';
|
||||
Rock[lipnt++] = ER_SIZE + len_id + len_des + len_src;
|
||||
Rock[lipnt++] = 1;
|
||||
Rock[lipnt++] = len_id;
|
||||
Rock[lipnt++] = len_des;
|
||||
Rock[lipnt++] = len_src;
|
||||
Rock[lipnt++] = 1;
|
||||
|
||||
memcpy(Rock + lipnt, id, len_id);
|
||||
lipnt += len_id;
|
||||
|
||||
memcpy(Rock + lipnt, descriptor, len_des);
|
||||
lipnt += len_des;
|
||||
|
||||
memcpy(Rock + lipnt, source, len_src);
|
||||
lipnt += len_src;
|
||||
|
||||
if(lipnt > SECTOR_SIZE) {
|
||||
fprintf(stderr,"Extension record too long\n");
|
||||
exit(1);
|
||||
};
|
||||
pnt = (char *) e_malloc(SECTOR_SIZE);
|
||||
memset(pnt, 0, SECTOR_SIZE);
|
||||
memcpy(pnt, Rock, lipnt);
|
||||
*size = lipnt;
|
||||
return pnt;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,564 @@
|
|||
/*
|
||||
** volume.c: prepare HFS volume for mkhybrid
|
||||
**
|
||||
** James Pearson 17/7/97
|
||||
** modified JCP 29/7/97 to improve allocation sizes to cut
|
||||
** down on wasted space. Now uses the HFS "allocation" size rounded
|
||||
** up to the nearest 2048 bytes. Savings can be significant with
|
||||
** a large volume containing lots of smallish files.
|
||||
**
|
||||
** Updated for v1.12 - now uses the built in RELOCATED_DIRECTORY
|
||||
** flag for finding the real directory location JCP 8/1/97
|
||||
*/
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
|
||||
#include "config.h"
|
||||
#include "mkisofs.h"
|
||||
#include "volume.h"
|
||||
#include "write.h"
|
||||
#include <errno.h>
|
||||
|
||||
static hfsvol *vol_save = 0; /* used to "destroy" an HFS volume */
|
||||
|
||||
int DECL(copy_to_mac_vol, (hfsvol *, struct directory *));
|
||||
|
||||
/*
|
||||
** AlcSiz: find allocation size for given volume size
|
||||
*/
|
||||
int
|
||||
AlcSiz(int vlen)
|
||||
{
|
||||
int lpa, drAlBlkSiz;
|
||||
|
||||
/* code extracted from hfs_format() */
|
||||
lpa = 1 + vlen / 65536;
|
||||
drAlBlkSiz = lpa * HFS_BLOCKSZ;
|
||||
|
||||
/* now set our "allocation size" to the allocation block rounded
|
||||
up to the nearest SECTOR_SIZE (2048 bytes) */
|
||||
drAlBlkSiz = V_ROUND_UP(drAlBlkSiz, SECTOR_SIZE);
|
||||
|
||||
return(drAlBlkSiz);
|
||||
}
|
||||
|
||||
/*
|
||||
** XClpSiz: find the default size of the catalog/extent file
|
||||
*/
|
||||
int
|
||||
XClpSiz(int vlen)
|
||||
{
|
||||
int olpa, lpa, drNmAlBlks, drAlBlkSiz;
|
||||
int vbmsz, drXTClpSiz;
|
||||
|
||||
/* code extracted from hfs_format() */
|
||||
|
||||
/* get the lpa from our calculated allocation block size */
|
||||
drAlBlkSiz = AlcSiz(vlen);
|
||||
lpa = drAlBlkSiz/HFS_BLOCKSZ;
|
||||
|
||||
vbmsz = (vlen / lpa + 4095) / 4096;
|
||||
drNmAlBlks = (vlen - 5 - vbmsz) / lpa;
|
||||
drXTClpSiz = drNmAlBlks / 128 * drAlBlkSiz;
|
||||
|
||||
/* make allowances because we have possibly rounded up the
|
||||
allocation size */
|
||||
|
||||
/* get the "original" lpa " */
|
||||
olpa = 1 + vlen / 65536;
|
||||
|
||||
/* adjust size upwards */
|
||||
drXTClpSiz = (drXTClpSiz*lpa)/olpa;
|
||||
|
||||
/* round up to the nearest alloaction size */
|
||||
drXTClpSiz = V_ROUND_UP(drXTClpSiz, drAlBlkSiz);
|
||||
|
||||
return(drXTClpSiz);
|
||||
}
|
||||
|
||||
/*
|
||||
** get_vol_size: get the size of the volume including the extent/catalog
|
||||
*/
|
||||
int
|
||||
get_vol_size(int vblen)
|
||||
{
|
||||
int drXTClpSiz, drAlBlkSiz;
|
||||
int new_vblen;
|
||||
|
||||
/* try to estimate a "volume size" based on the code
|
||||
in hfs_format - we need the size of the catalog/extents
|
||||
and Desktop files included in the volume, as we add this
|
||||
to the end of the ISO volume */
|
||||
|
||||
drXTClpSiz = XClpSiz(vblen);
|
||||
drAlBlkSiz = AlcSiz(vblen);
|
||||
|
||||
/* catalog file is set at CTC times (default twice) the extents file
|
||||
size - hence the (ctc_size + 1) below. The Desktop starts of the
|
||||
same size as the "clump size" == 4 x drAlBlkSiz, plus a spare
|
||||
drAlBlkSiz for the alternative MDB */
|
||||
|
||||
new_vblen = vblen + ((hce->ctc_size + 1)*drXTClpSiz + 5*drAlBlkSiz)/HFS_BLOCKSZ;
|
||||
|
||||
return (new_vblen);
|
||||
}
|
||||
|
||||
/*
|
||||
** write_fork: "write" file data to the volume
|
||||
**
|
||||
** This is used to update the HFS file internal structures
|
||||
** but no data is actually written (it's trapped deep down in
|
||||
** libhfs).
|
||||
*/
|
||||
int
|
||||
write_fork(hfsfile *hfp, long tot)
|
||||
{
|
||||
char blk[HFS_BLOCKSZ];
|
||||
unsigned short start;
|
||||
long len;
|
||||
|
||||
len = tot;
|
||||
/* we need to know where this fork starts */
|
||||
start = hfs_get_drAllocPtr(hfp);
|
||||
|
||||
/* loop through the data a block at a time */
|
||||
while (len >= HFS_BLOCKSZ)
|
||||
{
|
||||
if(hfs_write(hfp, blk, HFS_BLOCKSZ) < 0)
|
||||
return(-1);
|
||||
len -= HFS_BLOCKSZ;
|
||||
}
|
||||
/* write out anything left */
|
||||
if (len)
|
||||
if(hfs_write(hfp, blk, len) < 0)
|
||||
return(-1);
|
||||
|
||||
/* set the start of the allocation search to be immediately
|
||||
after this fork */
|
||||
hfs_set_drAllocPtr(hfp, start, tot);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
** make_mac_volume: "create" an HFS volume using the ISO data
|
||||
**
|
||||
** The HFS volume structures are set up (but no data is written yet).
|
||||
**
|
||||
** ISO volumes have a allocation size of 2048 bytes - regardless
|
||||
** of the size of the volume. HFS allocation size is depends on volume
|
||||
** size, so we may have to update the ISO structures to add in any
|
||||
** padding.
|
||||
*/
|
||||
int FDECL2(make_mac_volume, struct directory *, dpnt, int, start_extent)
|
||||
{
|
||||
char vol_name[HFS_MAX_VLEN+1]; /* Mac volume name */
|
||||
hfsvol *vol; /* Mac volume */
|
||||
int vlen, vblen; /* vol length (bytes, blocks) */
|
||||
int Csize, lastCsize; /* allocation sizes */
|
||||
int ret = 0; /* return value */
|
||||
int loop = 1;
|
||||
|
||||
/* umount volume if we have had a previous attempt */
|
||||
if (vol_save)
|
||||
if (hfs_umount(vol_save, 0) < 0)
|
||||
return (-1);
|
||||
|
||||
/* set the default clump size to the ISO block size */
|
||||
lastCsize = SECTOR_SIZE;
|
||||
|
||||
if (verbose > 1)
|
||||
fprintf(stderr, "Creating HFS Volume info\n");
|
||||
|
||||
/* name or copy ISO volume name to Mac Volume name */
|
||||
strncpy(vol_name, hfs_volume_id ? hfs_volume_id : volume_id, HFS_MAX_VLEN);
|
||||
vol_name[HFS_MAX_VLEN] = '\0';
|
||||
|
||||
/* get initial size of HFS volume (size of ISO volume) */
|
||||
vblen = last_extent * BLK_CONV;
|
||||
|
||||
/* add on size of extents/catalog file, but this may mean
|
||||
the allocation size will change, so loop round until the allocation
|
||||
size doesn't change */
|
||||
while (loop) {
|
||||
hce->XTCsize = XClpSiz(vblen);
|
||||
vblen = get_vol_size(vblen);
|
||||
Csize = AlcSiz(vblen);
|
||||
|
||||
if (Csize == lastCsize) {
|
||||
/* allocation size hasn't changed, so carry on */
|
||||
loop = 0;
|
||||
}
|
||||
else {
|
||||
/* allocation size has changed, so update ISO volume size */
|
||||
if ((vlen = get_adj_size(Csize)) < 0) {
|
||||
snprintf(hce->error, ERROR_SIZE,
|
||||
"too many files for HFS volume");
|
||||
return (-1);
|
||||
}
|
||||
vlen += V_ROUND_UP(start_extent * SECTOR_SIZE, Csize);
|
||||
vblen = vlen / HFS_BLOCKSZ;
|
||||
lastCsize = Csize;
|
||||
}
|
||||
}
|
||||
|
||||
/* set vlen to size in bytes */
|
||||
/* vlen = hce->hfs_vol_size = vblen * HFS_BLOCKSZ; */
|
||||
/* take off the label/map size */
|
||||
vblen -= hce->hfs_map_size;
|
||||
vlen = hce->hfs_vol_size = vblen * HFS_BLOCKSZ;
|
||||
|
||||
/* set the default allocation size for libhfs */
|
||||
hce->Csize = Csize;
|
||||
|
||||
/* format and mount the "volume" */
|
||||
if (hfs_format(hce, 0, vol_name) < 0)
|
||||
{
|
||||
snprintf(hce->error, ERROR_SIZE, "can't HFS format %s",vol_name);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* update the ISO structures with new start extents and any padding
|
||||
required */
|
||||
if (Csize != SECTOR_SIZE) {
|
||||
last_extent = adj_size(Csize, start_extent, hce->hfs_hdr_size + hce->hfs_map_size);
|
||||
adj_size_other(dpnt);
|
||||
}
|
||||
|
||||
if ((vol = hfs_mount(hce, 0, 0)) == 0)
|
||||
{
|
||||
snprintf(hce->error, ERROR_SIZE, "can't HFS mount %s",vol_name);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* save the volume for possible later use */
|
||||
vol_save = vol;
|
||||
|
||||
/* Recursively "copy" the files to the volume - we need to
|
||||
know the first allocation block in the volume as starting blocks
|
||||
of files are relative to this.
|
||||
*/
|
||||
ret = copy_to_mac_vol(vol, dpnt);
|
||||
if (ret < 0)
|
||||
return(ret);
|
||||
|
||||
/* make the Desktop files - I *think* this stops the Mac
|
||||
rebuilding the desktop when the CD is mounted on a Mac
|
||||
These will be ignored if they already exist */
|
||||
if (create_dt)
|
||||
ret = make_desktop(vol, last_extent*BLK_CONV);
|
||||
if (ret < 0)
|
||||
return(ret);
|
||||
|
||||
/* close the volume */
|
||||
if (hfs_flush(vol) < 0)
|
||||
return(-1);
|
||||
|
||||
/* unmount and set the start blocks for the catalog/extents files */
|
||||
if (hfs_umount(vol, last_extent*BLK_CONV) < 0)
|
||||
return(-1);
|
||||
|
||||
return(Csize);
|
||||
}
|
||||
|
||||
#define TEN 10 /* well, it is! */
|
||||
#define LCHAR "_"
|
||||
|
||||
/* copy_to_mac_vol: copy all files in a directory to corresponding
|
||||
** Mac folder.
|
||||
**
|
||||
** Files are copied recursively to corresponding folders on the Mac
|
||||
** volume. The caller routine needs to do a hfs_chdir before calling this
|
||||
** routine.
|
||||
*/
|
||||
int FDECL2(copy_to_mac_vol, hfsvol *, vol, struct directory *, node)
|
||||
{
|
||||
struct directory_entry * s_entry; /* ISO directory entry */
|
||||
struct directory_entry * s_entry1; /* tmp ISO directory entry */
|
||||
struct directory *dpnt; /* ISO directory */
|
||||
|
||||
hfsfile *hfp; /* HFS file */
|
||||
hfsdirent *ent; /* HFS file entities */
|
||||
long id; /* current HFS folder */
|
||||
long dext, rext; /* real data/rsrc start blk */
|
||||
int ret; /* result code */
|
||||
int new_name; /* HFS file has modified name */
|
||||
|
||||
int tens;
|
||||
int digits;
|
||||
int i;
|
||||
|
||||
/* store the current HFS directory ID */
|
||||
if ((id = hfs_getcwd(vol)) == 0)
|
||||
return(-1);
|
||||
|
||||
if (verbose > 1)
|
||||
fprintf(stderr,"HFS scanning %s\n", node->whole_name);
|
||||
|
||||
/* loop through the ISO directory entries and process files */
|
||||
for(s_entry = node->contents; s_entry; s_entry = s_entry->next)
|
||||
{
|
||||
/* ignore directory and associated (rsrc) files */
|
||||
if(s_entry->isorec.flags[0])
|
||||
continue;
|
||||
|
||||
/* ignore any non-Mac type file */
|
||||
if(!s_entry->hfs_ent)
|
||||
continue;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr," Name = %s", s_entry->whole_name);
|
||||
fprintf(stderr," Startb = %d\n", s_entry->starting_block);
|
||||
#endif /* DEBUG */
|
||||
|
||||
ent = s_entry->hfs_ent;
|
||||
|
||||
/* create file */
|
||||
i = HFS_MAX_FLEN - strlen(ent->name);
|
||||
new_name = 0;
|
||||
tens = TEN;
|
||||
digits = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* try to open file - if it exists, then append '_' to
|
||||
the name and try again */
|
||||
errno = 0;
|
||||
if ((hfs_create(vol, ent->name, ent->type, ent->creator)) < 0)
|
||||
{
|
||||
if (errno != EEXIST )
|
||||
{
|
||||
/* not an "exist" error, or we can't append as
|
||||
the filename is already HFS_MAX_FLEN chars */
|
||||
snprintf(hce->error, ERROR_SIZE,
|
||||
"can't HFS create file %s",
|
||||
s_entry->whole_name);
|
||||
return(-1);
|
||||
}
|
||||
else if (i == 0)
|
||||
{
|
||||
/* File name at max HFS length - make unique name */
|
||||
if (!new_name) new_name++;
|
||||
|
||||
sprintf(ent->name + HFS_MAX_FLEN - digits - 1,
|
||||
"%s%d", LCHAR, new_name);
|
||||
new_name++;
|
||||
if (new_name == tens) {
|
||||
tens *= TEN;
|
||||
digits++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append '_' to get new name */
|
||||
strcat(ent->name, LCHAR);
|
||||
i--;
|
||||
new_name = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* warn that we have a new name */
|
||||
if (new_name && verbose > 0)
|
||||
{
|
||||
fprintf(stderr, "Using HFS name: %s for %s\n", ent->name,
|
||||
s_entry->whole_name);
|
||||
}
|
||||
|
||||
/* open file */
|
||||
if ((hfp = hfs_open(vol, ent->name)) == 0)
|
||||
{
|
||||
snprintf(hce->error, ERROR_SIZE, "can't HFS open %s",
|
||||
s_entry->whole_name);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* if it has a data fork, then "write" it out */
|
||||
if (ent->dsize)
|
||||
write_fork(hfp, ent->dsize);
|
||||
|
||||
/* if it has a resource fork, set the fork and "write" it out */
|
||||
if (ent->rsize)
|
||||
{
|
||||
if ((hfs_setfork(hfp, 1)) < 0)
|
||||
return(-1);
|
||||
write_fork(hfp, ent->rsize);
|
||||
}
|
||||
|
||||
/* update any HFS file attributes */
|
||||
if ((hfs_fsetattr(hfp, ent)) < 0)
|
||||
{
|
||||
snprintf(hce->error, ERROR_SIZE, "can't HFS set attributes %s",
|
||||
s_entry->whole_name);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* get the ISO starting block of data fork (may be zero)
|
||||
and convert to the equivalent HFS block */
|
||||
if (ent->dsize)
|
||||
dext = s_entry->starting_block * BLK_CONV;
|
||||
else
|
||||
dext = 0;
|
||||
|
||||
/* if the file has a resource fork (associated file), get it's
|
||||
ISO starting block and convert as above */
|
||||
if (s_entry->assoc && ent->rsize)
|
||||
rext = s_entry->assoc->starting_block * BLK_CONV;
|
||||
else
|
||||
rext = 0;
|
||||
|
||||
/* close the file and update the starting blocks */
|
||||
if (hfs_close(hfp, dext, rext) < 0)
|
||||
{
|
||||
snprintf(hce->error, ERROR_SIZE, "can't HFS close file %s",
|
||||
s_entry->whole_name);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* process sub-directories - have a slight problem here,
|
||||
if the directory had been relocated, then we need to find
|
||||
the real directory - we do this by first finding the real
|
||||
directory_entry, and then finding it's directory info */
|
||||
|
||||
/* following code taken from joliet.c */
|
||||
for(s_entry=node->contents;s_entry;s_entry=s_entry->next)
|
||||
{
|
||||
if((s_entry->de_flags & RELOCATED_DIRECTORY) != 0)
|
||||
{
|
||||
/* if the directory has been reloacted, then search the
|
||||
relocated directory for the real entry */
|
||||
for(s_entry1=reloc_dir->contents;s_entry1;s_entry1=s_entry1->next)
|
||||
{
|
||||
if(s_entry1->parent_rec == s_entry)
|
||||
break;
|
||||
}
|
||||
|
||||
/* have a problem - can't find the real directory */
|
||||
if(s_entry1 == NULL)
|
||||
{
|
||||
snprintf(hce->error, ERROR_SIZE,
|
||||
"can't locate relocated directory %s",
|
||||
s_entry->whole_name);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
s_entry1 = s_entry;
|
||||
|
||||
/* now have the correct entry - now find the actual directory */
|
||||
if ((s_entry1->isorec.flags[0] & 2) && strcmp(s_entry1->name,".") && strcmp(s_entry1->name,".."))
|
||||
{
|
||||
if((s_entry->de_flags & RELOCATED_DIRECTORY) != 0)
|
||||
dpnt = reloc_dir->subdir;
|
||||
else
|
||||
dpnt = node->subdir;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (dpnt->self == s_entry1)
|
||||
break;
|
||||
dpnt = dpnt->next;
|
||||
if(!dpnt)
|
||||
{
|
||||
snprintf(hce->error, ERROR_SIZE,
|
||||
"can't find directory location %s",
|
||||
s_entry1->whole_name);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
/* now have the correct directory - so do the HFS stuff */
|
||||
ent = dpnt->hfs_ent;
|
||||
|
||||
/* if we don't have hfs entries, then this is a "deep"
|
||||
directory - this will be processed later */
|
||||
if (!ent)
|
||||
continue;
|
||||
|
||||
/* make sub-folder */
|
||||
i = HFS_MAX_FLEN - strlen(ent->name);
|
||||
new_name = 0;
|
||||
tens = TEN;
|
||||
digits = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* try to create new directory - if it exists, then
|
||||
append '_' to the name and try again */
|
||||
errno = 0;
|
||||
if (hfs_mkdir(vol, ent->name) < 0)
|
||||
{
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
/* not an "exist" error, or we can't append as
|
||||
the filename is already HFS_MAX_FLEN chars */
|
||||
snprintf(hce->error, ERROR_SIZE,
|
||||
"can't HFS create folder %s",
|
||||
s_entry->whole_name);
|
||||
return(-1);
|
||||
}
|
||||
else if (i == 0)
|
||||
{
|
||||
/* File name at max HFS length - make unique name */
|
||||
if (!new_name) new_name++;
|
||||
|
||||
sprintf(ent->name + HFS_MAX_FLEN - digits - 1,
|
||||
"%s%d", LCHAR, new_name);
|
||||
new_name++;
|
||||
if (new_name == tens) {
|
||||
tens *= TEN;
|
||||
digits++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append '_' to get new name */
|
||||
strcat(ent->name, LCHAR);
|
||||
i--;
|
||||
new_name = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* warn that we have a new name */
|
||||
if (new_name && verbose > 0)
|
||||
{
|
||||
fprintf(stderr, "Using HFS name: %s for %s\n", ent->name,
|
||||
s_entry->whole_name);
|
||||
}
|
||||
|
||||
/* see if we need to "bless" this folder */
|
||||
if (hfs_bless && strcmp(s_entry->whole_name, hfs_bless) == 0) {
|
||||
hfs_stat(vol, ent->name, ent);
|
||||
hfs_vsetbless(vol, ent->cnid);
|
||||
if (verbose > 0) {
|
||||
fprintf(stderr, "Blessing %s (%s)\n",
|
||||
ent->name, s_entry->whole_name);
|
||||
}
|
||||
/* stop any further checks */
|
||||
hfs_bless = NULL;
|
||||
}
|
||||
|
||||
/* change to sub-folder */
|
||||
if (hfs_chdir(vol, ent->name) < 0)
|
||||
return(-1);
|
||||
|
||||
/* recursively copy files ... */
|
||||
ret = copy_to_mac_vol(vol, dpnt);
|
||||
if (ret < 0)
|
||||
return(ret);
|
||||
|
||||
/* change back to this folder */
|
||||
if (hfs_setcwd(vol, id) < 0)
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif /* APPLE_HYB */
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/* volume.h */
|
||||
/* $OpenBSD: volume.h,v 1.1 2008/03/08 15:36:12 espie Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008 Marc Espie <espie@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef VOLUME_H
|
||||
#define VOLUME_H
|
||||
|
||||
extern int make_mac_volume(struct directory *, int);
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,28 @@
|
|||
/* write.h */
|
||||
/* $OpenBSD: write.h,v 1.1 2008/03/08 15:36:12 espie Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008 Marc Espie <espie@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef WRITE_H
|
||||
#define WRITE_H
|
||||
|
||||
struct directory;
|
||||
|
||||
extern int get_adj_size(int);
|
||||
extern int adj_size(int, int, int);
|
||||
extern void adj_size_other(struct directory *);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue