hfsplus-1.0.4/ 0040755 0000000 0000000 00000000000 07450157145 011712 5 ustar root root hfsplus-1.0.4/doc/ 0040755 0000000 0000000 00000000000 07450157144 012456 5 ustar root root hfsplus-1.0.4/doc/man/ 0040755 0000000 0000000 00000000000 07450157145 013232 5 ustar root root hfsplus-1.0.4/doc/man/hfsp.man 0100644 0000000 0000000 00000004032 07441220604 014652 0 ustar root root .if n .ds Q \&"
.if t .ds Q ``
.if n .ds U \&"
.if t .ds U ''
.TH "HFSP" 1
.tr \&
.nr bi 0
.nr ll 0
.nr el 0
.de DS
..
.de DE
..
.de Pp
.ie \\n(ll>0 \{\
.ie \\n(bi=1 \{\
.nr bi 0
.if \\n(t\\n(ll=0 \{.IP \\(bu\}
.if \\n(t\\n(ll=1 \{.IP \\n+(e\\n(el.\}
.\}
.el .sp
.\}
.el \{\
.ie \\nh=1 \{\
.LP
.nr h 0
.\}
.el .PP
.\}
..
NAME
.Pp
\fBhfsp\fP \fBhfsplus\fP - Collection of tools to acces
HFS+ volumes.
.Pp
DESCRIPTION
.Pp
The hfsplus collection cotains tools to read and display the files
found on an HFS+ formatted volume. HFS+ is the volume format
intodruced by Apple Computer inc. around MacOS 8. The HFS+ format
uses a better approach to acces large volumes and allows files
with a size up to 2[circ ]64 bytes. In Addition filenames are saved
as two-byte unicode with a length upto 255 (unicode) characters.
.Pp
In contrast to its sucessor, the hfs-tools hfsplus does not use
the volume/directory/file/ syntax using ':' as delimiter but
uses the standard unix '/', '..' and '.' notation. Since this
concept is not fully supported my HFS+ not all combinations
will be understood.
.Pp
EXAMPLES
.Pp
This example mounts my main HFS+ volume, shows some files and copies
one to the linux side:
.DS
.sp
.ft RR
.nf
> hpmount /dev/hda13
> hpls
Apple Extras Desktop Folder MP3 Systemordner
Benutzer Develop Programme Temporary Items
Bibel Dokumente Spiele VM Storage
> hpcd Develop
> hpcd Test
> hppwd
/Aida/Develop/Test
hpcopy -t Test.cp .
> hpumount
.DE
.fi
.ec
.ft P
.sp
.Pp
FILES
.Pp
\fB$HOME/.hfsplusvolume\fP
This file is created by hpmount and removed by hpunmount. It contains
the volume name and the current directory id.
.Pp
BUGS
.Pp
There are some bugs related to uniocde handling and the large file
sizes not supported by some older formats (binhex, macbinary).
See the developer documenatation for details
.Pp
SEE ALSO
.Pp
hpmount(1), hpumount(1), hpls(1), hpcd(1), hppwd(1), hpcopy(1),
hfsutils(1),
.Pp
.SH AUTHORS
.Pp
Klaus Halfmann \f(CR[lt ]halfmann@libra.de[gt ]\fP
.Pp
hfsplus-1.0.4/doc/man/hfsp.sgml 0100644 0000000 0000000 00000003547 07441220604 015053 0 ustar root root
NAME
hfsp hfsplus - Collection of tools to acces
HFS+ volumes.
DESCRIPTION
The hfsplus collection cotains tools to read and display the files
found on an HFS+ formatted volume. HFS+ is the volume format
intodruced by Apple Computer inc. around MacOS 8. The HFS+ format
uses a better approach to acces large volumes and allows files
with a size up to 2^64 bytes. In Addition filenames are saved
as two-byte unicode with a length upto 255 (unicode) characters.
In contrast to its sucessor, the hfs-tools hfsplus does not use
the volume/directory/file/ syntax using ':' as delimiter but
uses the standard unix '/', '..' and '.' notation. Since this
concept is not fully supported my HFS+ not all combinations
will be understood.
EXAMPLES
This example mounts my main HFS+ volume, shows some files and copies
one to the linux side:
> hpmount /dev/hda13
> hpls
Apple Extras Desktop Folder MP3 Systemordner
Benutzer Develop Programme Temporary Items
Bibel Dokumente Spiele VM Storage
> hpcd Develop
> hpcd Test
> hppwd
/Aida/Develop/Test
hpcopy -t Test.cp .
> hpumount
FILES
$HOME/.hfsplusvolume
This file is created by hpmount and removed by hpunmount. It contains
the volume name and the current directory id.
BUGS
There are some bugs related to uniocde handling and the large file
sizes not supported by some older formats (binhex, macbinary).
See the developer documenatation for details
SEE ALSO
hpmount(1), hpumount(1), hpls(1), hpcd(1), hppwd(1), hpcopy(1),
hfsutils(1),
AUTHORS
Klaus Halfmann <halfmann@libra.de>
hfsplus-1.0.4/doc/man/hfsp.txt 0100644 0000000 0000000 00000003677 07441220604 014734 0 ustar root root 00..11.. NNAAMMEE
hhffsspp hhffsspplluuss - Collection of tools to acces HFS+ volumes.
00..22.. DDEESSCCRRIIPPTTIIOONN
The hfsplus collection cotains tools to read and display the files
found on an HFS+ formatted volume. HFS+ is the volume format
intodruced by Apple Computer inc. around MacOS 8. The HFS+ format uses
a better approach to acces large volumes and allows files with a size
up to 2^64 bytes. In Addition filenames are saved as two-byte unicode
with a length upto 255 (unicode) characters.
In contrast to its sucessor, the hfs-tools hfsplus does not use the
volume/directory/file/ syntax using ':' as delimiter but uses the
standard unix '/', '..' and '.' notation. Since this concept is not
fully supported my HFS+ not all combinations will be understood.
00..33.. EEXXAAMMPPLLEESS
This example mounts my main HFS+ volume shows some files and copies
one to the linux side:
> hpmount /dev/hda13
> hpls
Apple Extras Desktop Folder MP3 Systemordner
Benutzer Develop Programme Temporary Items
Bibel Dokumente Spiele VM Storage
> hpcd Develop
> hpcd Test
> hppwd
/Aida/Develop/Test
hpcopy -t Test.cp .
> hpumount
00..44.. FFIILLEESS
$$HHOOMMEE//..hhffsspplluussvvoolluummee This file is created by hpmount and removed by
hpunmount. It contains the volume name and the current directory id.
00..55.. BBUUGGSS
There are some bugs related to uniocde handling and the large file
sizes not supported by some older formats (binhex, macbinary). See
the developer documenatation for details
00..66.. SSEEEE AALLSSOO
hpmount(1), hpumount(1), hpls(1), hpcd(1), hppwd(1), hpcopy(1)
00..77.. AAUUTTHHOORRSS
Klaus Halfmann
hfsplus-1.0.4/doc/.cvsignore 0100644 0000000 0000000 00000000026 07441220604 014441 0 ustar root root Makefile
Makefile.in
hfsplus-1.0.4/doc/Makefile.am 0100644 0000000 0000000 00000000167 07441220604 014503 0 ustar root root #
# Makefile.am for hfsplus/doc
#
htmldir = $(DOCDIR)/hfsplus
html_DATA = \
bugs.html
EXTRA_DIST = $(html_DATA)
hfsplus-1.0.4/doc/bugs.html 0100644 0000000 0000000 00000010067 07450157136 014306 0 ustar root root
HFS+ Utilities, BUGS
HFS+ Utilities, BUGS
- Disk First Aid will hang with some strange behaviour in case the
length of a key does not match the length of the string inside the key
(Ill try to report this bug to Apple ;-)
- HFS+ cotains hints for the finder what encoding (Roman, Asiatic,
etc. to use. These are not supported. MacOS may react strange on files
or folders that are not marked but need such an encoding.
- HFS+ contains POSIX permissions which are not used by MacOS <= 9,
but probably by MacOS X. None of the HFS+ utils cares fore those by now.
This should be implemented in some later version.
- hpfsck will not complain abut files/folders without thread and vice
versa. All sorts of strange results will happen when using such a volume.
- hpfsck will not complain about records without parent. They will not
show up, but are still there. Fixing this is a difficult task.
- Error handling ist not always consistent and will need a cleanung
once the major goals are reached. You sometimes will get errors without
any message (failed: No Error) or errors with wrong explanation
(Internal errors that were caught and handled.)
- The conversion from and to unicode does not work fully. Files with
extended characters are not created correctly and therefore are not
found by MacOS. The sorting of files with extended characters will be
different from the result of a "normal" sort. (How does kanji work with
linux ?).
- HFS+ allows any charcter as name. MacOS does not allow ':' since it
is used as folder seperator. I dont know what MacOS X allows. With
hfsplus the standard unix . and .. is used to denote the current and
parent directory. Thus using '.' or '..' as filenames will result in
unpredictable behaviour.
- Unicode Strings that convert to UTF-8/ISO Strings longer than 255
characters will be trunctated. (In case you run into this theoretically
bug please send Email to <klaus.halfmann@feri.de> Im curious :)
- The creation date of a mac volume is set in local time. (So mac
programs do not think the volume has changed when the timezone or DST
changes). This difference is ignored since Linux/Unix per default only
uses UUTC times. (In practice this should not matter.)
- The volume name must not contain the charcter ':' (Which is rather
unlikely with MacOS but theoretically possible). This is a limitation of
the hfsputils which need to save some information in a text file.
- The Macbinary and BinHex formats contain limitations on the length
of filenames, longer names will (hopefully) be truncated.
- The Macbinary and BinHex formats are unable to cope with 64 bit file
length. Such files can not be copied using these formats, use raw mode
instead.
- The globbing mechanism in hpls and other functions can (per desgin)
not match patterns spaning directories so 'a*b' or 'a{/,b}c' will not
match 'a/b'. (I dont think a normal ls * does this, perhaps Im
--pedantic here :)
- hpls does not support the unix '.' and '..' notation completly. '.'
will be shown, but '..' not. hpls '.' and hpls '..' wont work. (hpcd
'..' will work :). Since HFS+ does not really have these concepts It is
somewhat difficult to implement this completly.
- The Partition code could be a bit better and should release
the Memory allocated, but I'm happy its there at all ;-)
$Id: bugs.html,v 1.3 2002/03/26 20:47:26 klaus Exp $
hfsplus-1.0.4/doc/faq.html 0100644 0000000 0000000 00000000700 07441220604 014075 0 ustar root root
HFS+ Utilities, FAQ
HFS+ Utilities, Frequently Asked Questions
- Did I (Klaus Halfmann) use any code from Darwin (MacOSX)
-
No, due to space and time constraints I did not yet do
anything with Darwin.
$Id: faq.html,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
hfsplus-1.0.4/doc/hfsp.html 0100644 0000000 0000000 00000004473 07441220604 014301 0 ustar root root
What is HFS+
What is HFS+
HFS+ is the new Filesystem intodruced my Apple around MacOS8.
It became necessary because its predecessor, HFS, had a fixed numer
of blocks (2^16), and on large volumes theses block became very
large, wasting a lot of space. HFS+ solves this problem and
intodruces some new concepts like Unicode file names.
Detailed Documentation can be found in
Technote 1150 HFS+ Volume format and in
File Manager.
In contrast to unix-like file Systems, HFS+ (and HFS+) work like indexes
in a database. As with databases The index is composed of keys structered
in a B*-Tree. (A B*Tree is basically a n-ary tree located in nodes on a volume.
This way acces to any file is pretty fast at the price of a complex
insert / delete management. I migt provide some O(..) notation
here but dont want to get blamed by some Theoritican :) .
The B*-tree is composed of index nodes and leaf nodes. Index nodes
contain ordered keys that point to deeper index- or leaf-nodes.
Leaf nodes contain keys and associated file or folder records.
The keys and records have variable length but an additional
index at the end of every node allows indexed acces.
Apple places additional restrictions on the B*-Tree:
- All leaf nodes are found a the same depth
- All nodes of the same depth are linked foreward and backward
- ... More I dont remember right now.
The keys are composed of the unique id of the parent folder and
the (specially encoded) unicode name of the file. The folder
THREADS are needed to retrive the parent folder for a given
folder id. Theese use an empty name and are simliar to the
'.' directory in unix.
Files and the B*Trees themselfes are stored in forks. For files these
are the Apple-like data- and resource-fork. With HFS+ every files
may have up to 8 not continuos parts until the additional parts
are found in the Extends record. This Extends record is used
for the catalog file (fork) and other forks, too. So that theese
have fixed record ids, too.
$Id: hfsp.html,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
hfsplus-1.0.4/doc/libhfsp.html 0100644 0000000 0000000 00000005755 07441220604 014774 0 ustar root root
libhfsp
libhfsp
This library can be used to prorammatically acces HFS+
volumes. The library in turn is used by utilities allowing
user access to the volume.
objects exposed
The library has some top level objects that are to be used
by other programs:
- volume identifies the volume as a whole.
The btree is used a cache for the records used
later (this object will eventually be included in the volume later
on).
- The record represent a file or folder.
Design principles
In contrast to the original library by Robert Leslie this libray
rarely uses malloc/free. This impoes, that all memory is contained
in the objects shown above. As of now only the current two
blocks are "cached". Performance may be poor when doing large
transactions. function returning int return 0 on success and any
other value (normally -1) on failure unless stated otherwise.
functions returning pointers return NULL on error. In most
cases hfsp_error
and errno
should be set.
Byte swapping happens when reading structure from raw memory,
this avoids any alignment problems. (In contrast to Brad Boyers
aproach wich needs to swap (and assemble) the bytes on every acces.)
The contentes of the raw HFS+ structures is usually not
copied to other structures and remains embedded in the high
level strcutures. In case you need such a value acces it directly
(e.G. volume->vol.create_date - HFSPTIMEDIFF )
Call volume_open()
to open a volume.
You must call volume_close()
to close the volume.
all other volume_
functions are used internally only
use them when you really know what you are doing.
The btree as of now is the catalog-file btree, althoug there are
other btrees like the extends-file btree. I intend to make the
btree a (more or less) private member of the volume. This will
be done together with implementing a catalog-node cache superseeding
the simple block cache at the volume.
The record is used whenever a file or folder is needed. There
is a sufficient set of methods to navigate around with records.
Folders and FolderThreads can both be used when acces to the
files of a folder is needed. File Threads are supported, althoug
Apple does not use them. (The utility functions like hpls however
suppress then since I dont know what to do with them.)
As of now there is no concept of "opening" a record, for
readonlny acces just take one of the forks and use the
fork functkions found at the volume to acces the raw data. See
hpcopy for examples how to do that.
This is work in progress, either be patient or provide help.
$Id: libhfsp.html,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
hfsplus-1.0.4/.cvsignore 0100644 0000000 0000000 00000000253 07441220604 013676 0 ustar root root Makefile
Makefile.in
configure
config.h.in
config.h
config.cache
config.status
config.sub
config.guess
ltconfig
ltmain.sh
stamp-h
stamp-h.in
libtool
config.log
aclocal.m4
hfsplus-1.0.4/AUTHORS 0100644 0000000 0000000 00000002207 07442226174 012760 0 ustar root root The following people contributed to the hfsplus package:
Klaus Halfmann
Did most of the programming and sometimes tries to push
the project foreward.
Michael Schulze appeard in Winter 2002
and gave new drive to the dormant project
Brad Boyer (flar@allandria.com)
Wrote (parts of) a kernel module for linux ppc 2.2 which
where used by Klaus as a starting point. Commented at
the code.
R. Shapiro (rshapiro@bbn.com)
Create src and binary rpms for easier distribution
Olaf Hering (olh@suse.de) Supplied us with the CVS access
at Suse
Klaus Kämpf (kkaempf@suse.de) set up the initial structure
to use all those nifty auto... tools
Some people at the linuxppc-kernel mailing list.
Some people at the #mklinux channel on efnet/openrojects
* You * if you want to help ...
I (Klaus Halfmann) would like to mention my father - Peter Heck -
at this place. He died at the 16th of September 2000 after
figthing a long fight against his cancer. Some parts of
this code where written on my iBook traveling back and forth
by train, visting and attending him.
$Id: AUTHORS,v 1.2 2002/03/08 21:26:20 klaus Exp $
hfsplus-1.0.4/COPYING 0100644 0000000 0000000 00000035631 07441220604 012741 0 ustar root root The hfsplus package if fully covered by the GNU GENERAL PUBLIC LICENCE.
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 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
$Id: COPYING,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
hfsplus-1.0.4/ChangeLog 0100644 0000000 0000000 00000000772 07450157136 013467 0 ustar root root
Added blockiterator to volume.c
Added ChangeLog to CVS :)
2000-09-29: Version 1.0.1 is considered a stable, readonly implementation
2000-10-19: Version 1.0.2 is faster and fixes a bug for volume > 2Gb
2000-10-XX: Fixed a bug when accessing fragmented files on larger volumes
2000-11-XX: Fixed a display bug when doing ls -la for '.'
2000-11-06: hpfsck is ok for the most purposes
2002-03-25: Added (Thanks To Michael Schulze) Partition support
$Id: ChangeLog,v 1.2 2002/03/26 20:47:26 klaus Exp $
hfsplus-1.0.4/INSTALL 0100644 0000000 0000000 00000020003 07441220604 012722 0 ustar root root Quick Build instructions
========================
make -f makefile.cvs
make
This assumes, that several auto-tools are availeable. Those
should be part fo almost any Linux-distributon.
The rest of this document is the generic one since
Im still not familiar with all the option the build process
allows:
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.
$Id: INSTALL,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
hfsplus-1.0.4/Makefile.am 0100644 0000000 0000000 00000000712 07442720755 013747 0 ustar root root #
# Makefile.am for hfsplus
#
# Created by Klaus Kaempf and
# Klaus Halfmann
#
# $Id: Makefile.am,v 1.2 2002/03/10 18:11:57 klaus Exp $
SUBDIRS = libhfsp src
EXTRA_DIST = index.html
AUTOMAKE_OPTIONS = foreign gnu
CLEANFILES = config.cache config.log
MAINTAINERCLEANFILES = Makefile Makefile.in \
configure config.h config.sub config.guess \
ltconfig ltmain.sh stamp-h stamp-h.in libtool aclocal.m4
hfsplus-1.0.4/Makefile.cvs 0100644 0000000 0000000 00000000315 07441220604 014127 0 ustar root root #
# Makefile.cvs for libycp
#
configure: all
./configure
all:
aclocal
autoconf
autoheader
automake -a
install: configure
make
make install
reconf: all
./config.status --recheck
./config.status
hfsplus-1.0.4/NEWS 0100644 0000000 0000000 00000000301 07450157136 012400 0 ustar root root V 1.0.1 should be stable, performance on highly fragmented files
may be poor
V 1.0.4 Adds Partition support and will work on x86 Linux, too
$Id: NEWS,v 1.2 2002/03/26 20:47:26 klaus Exp $
hfsplus-1.0.4/README 0100644 0000000 0000000 00000000765 07441220604 012566 0 ustar root root
This package is a set of tools that allow acces to HFS+ fomatted
volumes. HFS+ is a modernized version of Apple Computers HFS
Filesystem. In addition in contains the library "libhfsp" which
you may use for your own experiments, all the tools are based
on this library. (A bit of understanding is still needed however).
Feel free to contact me (Klaus Halfmann, )
Thanks to Suse which supplied me with a CVS Server.
$Id: README,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
hfsplus-1.0.4/VERSION 0100644 0000000 0000000 00000000235 07450157136 012757 0 ustar root root 1.0.4
Please keep in sync with HPUTILS_VERS
in libhfsp/src/libhfsp.h
*** Version number must be on line 1 ***
(configure.in uses "head -1" to extract it)
hfsplus-1.0.4/configure.in 0100644 0000000 0000000 00000003635 07441221437 014223 0 ustar root root dnl -*- shell-script -*-
dnl
dnl Process this file with autoconf to produce a configure script.
dnl
dnl libhfs - library for reading and writing Macintosh HFS volumes
dnl Copyright (C) 1996-1998 Robert Leslie
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 2 of the License, or
dnl (at your option) any later version.
dnl
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
dnl
dnl $Id: configure.in,v 1.1 2002/03/05 19:57:19 klaus Exp $
dnl
AC_INIT(src/hfsputil.c)
AM_CONFIG_HEADER(config.h)
AC_CANONICAL_SYSTEM
AC_ARG_PROGRAM
VERSION=`head -1 ${srcdir}/VERSION`
PACKAGE=hfsplus
AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
AC_ARG_ENABLE(debug,
[ --enable-debug enable diagnostic debugging support])
if test "x$enable_debug" = xyes
then
AC_DEFINE(DEBUG,1,'enable diagnostic debugging support')
fi
dnl Checks for programs.
AC_PROG_MAKE_SET
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_RANLIB
AC_PROG_LN_S
AC_PROG_GCC_TRADITIONAL
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(unistd.h fcntl.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
AC_STRUCT_TM
AC_C_CONST
dnl Checks for library functions.
AC_FUNC_MEMCMP
AC_CHECK_FUNCS(mktime)
dnl Tool for creating libraries
AM_PROG_LIBTOOL
dnl Create output files.
AC_OUTPUT(Makefile
src/Makefile
doc/Makefile
libhfsp/Makefile
libhfsp/src/Makefile
libhfsp/test/Makefile)
hfsplus-1.0.4/index.html 0100644 0000000 0000000 00000005414 07441220604 013677 0 ustar root root
HFS+ Utilities
HFS+ Utilities
This directory is a work in progress. It is maintained
by Klaus Halfmann <klaus.halfmann@t-online.de> please contact me
for any questions.
Parts of this project
What is HFS+
libhfsp
bugs
FAQ
Current Status
Klaus Halfmann
I decided to recreate the parts of the original hfsutils and
keep theire names but remame "hfs" to "hfsp" reso. "h" to "hp"
wherever needed.
I started working on libhfsp. Im used to OO-Programming, so
I recreated the code with objects in mind. See documenation
for libhfsp.
The libhfsp part works for (most) readonly purposes. Im currently
working on user-useable tools like hpmount hpcd and hpls.
Other...
Ask me (Klaus Hafmann <klaus.halfmann@t-online.de> where you might help.
To Do:
- create a working libhfsp (readonly)
- create a working libhfsp (writing)
- Create a hpfscheck to find at least maximum node Id
- Recreate commandline tools
- (Re-)create kernel module
- optimize libhfsp (caching, etc)
- optimize key search for fixed length keys (extends tree...)
- Make the address of the FSF correctly everywhere
- create mkfs / chkfs
- Recreate UI/X-Tools
Copyright (C) 2000 Klaus Halfmann <klaus.halfmann@t-online.de>
Original code 1996-1998 by Robert Leslie <rob@mars.rog>
other work 2000 from Brad Boyer <flar@pants.nu>
All files found in this directory and subdirectory are free software;
you can redistribute it and/or modify them
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.
$Id: index.html,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
hfsplus-1.0.4/libhfsp/ 0040755 0000000 0000000 00000000000 07450157145 013341 5 ustar root root hfsplus-1.0.4/libhfsp/src/ 0040755 0000000 0000000 00000000000 07450157145 014130 5 ustar root root hfsplus-1.0.4/libhfsp/src/.cvsignore 0100644 0000000 0000000 00000000064 07441220604 016114 0 ustar root root Makefile
Makefile.in
*.o
*.lo
.deps
.libs
*.a
*.la
hfsplus-1.0.4/libhfsp/src/FastUnicodeCompare.c 0100644 0000000 0000000 00000075456 07441220604 020014 0 ustar root root // FastUnicodeCompare - Compare two Unicode strings; produce a relative ordering
//
// IF RESULT
// --------------------------
// str1 < str2 => -1
// str1 = str2 => 0
// str1 > str2 => +1
//
// The lower case table starts with 256 entries (one for each of the upper bytes
// of the original Unicode char). If that entry is zero, then all characters with
// that upper byte are already case folded. If the entry is non-zero, then it is
// the _index_ (not byte offset) of the start of the sub-table for the characters
// with that upper byte. All ignorable characters are folded to the value zero.
//
// In pseudocode:
//
// Let c = source Unicode character
// Let table[] = lower case table
//
// lower = table[highbyte(c)]
// if (lower == 0)
// lower = c
// else
// lower = table[lower+lowbyte(c)]
//
// if (lower == 0)
// ignore this character
//
// To handle ignorable characters, we now need a loop to find the next valid
// character. Also, we can't pre-compute the number of characters to compare;
// the string length might be larger than the number of non-ignorable characters.
// Further, we must be able to handle ignorable characters at any point in the
// string, including as the first or last characters. We use a zero value as a
// sentinel to detect both end-of-string and ignorable characters. Since the File
// Manager doesn't prevent the NUL character (value zero) as part of a filename,
// the case mapping table is assumed to map u+0000 to some non-zero value (like
// 0xFFFF, which is an invalid Unicode character).
//
// Pseudocode:
//
// while (1) {
// c1 = GetNextValidChar(str1) // returns zero if at end of string
// c2 = GetNextValidChar(str2)
//
// if (c1 != c2) break // found a difference
//
// if (c1 == 0) // reached end of string on both
// // strings at once?
// return 0; // yes, so strings are equal
// }
//
// // When we get here, c1 != c2. So, we just need to determine which one is
// // less.
// if (c1 < c2)
// return -1;
// else
// return 1;
//
SInt32 FastUnicodeCompare ( register ConstUniCharArrayPtr str1, register ItemCount length1,
register ConstUniCharArrayPtr str2, register ItemCount length2)
{
register UInt16 c1,c2;
register UInt16 temp;
register UInt16* lowerCaseTable;
lowerCaseTable = gLowerCaseTable;
while (1) {
// Set default values for c1, c2 in case there are no more valid chars
c1 = 0;
c2 = 0;
// Find next non-ignorable char from str1, or zero if no more
while (length1 && c1 == 0) {
c1 = *(str1++);
--length1;
if ((temp = lowerCaseTable[c1>>8]) != 0) // is there a subtable
// for this upper byte?
c1 = lowerCaseTable[temp + (c1 & 0x00FF)]; // yes, so fold the char
}
// Find next non-ignorable char from str2, or zero if no more
while (length2 && c2 == 0) {
c2 = *(str2++);
--length2;
if ((temp = lowerCaseTable[c2>>8]) != 0) // is there a subtable
// for this upper byte?
c2 = lowerCaseTable[temp + (c2 & 0x00FF)]; // yes, so fold the char
}
if (c1 != c2) // found a difference, so stop looping
break;
if (c1 == 0) // did we reach the end of both strings at the same time?
return 0; // yes, so strings are equal
}
if (c1 < c2)
return -1;
else
return 1;
}
/* The lower case table consists of a 256-entry high-byte table followed by
some number of 256-entry subtables. The high-byte table contains either an
offset to the subtable for characters with that high byte or zero, which
means that there are no case mappings or ignored characters in that block.
Ignored characters are mapped to zero.
*/
UInt16 gLowerCaseTable[] = {
// High-byte indices ( == 0 iff no case mapping and no ignorables )
/* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 1 */ 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 2 */ 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 3 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 4 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 5 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 6 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 9 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* E */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* F */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00,
// Table 1 (for high byte 0x00)
/* 0 */ 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
/* 1 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
/* 2 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
/* 3 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
/* 4 */ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
/* 5 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
/* 6 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
/* 7 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
/* 8 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
/* 9 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
/* A */ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
/* B */ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
/* C */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7,
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
/* D */ 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF,
/* E */ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
/* F */ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
// Table 2 (for high byte 0x01)
/* 0 */ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F,
/* 1 */ 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117,
0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F,
/* 2 */ 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127,
0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F,
/* 3 */ 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137,
0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140,
/* 4 */ 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F,
/* 5 */ 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157,
0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F,
/* 6 */ 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167,
0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F,
/* 7 */ 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177,
0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F,
/* 8 */ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
/* 9 */ 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
/* A */ 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8,
0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF,
/* B */ 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
/* C */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF,
/* D */ 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7,
0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF,
/* E */ 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7,
0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF,
/* F */ 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7,
0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF,
// Table 3 (for high byte 0x03)
/* 0 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
/* 1 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F,
/* 2 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F,
/* 3 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F,
/* 4 */ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F,
/* 5 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F,
/* 6 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F,
/* 7 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F,
/* 8 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,
0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,
/* 9 */ 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
/* A */ 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
/* B */ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
/* C */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF,
/* D */ 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,
/* E */ 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
/* F */ 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,
0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,
// Table 4 (for high byte 0x04)
/* 0 */ 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407,
0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F,
/* 1 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
/* 2 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
/* 3 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
/* 4 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
/* 5 */ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F,
/* 6 */ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467,
0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F,
/* 7 */ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477,
0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F,
/* 8 */ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,
/* 9 */ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497,
0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F,
/* A */ 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7,
0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF,
/* B */ 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7,
0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF,
/* C */ 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8,
0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF,
/* D */ 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7,
0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF,
/* E */ 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7,
0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF,
/* F */ 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7,
0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF,
// Table 5 (for high byte 0x05)
/* 0 */ 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507,
0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F,
/* 1 */ 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517,
0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,
/* 2 */ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,
/* 3 */ 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
/* 4 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
/* 5 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557,
0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,
/* 6 */ 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
/* 7 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
/* 8 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587,
0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F,
/* 9 */ 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597,
0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F,
/* A */ 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7,
0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF,
/* B */ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
/* C */ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7,
0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF,
/* D */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
/* E */ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF,
/* F */ 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7,
0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF,
// Table 6 (for high byte 0x10)
/* 0 */ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F,
/* 1 */ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017,
0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F,
/* 2 */ 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F,
/* 3 */ 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037,
0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F,
/* 4 */ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047,
0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F,
/* 5 */ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057,
0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F,
/* 6 */ 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067,
0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F,
/* 7 */ 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077,
0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F,
/* 8 */ 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087,
0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F,
/* 9 */ 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097,
0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F,
/* A */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
/* B */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
/* C */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7,
0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF,
/* D */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
/* E */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
/* F */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7,
0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF,
// Table 7 (for high byte 0x20)
/* 0 */ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000,
/* 1 */ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017,
0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F,
/* 2 */ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027,
0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F,
/* 3 */ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037,
0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F,
/* 4 */ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047,
0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F,
/* 5 */ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057,
0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F,
/* 6 */ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067,
0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 7 */ 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077,
0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F,
/* 8 */ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087,
0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F,
/* 9 */ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097,
0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F,
/* A */ 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7,
0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF,
/* B */ 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7,
0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF,
/* C */ 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7,
0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF,
/* D */ 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7,
0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF,
/* E */ 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7,
0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF,
/* F */ 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7,
0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF,
// Table 8 (for high byte 0x21)
/* 0 */ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107,
0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F,
/* 1 */ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117,
0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F,
/* 2 */ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127,
0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F,
/* 3 */ 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137,
0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F,
/* 4 */ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,
0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,
/* 5 */ 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,
0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,
/* 6 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
/* 7 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
/* 8 */ 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187,
0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F,
/* 9 */ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197,
0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F,
/* A */ 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7,
0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF,
/* B */ 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7,
0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF,
/* C */ 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7,
0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF,
/* D */ 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7,
0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF,
/* E */ 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7,
0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF,
/* F */ 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7,
0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF,
// Table 9 (for high byte 0xFE)
/* 0 */ 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07,
0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F,
/* 1 */ 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17,
0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F,
/* 2 */ 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27,
0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F,
/* 3 */ 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37,
0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F,
/* 4 */ 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47,
0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F,
/* 5 */ 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57,
0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F,
/* 6 */ 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67,
0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F,
/* 7 */ 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77,
0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F,
/* 8 */ 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87,
0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F,
/* 9 */ 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97,
0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F,
/* A */ 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7,
0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF,
/* B */ 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7,
0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF,
/* C */ 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7,
0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF,
/* D */ 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7,
0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF,
/* E */ 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7,
0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
/* F */ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7,
0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000,
// Table 10 (for high byte 0xFF)
/* 0 */ 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07,
0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,
/* 1 */ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,
/* 2 */ 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
/* 3 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
/* 4 */ 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
/* 5 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F,
/* 6 */ 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
/* 7 */ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
/* 8 */ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87,
0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
/* 9 */ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97,
0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
/* A */ 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7,
0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF,
/* B */ 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7,
0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF,
/* C */ 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7,
0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF,
/* D */ 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7,
0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF,
/* E */ 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7,
0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF,
/* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7,
0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF,
};
hfsplus-1.0.4/libhfsp/src/Makefile.am 0100644 0000000 0000000 00000002466 07442225010 016155 0 ustar root root # Makefile.am for libhfsp/src, used by automake
# Created by Klaus Kaempf
#
# Copyright (C) 2000 Klaus Halfmann
# Original code 1996-1998 by Robert Leslie
# other work 2000 from Brad Boyer (flar@pants.nu)
#
# 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.
#
# $Id: Makefile.am,v 1.2 2002/03/08 21:15:52 klaus Exp $
#
lib_LTLIBRARIES = libhfsp.la
libhfsp_la_SOURCES = \
blockiter.c btree.c btreecheck.c fscheck.c hfstime.c libhfsp.c os.c unicode.c \
record.c volume.c partitions.c
CFLAGS = -O2 -Wall
# I need to clean up these headers first before i can distribute them ...
# include_HEADERS = apple.h hfs.h hfsp.h libhfsp.h
hfsplus-1.0.4/libhfsp/src/apple.h 0100644 0000000 0000000 00000011242 07442744341 015400 0 ustar root root /*
* libhfsp - library for reading and writing Macintosh HFS+ volumes
*
* This file contains defintions that are special for Apple.
* The names match the defintions found in Apple Header files.
*
* Copyright (C) 2000 Klaus Halfmann
* Original code 1996-1998 by Robert Leslie
* other work 2000 from Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: apple.h,v 1.3 2002/03/10 20:58:09 klaus Exp $
*/
#define APPLE_H
typedef signed char Char;
typedef unsigned char UChar;
typedef signed char SInt8;
typedef unsigned char UInt8;
typedef signed short SInt16;
typedef unsigned short UInt16;
typedef signed long SInt32;
typedef unsigned long UInt32;
typedef unsigned long OSType;
typedef unsigned long long UInt64;
#define PARTITION_SIG 0x504d /* 'PM' */
typedef struct {
UInt16 pmSig; /* partition signature: should be 'PM' */
UInt16 pmSigPad; /* reserved stuff */
UInt32 pmMapBlkCnt; /* number of blocks in partition map */
UInt32 pmPyPartStart; /* startblock of the partition */
UInt32 pmPartBlkCnt; /* number of blocks in partition */
char pmPartName[ 32]; /* partition name */
char pmPartType[ 32]; /* partition type */
UInt32 pmLgDataStart; /* first logical block of data area */
UInt32 pmDataCnt; /* number of blocks in data area */
UInt32 pmPartStatus; /* partition status information */
UInt32 pmLgBootStart; /* first logical block of boot code */
UInt32 pmBootSize; /* size of boot code, in bytes */
UInt32 pmBootAddr; /* boot code load address */
UInt32 pmBootAddr2; /* reserved */
UInt32 pmBootEntry; /* boot code entry point */
UInt32 pmBootEntry2; /* reserved */
UInt32 pmBootCksum; /* boot code checksum */
char pmProcessor[ 16]; /* processor type */
UInt16 pmPad[ 188]; /* reserved, sums up with the rest to 512 */
} Partition;
/* A point, normally used by Quickdraw,
* but found in Finderinformation, too
*/
typedef struct {
SInt16 v; /* vertical coordinate */
SInt16 h; /* horizontal coordinate */
} Point;
/* A rectancle, normally used by Quickdraw,
* but found in Finderinformation, too.
*/
typedef struct {
SInt16 top; /* top edge of rectangle */
SInt16 left; /* left edge */
SInt16 bottom; /* bottom edge */
SInt16 right; /* right edge */
} Rect;
/* Information about the location and size of a folder
* used by the Finder.
*/
typedef struct {
Rect frRect; /* folder's rectangle */
SInt16 frFlags; /* flags */
Point frLocation; /* folder's location */
SInt16 frView; /* folder's view */
} DInfo;
/* Extended folder information used by the Finder ...
*/
typedef struct {
Point frScroll; /* scroll position */
SInt32 frOpenChain; /* directory ID chain of open folders */
SInt16 frUnused; /* reserved */
SInt16 frComment; /* comment ID */
SInt32 frPutAway; /* directory ID */
} DXInfo;
/* Finder information for a File
*/
typedef struct {
OSType fdType; /* file type */
OSType fdCreator; /* file's creator */
SInt16 fdFlags; /* flags */
Point fdLocation; /* file's location */
SInt16 fdFldr; /* file's window */
} FInfo;
/* Extendend Finder Information for a file
*/
typedef struct {
SInt16 fdIconID; /* icon ID */
SInt16 fdUnused[4]; /* reserved */
SInt16 fdComment; /* comment ID */
SInt32 fdPutAway; /* home directory ID */
} FXInfo;
/* Flagvalues for FInfo and DInfo */
# 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)
hfsplus-1.0.4/libhfsp/src/blockiter.c 0100644 0000000 0000000 00000007500 07441220604 016240 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes
*
* The iterator shown here iterates over the blocks of a fork.
*
* Copyright (C) 2000 Klaus Halfmann
* Original work by 1996-1998 Robert Leslie
* other work 2000 from Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: blockiter.c,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include
# include
# include
# include
# include
# include "libhfsp.h"
# include "blockiter.h"
# include "volume.h"
# include "record.h"
# include "btree.h"
# include "os.h"
# include "swab.h"
# include "hfstime.h"
/* Initialize iterator for a given fork */
void blockiter_init(blockiter* b, volume* vol, hfsp_fork_raw* f,
UInt8 forktype, UInt32 fileId)
{
b->vol = vol;
b->curr_block = 0;
b->block = 0;
b->max_block = f->total_blocks;
b->fileId = fileId;
b->index = 0;
b->file = f->extents;
b->e = f->extents;
b->forktype = forktype;
b->in_extent = 0;
}
/* get next extent record when needed */
static int blockiter_next_extent(blockiter *b)
{
btree* extents_tree = volume_get_extents_tree(b->vol);
int err;
b->index = 0;
if (b->in_extent) // already using extents record ?
{
err = record_next_extent(&b->er);
// Hope there is no need to check this ...
// if (b->er.key.start_block != b->curr_block)
// HFSP_ERROR(ENOENT,
// "Extents record inconistent");
}
else
{
err = record_init_file(&b->er, extents_tree, b->forktype,
b->fileId, b->curr_block);
b->in_extent = -1; // true
}
b->e = b->er.extent;
return err;
}
/* find next block of the fork iterating over */
int blockiter_next(blockiter *b)
{
b->curr_block ++;
b->block ++;
if (b->curr_block >= b->max_block)
return -1; // end of Blocks, but no error
// in current part of extent ?
if (b->block >= b->e->block_count)
{
b->index++;
b->block = 0; // reset relative position
b->e++;
if (b -> index >= 8) // need to fetch another extent
{
if (blockiter_next_extent(b))
HFSP_ERROR(ENOENT, "Extends record not found.");
}
}
return 0;
fail:
return -1;
}
/* skip the indicated number of blocks */
int blockiter_skip(blockiter *b, UInt32 skip)
{
while (skip > 0)
{
// Skip to skip or end of current extent
UInt32 diff = b->e->block_count - b->block;
if (skip < diff)
{
diff = skip;
skip = 0;
}
else
skip -= diff;
b->curr_block += diff;
b->block += diff;
if (b->curr_block >= b->max_block)
return -1; // end of Blocks, but no error
if (b->block >= b->e->block_count)
{
b->index++;
b->block = 0; // reset relative position
b->e++;
if (b -> index >= 8) // need to fetch another extent
{
if (blockiter_next_extent(b))
HFSP_ERROR(ENOENT, "Extends record not found.");
}
}
} // we are here when skip was null, thats ok
return 0;
fail:
return -1;
}
/* return current block */
UInt32 blockiter_curr(blockiter *b) /* inline */
{
return b->e->start_block + b->block;
}
hfsplus-1.0.4/libhfsp/src/blockiter.h 0100644 0000000 0000000 00000004330 07441220604 016243 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes
*
* The iterator shown here iterates over the blocks of a fork.
*
* Copyright (C) 2000 Klaus Halfmann
* Original work by 1996-1998 Robert Leslie
* other work 2000 from Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: blockiter.h,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
*/
/* Structure of the blockiterator */
typedef struct
{
volume* vol; // volume we iterate over
UInt32 curr_block; // current, absolute block
UInt32 block; // relative block in current extent
UInt32 max_block; // Maximum allowed block
UInt32 fileId; // id of file we iterate over
int index; // 0 .. 7 in current extent
hfsp_extent* file; // original extent record from file
hfsp_extent* e; // current extentent under examination
UInt8 forktype; // type of fork we iterate over
UInt8 in_extent; // boolean 0 - in file extent
// 1 - in extents file
extent_record er; // record to iterate in extents file.
} blockiter;
/* Initialize iterator for a given fork */
extern void blockiter_init(blockiter* b, volume* vol, hfsp_fork_raw* f,
UInt8 forktype, UInt32 fileId);
/* find next block of the fork iterating over */
extern int blockiter_next(blockiter *b);
/* skip the indicated number of blocks */
extern int blockiter_skip(blockiter *b, UInt32 skip);
/* return current block */
extern inline UInt32 blockiter_curr(blockiter *b)
{
return b->e->start_block + b->block;
}
hfsplus-1.0.4/libhfsp/src/btree.c 0100644 0000000 0000000 00000046357 07441220604 015400 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes
* The fucntions are used to handle the various forms of btrees
* found on HFS+ volumes.
*
* The functions are used to handle the various forms of btrees
* found on HFS+ volumes.
*
* Copyright (C) 2000 Klaus Halfmann
* Original 1996-1998 Robert Leslie
* Additional work by Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: btree.c,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include
# include
# include
# include
# include
# include "libhfsp.h"
# include "volume.h"
# include "btree.h"
# include "record.h"
# include "swab.h"
/* Read the node from the given buffer and swap the bytes.
*
* return pointer after reading the structure
*/
void* btree_readnode(btree_node_desc* node, void *p)
{
node->next = bswabU32_inc(p);
node->prev = bswabU32_inc(p);
node->kind = bswabU8_inc(p);
node->height = bswabU8_inc(p);
node->num_rec = bswabU16_inc(p);
node->reserved = bswabU16_inc(p);
return p;
}
/* Write the node to the given buffer and swap the bytes.
*
* return pointer after writing the structure
*/
void* btree_writenode(btree_node_desc* node, void *p)
{
bstoreU32_inc(p, node->next);
bstoreU32_inc(p, node->prev);
bstoreU8_inc (p, node->kind);
bstoreU8_inc (p, node->height);
bstoreU16_inc(p, node->num_rec);
bstoreU16_inc(p, node->reserved);
return p;
}
/* read a btree header from the given buffer and swap the bytes.
*
* return pointer after reading the structure
*/
void* btree_readhead(btree_head* head, void *p)
{
int i;
head->depth = bswabU16_inc(p);
head->root = bswabU32_inc(p);
head->leaf_count = bswabU32_inc(p);
head->leaf_head = bswabU32_inc(p);
head->leaf_tail = bswabU32_inc(p);
head->node_size = bswabU16_inc(p);
head->max_key_len = bswabU16_inc(p);
head->node_count = bswabU32_inc(p);
head->free_nodes = bswabU32_inc(p);
head->reserved1 = bswabU16_inc(p);
head->clump_size = bswabU32_inc(p);
head->btree_type = bswabU8_inc(p);
head->reserved2 = bswabU8_inc(p);
head->attributes = bswabU32_inc(p);
for (i=0; i < 16; i++)
head->reserved3[i] = bswabU32_inc(p);
return p;
}
/* read a btree header from the given buffer and swap the bytes.
*
* return pointer after reading the structure
*/
void* btree_writehead(btree_head* head, void *p)
{
int i;
bstoreU16_inc(p, head->depth);
bstoreU32_inc(p, head->root);
bstoreU32_inc(p, head->leaf_count);
bstoreU32_inc(p, head->leaf_head);
bstoreU32_inc(p, head->leaf_tail);
bstoreU16_inc(p, head->node_size);
bstoreU16_inc(p, head->max_key_len);
bstoreU32_inc(p, head->node_count);
bstoreU32_inc(p, head->free_nodes);
bstoreU16_inc(p, head->reserved1);
bstoreU32_inc(p, head->clump_size);
bstoreU8_inc (p, head->btree_type);
bstoreU8_inc (p, head->reserved2);
bstoreU32_inc(p, head->attributes);
for (i=0; i < 16; i++)
bstoreU32_inc(p, head->reserved3[i]);
return p;
}
/* Intialize cache with default cache Size,
* must call node_cache_close to deallocate memory */
int node_cache_init(node_cache* cache, btree* tree, int size)
{
int nodebufsize;
char * buf;
cache->size = size;
cache->currindex = 0;
nodebufsize = tree->head.node_size + sizeof(node_buf);
buf = malloc(size *(sizeof(node_entry) + nodebufsize));
if (!buf)
return -1;
cache -> nodebufsize = nodebufsize;
cache -> entries = (node_entry*) buf;
cache -> buffers = (char*) &cache->entries[size];
bzero(cache->entries, size*sizeof(node_entry));
return 0;
}
/* Like cache->buffers[i], since size of node_buf is variable */
static inline node_buf* node_buf_get(node_cache* cache, int i)
{
return (node_buf*) (cache->buffers + (i * cache->nodebufsize));
}
/* write back a node at given node in fork with nodebuf */
static int btree_write_node(btree* bt, int index, char* nodebuf)
{
UInt16 blkpernode = bt->blkpernode;
UInt16 nodeperblk = bt->nodeperblk;
if (blkpernode)
{
return volume_writetofork(bt->vol, nodebuf, bt->fork,
index * blkpernode, blkpernode, HFSP_EXTENT_DATA, bt->cnid);
}
else // use nodeperblk, must reread other blocks, too
{
char buf[bt->vol->blksize];
UInt16 node_size = bt->head.node_size;
UInt16 offset = (index % nodeperblk) * node_size;
int block = index / nodeperblk;
// read block including this one
void* p = volume_readfromfork(bt->vol, buf, bt->fork,
block, 1, HFSP_EXTENT_DATA, bt->cnid);
if (p != buf) // usually NULL
return -1; // evil ...
p = &nodebuf[offset]; // node is found at that offset
memcpy(p, nodebuf, node_size);
if (volume_writetofork(bt->vol, buf, bt->fork,
block, 1, HFSP_EXTENT_DATA, bt->cnid))
return -1; // evil ...
}
return 0; // all is fine
}
/* flush the node at cache index */
static int node_cache_flush_node(btree* bt, int index)
{
node_entry *e = &bt->cache.entries[index];
int result = 0;
int node_index = e->index;
// Only write back valid, dirty nodes
if(e->index && (e->flags & NODE_DIRTY))
{
node_buf* b = node_buf_get(&bt->cache, index);
if (!b->index)
{
hfsp_error = "cache inconsistency in node_cache_flush_node";
return -1;
}
// Write back node header to cached memory
btree_writenode(&b->desc, b->node);
result = btree_write_node(bt, node_index, b->node);
b->index = 0; // invalidate block entry
}
e->index = 0; // invalidate cache entry
return result; // all is fine
}
/* flush the cache */
static int node_cache_flush(btree* bt)
{
int i, size = bt->cache.size;
int result = 0;
for (i=0; i < size; i++)
{
node_entry* e = &bt->cache.entries[i];
if(e->index && (e->flags & NODE_DIRTY))
if (node_cache_flush_node(bt, i))
result = -1;
}
return result;
}
static int node_cache_close(btree* bt)
{
int result = 0;
if (!bt->cache.entries) // not (fully) intialized ?
return result;
result = node_cache_flush(bt);
free(bt->cache.entries);
return result;
}
/* Load the cach node indentified by index with
* the node identified by node_index.
*
* Set the inital flags as given.
*/
static node_buf* node_cache_load_buf
(btree* bt, node_cache* cache, int index, UInt16 node_index, int flags)
{
node_buf *result = node_buf_get(cache ,index);
UInt16 blkpernode = bt->blkpernode;
UInt16 nodeperblk = bt->nodeperblk;
node_entry *e = &cache->entries[index];
UInt32 block;
void *p;
if (blkpernode)
{
block = node_index * blkpernode;
p = volume_readfromfork(bt->vol, result->node, bt->fork,
block, blkpernode, HFSP_EXTENT_DATA, bt->cnid);
if (!p)
return NULL; // evil ...
btree_readnode(&result->desc, p);
}
else // use nodeperblk
{
char buf[bt->vol->blksize];
UInt16 node_size = bt->head.node_size;
UInt16 offset = node_index % nodeperblk * node_size;
block = node_index / nodeperblk;
p = volume_readfromfork(bt->vol, buf, bt->fork,
block, 1, HFSP_EXTENT_DATA, bt->cnid);
if (p != buf) // usually NULL
return NULL; // evil ...
p = &buf[offset]; // node is found at that offset
memcpy(&result->node, p , node_size);
btree_readnode(&result->desc, p);
}
result->index = node_index;
e -> priority = result->desc.height * DEPTH_FACTOR;
e -> index = node_index;
e -> flags = flags;
return result;
}
/* Mark node at given index dirty in cache.
*/
inline static void btree_dirty_node(btree* bt, UInt16 index)
{
node_cache* cache = &bt->cache;
node_entry *e = &cache->entries[index];
e->flags |= NODE_DIRTY;
}
/* Read node at given index, using cache.
*
* Make node with given flag, usually NODE_CLEAN/NODE_DIRTY
*/
node_buf* btree_node_by_index(btree* bt, UInt16 index, int flags)
{
node_cache* cache = &bt->cache;
int oldindex, lruindex;
int currindex = cache->currindex;
UInt32 prio;
node_entry *e;
// Shortcut acces to current node, will not change priorities
if (cache->entries[currindex].index == index)
{
cache->entries[currindex].flags |= flags;
return node_buf_get(cache ,currindex);
}
oldindex = currindex;
if (currindex == 0)
currindex = cache->size;
currindex--;
lruindex = oldindex; // entry to be flushed when needed
prio = 0; // current priority
while (currindex != oldindex) // round robin
{
e = &cache->entries[currindex];
if (e->index == index) // got it
{
if (e->priority != 0) // already top, uuh
e->priority--;
cache->currindex = currindex;
e -> flags |= flags;
return node_buf_get(cache ,currindex);
}
else
{
if (!e->index) // free entry, well
{
lruindex = currindex;
prio = UINT_MAX; // remember empty entry
}
if (e->priority != UINT_MAX) // already least, uuh
e->priority++;
}
if (prio < e->priority)
{
lruindex = currindex;
prio = e->priority;
}
if (currindex == 0)
currindex = cache->size;
currindex--;
}
e = &cache->entries[lruindex];
cache->currindex = lruindex;
if (e->flags & NODE_DIRTY)
node_cache_flush_node(bt, lruindex);
return node_cache_load_buf (bt, cache, lruindex, index, flags);
}
/** intialize the btree with the first entry in the fork */
static int btree_init(btree* bt, volume* vol, hfsp_fork_raw* fork)
{
void *p;
char buf[vol->blksize];
UInt16 node_size;
btree_node_desc* node = &bt->head_node;
int alloc_size;
bt->vol = vol;
bt->fork = fork;
p = volume_readfromfork(vol, buf, fork, 0, 1,
HFSP_EXTENT_DATA, bt->cnid);
if (!p)
return -1;
p = btree_readnode(node, p);
if (node->kind != HFSP_NODE_HEAD)
return -1; // should not happen ?
p = btree_readhead(&bt->head, p);
node_size = bt->head.node_size;
bt->blkpernode = node_size / vol->blksize;
if (bt->blkpernode == 0) // maybe the other way round ?
bt->nodeperblk = vol->blksize / node_size;
alloc_size = node_size - HEADER_RESERVEDOFFSET; // sizeof(node_desc) + sizeof(header)
/* Sometimes the node_size is bigger than the volume-blocksize
* so here I reread the node when needed */
{ // need new block for allocation
char nodebuf[node_size];
if (bt->blkpernode > 1)
{
p = volume_readfromfork(vol, nodebuf, fork, 0, bt->blkpernode,
HFSP_EXTENT_DATA, bt->cnid);
((char*) p) += HEADER_RESERVEDOFFSET; // skip header
}
bt->alloc_bits = malloc(alloc_size);
if (!bt->alloc_bits)
return ENOMEM;
memcpy(bt->alloc_bits, p, alloc_size);
}
/*** for debugging ***/
// bt->attributes |= BTREE_HEADDIRTY;
if (node_cache_init(&bt->cache, bt, bt->head.depth + EXTRA_CACHESIZE))
return -1;
return 0;
}
/** Intialize catalog btree, so that btree_close can safely be called. */
void btree_reset(btree* bt)
{
bt->alloc_bits = NULL;
bt->cache.entries = NULL;
}
/** Intialize catalog btree */
int btree_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork)
{
int result = btree_init(bt,vol,fork); // super (...)
bt->cnid = HFSP_CAT_CNID;
bt->kcomp = record_key_compare;
bt->kread = record_readkey;
bt->rread = record_readentry;
bt->max_rec_size = sizeof(hfsp_cat_entry);
// this is a bit too large due to alignment/padding
return result;
}
/** Intialize catalog btree */
int btree_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork)
{
int result = btree_init(bt,vol,fork); // super (...)
bt->cnid = HFSP_EXT_CNID;
bt->kcomp = record_extent_key_compare;
bt->kread = record_extent_readkey;
bt->rread = record_extent_readrecord;
bt->max_rec_size = sizeof(hfsp_extent);
return result;
}
/** close the btree and free any resources */
int btree_close(btree* bt)
{
int result = 0;
node_cache_close(bt);
// a dirty header without alloc_bits must not happen, mmh
if ((bt->attributes & BTREE_HEADDIRTY) && bt->alloc_bits)
{
btree_head* head = &bt->head;
btree_node_desc* node = &bt->head_node;
UInt16 node_size = head->node_size;
UInt16 alloc_size = node_size - HEADER_RESERVEDOFFSET;
char buf[node_size];
void *p;
p = btree_writenode(node, buf);
p = btree_writehead(head, p);
memcpy(p, bt->alloc_bits, alloc_size);
result = btree_write_node(bt, 0, buf);
}
if (bt->alloc_bits)
free(bt->alloc_bits);
return result;
}
/* returns pointer to key given by index in current node.
*
* Assumes that current node is not NODE_HEAD ...
* index may be == num_rec in whcih case a pointer
* to the first free byte is returned ...
*/
void* btree_key_by_index(btree* bt, node_buf* buf, UInt16 index)
{
UInt16 node_size, off_pos;
btree_record_offset offset;
if (index > buf->desc.num_rec) // oops out of range
{
hfsp_error = "btree_key_by_index: index out of range";
return NULL;
}
node_size = bt->head.node_size;
// The offsets are found at the end of the node ...
off_pos = node_size - (index +1) * sizeof(btree_record_offset);
// position of offset at end of node
if (off_pos >= node_size) // oops out of range
{
hfsp_error = "btree_key_by_index: off_pos out of range";
return NULL;
}
offset = bswabU16(*((btree_record_offset*) (buf->node + off_pos)));
if (offset >= node_size) // oops out of range
{
hfsp_error = "btree_key_by_index: offset out of range";
return NULL;
}
// now we have the offset and can read the key ...
return buf->node + offset;
}
/** return allocation status of node given by index in btree */
int btree_check_nodealloc(btree* bt, UInt16 node)
{
btree_head* head = &bt->head;
btree_node_desc* desc = &bt->head_node;
UInt16 node_size = head->node_size;
UInt16 node_num = desc->next;
UInt32 node_count = head->node_count;
char* alloc_bits = bt->alloc_bits + 128; // skip reserved node
int bit = node & 0x07;
int alloc_size = node_size - 256;
// sizeof(node_desc) + sizeof(header) + 128 - 8
node_buf* nbuf = NULL;
if (node >= node_count)
HFSP_ERROR(-1, "Node index out of range.");
node >>= 3;
// First must check bits in saved allocation bits from node header
if (node < alloc_size)
return (alloc_bits[node] & (0x80 >> bit)); /* Bit one is 0x80 ! */
// Now load matching node by iterating over MAP-Nodes
node -= alloc_size;
while (node_num && node >= node_size)
{
nbuf = btree_node_by_index(bt, node_num, NODE_CLEAN);
if (!nbuf)
HFSP_ERROR(-1, "Unable to fetch map node");
desc = &nbuf->desc;
if (desc->kind != HFSP_NODE_MAP)
HFSP_ERROR(-1, "Invalid chain of map nodes");
node -= node_size;
node = desc->next;
}
if (!nbuf)
HFSP_ERROR(-1, "Oops this code is wrong"); // Should not happen, oops
return (nbuf->node[node] & (0x80 >> bit)); /* Bit one is 0x80 ! */
fail:
return -1;
}
/* Remove the key and an (eventual) record from the btree.
* Warning, you must WRITELOCK the btree before calling this
*/
int btree_remove_record(btree* bt, UInt16 node_index, UInt16 keyind)
{
node_buf* node = btree_node_by_index(bt, node_index, NODE_DIRTY);
btree_node_desc* desc = &node->desc;
int num_rec = desc->num_rec;
void* curr = btree_key_by_index(bt, node, keyind);
if (keyind != num_rec) // Last record needs no special action
{
void *next = btree_key_by_index(bt, node, keyind+1);
void *last = btree_key_by_index(bt, node, num_rec);
// difference needed to update the backpointers
int diff = ((char*) next) - ((char*) curr);
// hfsp_key* key = (hfsp_key*) curr;
// UInt16 help = key->key_length;
// size of the block to move "down"
int size = ((char*) last) - ((char*) next);
UInt16 node_size = bt->head.node_size;
int i,n, off_pos;
btree_record_offset* offsets;
btree_record_offset old;
memmove(curr, next, size);
// Now care about the backpointers,
off_pos = node_size - (num_rec + 1) * sizeof(btree_record_offset);
offsets = (btree_record_offset*) (node->node + off_pos);
// fprintf(stderr,
// "moving backpointers in node %d by %4x (%d)\n",
// node_index, diff, help);
// The backpointer at keyind is already correct
n = num_rec - keyind;
old = 0xffff;
// will override former index to free area, thats ok
for (i=0; i <= n; i++)
{
btree_record_offset off = offsets[i];
// fprintf(stderr, "moving backpointers %4x, %4x\n", off, old);
offsets[i] = old;
old = off - diff; // adjust the backpointer
}
}
desc->num_rec = num_rec - 1;
if (desc->kind == HFSP_NODE_LEAF)
{
bt->head.leaf_count --;
bt->attributes |= BTREE_HEADDIRTY;
}
return 0;
}
/* insert a key and an (eventual) record into the btree.
* Warning, you must WRITELOCK the btree before calling this.
* keyind may well be == num_rec indicating an append.
*
* node_index number of the node in the tree.
* keyind the index where the key/record should be insert in the node
* key the key (+ record) to append
* len the lenght of the key or key + record
*/
int btree_insert_record(btree* bt, UInt16 node_index, UInt16 keyind,
void* key, int len)
{
node_buf* node = btree_node_by_index(bt, node_index, NODE_DIRTY);
btree_node_desc* desc = &node->desc;
int num_rec = desc->num_rec;
UInt16 node_size= bt->head.node_size;
void *curr,*last; // Pointer for calculations
int size, total;
int i,n,off_pos;
btree_record_offset* offsets;
curr = btree_key_by_index(bt, node, keyind);
last = btree_key_by_index(bt, node, num_rec);
// size of the block to move "up"
size = ((char*) last) - ((char*) curr);
total = ((char*) last) - node->node;
// account for backpointers, too
if ((total + len) > (node_size - num_rec * sizeof(btree_record_offset)))
return -1; // need to split/repartition node first, NYI
memmove(curr + len, curr, size);
// printf("Moving to [%p %p]\n", curr+len, curr+len+size);
memcpy (curr , key , len); // Copy the key / record
num_rec ++;
// Now care about the backpointers,
off_pos = node_size - (num_rec + 1) * sizeof(btree_record_offset);
offsets = (btree_record_offset*) (node->node + off_pos);
// Recalculate backpointers
n = num_rec - keyind;
// printf("Copying to [%p %p]\n", offsets, &offsets[n]);
for (i=0; i < n; i++)
offsets[i] = offsets[i+1] + len;
desc->num_rec = num_rec; // Adjust node descriptor
if (desc->kind == HFSP_NODE_LEAF)
{
bt->head.leaf_count ++;
bt->attributes |= BTREE_HEADDIRTY;
}
return 0;
}
hfsplus-1.0.4/libhfsp/src/btree.h 0100644 0000000 0000000 00000006353 07441220604 015375 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes.
*
* The fucntions are used to handle the various forms of btrees
* found on HFS+ volumes.
*
* Copyright (C) 2000 Klaus Halfmann
* Original 1996-1998 Robert Leslie
* Additional work by Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: btree.h,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
*/
/* Read the node from the given buffer and swap the bytes.
*
* return pointer after reading the structure
*/
void* btree_readnode(btree_node_desc* node, void *p);
/* read a btree header from the given buffer and swap the bytes.
*
* return pointer after reading the structure
*/
void* btree_readhead(btree_head* head, void *p);
/** Intialize catalog btree, so that btree_close can safely be called. */
extern void btree_reset(btree* bt);
/** Intialize catalog btree */
extern int btree_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork);
/** Intialize extents btree */
extern int btree_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork);
/** close the btree and free any resources */
extern int btree_close(btree* bt);
/* Read node at given index.
*
* Make node with given flag, usually NODE_CLEAN/NODE_DIRTY
*/
extern node_buf* btree_node_by_index(btree* bt, UInt16 index, int flags);
/* returns pointer to key given by index in current node */
extern void* btree_key_by_index(btree* bt, node_buf* buf, UInt16 index);
/* remove the key and record from the btree.
* Warning, you must WRITELOCK the btree before calling this */
extern int btree_remove_record(btree* bt, UInt16 node_index, UInt16 recind);
/* insert a key and an (eventual) record into the btree.
* Warning, you must WRITELOCK the btree before calling this */
extern int btree_insert_record(btree* bt, UInt16 node_index, UInt16 keyind,
void* key, int len);
// --------------- Cache Handling ------------
/* Priority of the depth of the node compared to LRU value.
* Should be the average number of keys per node but these vary. */
#define DEPTH_FACTOR 1000
/* Cache size is height of tree + this value
* Really big numbers wont help in case of ls -R
* Must be enough to cache all nodes (+ Map nodes !)
* used during tree reorganizations to avoid
* inconsistent states before flush
*/
#define EXTRA_CACHESIZE 3
/* Intialize cache with default cache Size,
* must call node_cache_close to deallocate memory */
extern int node_cache_init(node_cache* cache, btree* tree, int size);
/** return allocation status of node given by index in btree */
extern int btree_check_nodealloc(btree* bt, UInt16 node);
hfsplus-1.0.4/libhfsp/src/btreecheck.c 0100644 0000000 0000000 00000072111 07441220605 016362 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes
*
* This code checks the btreee structures of a HFS+ volume for correctnes.
*
* Copyright (C) 2000 Klaus Halfmann
* Original 1996-1998 Robert Leslie
* Additional work by Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: btreecheck.c,v 1.1.1.1 2002/03/05 19:50:29 klaus Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include
# include
# include
# include
# include
# include
# include "libhfsp.h"
# include "volume.h"
# include "fscheck.h"
# include "btree.h"
# include "record.h"
# include "hfstime.h"
# include "unicode.h"
# include "swab.h"
/** helper function to print those Apple 4 byte Signatures */
static inline void print_sig(UInt32 sig)
{
printf("%c%c%c%c" ,
((char*)&sig)[0], ((char*)&sig)[1],
((char*)&sig)[2], ((char*)&sig)[3]);
}
/* print the key of a record */
static void record_print_key(hfsp_cat_key* key)
{
char buf[255]; // mh this _might_ overflow
unicode_uni2asc(buf, &key->name, 255);
printf("parent cnid : %ld\n", key->parent_cnid);
printf("name : %s\n", buf);
}
/* Check the btree header as far as possible.
*/
static int fscheck_checkbtree(btree* bt)
{
int result = 0;
btree_head* head = &bt->head;
UInt16 node_size = head->node_size;
UInt32 node_count = head->node_count;
UInt32 blocksize = bt->vol->vol.blocksize;
// head->depth to be checked later
if (node_size % HFSP_BLOCKSZ)
{
printf("node_size %d not a multiple of HFSP_BLOCKSZ %d\n",
node_size, HFSP_BLOCKSZ);
result |= FSCK_ERR; // dont know how to fix that by now
}
/* This is quite ok for a newly created extends-tree
if (!head->root)
{
printf("root node must not be 0\n");
result |= FSCK_ERR; // dont know how to fix that by now
}
*/
if (head->root >= node_count)
{
printf("root node out of range %lX >= %lX\n",
head->root, node_count);
result |= FSCK_ERR; // This is really evil
}
if (head->leaf_head >= node_count)
{
printf("leaf_head out of range %lX >= %lX\n",
head->leaf_head, node_count);
result |= FSCK_ERR; // dont know how to fix that by now
}
if (head->leaf_tail >= node_count)
{
printf("leaf_head out of range %lX >= %lX\n",
head->leaf_tail, node_count);
result |= FSCK_ERR; // dont know how to fix that by now
}
if (head->max_key_len < HFSP_CAT_KEY_MIN_LEN)
{
printf("max key len small %d < %d\n",
head->max_key_len, HFSP_CAT_KEY_MIN_LEN);
result |= FSCK_ERR; // dont know how to fix that by now
}
if (head->max_key_len > HFSP_CAT_KEY_MAX_LEN)
{
printf("max key to large %d > %d\n",
head->max_key_len, HFSP_CAT_KEY_MAX_LEN);
result |= FSCK_ERR; // dont know how to fix that by now
}
if (head->free_nodes >= node_count)
{
printf("free_nodes out of range %lX >= %lX\n",
head->free_nodes, node_count);
result |= FSCK_ERR; // dont know how to fix that by now
}
// head->reserved1 nothing to check here
if (head->clump_size % blocksize)
{
printf("clump_size %ld not a multiple of blocksize %ld\n",
head->free_nodes, blocksize);
result |= FSCK_ERR; // dont know how to fix that by now
}
if (head->btree_type != 0)
{
printf("Unexpected btree_type %d\n" , head->btree_type);
result |= FSCK_ERR; // dont know how to fix that by now
}
// head->reserved2 nothing to check here
if (head->attributes & HFSPLUS_TREE_RESERVED)
{
printf("Unexpected bits in btree header node attributes %lX\n",
head->attributes);
result |= FSCK_ERR; // dont know how to fix that by now
}
return result;
}
/* print btree header node information */
static void btree_printhead(btree_head* head)
{
UInt32 attr;
printf(" depth : %#X\n", head->depth);
printf(" root : %#lX\n", head->root);
printf(" leaf_count : %#lX\n", head->leaf_count);
printf(" leaf_head : %#lX\n", head->leaf_head);
printf(" leaf_tail : %#lX\n", head->leaf_tail);
printf(" node_size : %#X\n", head->node_size);
printf(" max_key_len : %#X\n", head->max_key_len);
printf(" node_count : %#lX\n", head->node_count);
printf(" free_nodes : %#lX\n", head->free_nodes);
printf(" reserved1 : %#X\n", head->reserved1);
printf(" clump_size : %#lX\n", head->clump_size);
printf(" btree_type : %#X\n", head->btree_type);
attr = head->attributes;
printf(" reserved2 : %#X\n", head->reserved2);
if (attr & HFSPLUS_BAD_CLOSE)
printf(" HFSPLUS_BAD_CLOSE *** ");
else
printf(" !HFSPLUS_BAD_CLOSE");
if (attr & HFSPLUS_TREE_BIGKEYS)
printf(" HFSPLUS_TREE_BIGKEYS ");
else
printf(" !HFSPLUS_TREE_BIGKEYS");
if (attr & HFSPLUS_TREE_VAR_NDXKEY_SIZE)
printf(" HFSPLUS_TREE_VAR_NDXKEY_SIZE");
else
printf(" !HFSPLUS_TREE_VAR_NDXKEY_SIZE");
if (attr & HFSPLUS_TREE_UNUSED)
printf(" HFSPLUS_TREE_UNUSED ***\n");
printf("\n");
}
/* Dump a node descriptor to stdout */
static void print_node_desc(UInt32 nodeIndex, btree_node_desc* node)
{
printf("Node descriptor for Node %ld\n", nodeIndex);
printf("next : %#lX\n", node->next);
printf("prev : %#lX\n", node->prev);
printf("height : %#X\n", node->height);
printf("num_rec : %d\n", node->num_rec);
printf("reserved : %#X\n", node->reserved);
printf("height : %#X\n", node->height);
switch(node->kind)
{
case HFSP_NODE_NDX :
printf("HFSP_NODE_NDX\n");
break;
case HFSP_NODE_HEAD :
printf("HFSP_NODE_HEAD\n");
break;
case HFSP_NODE_MAP :
printf("HFSP_NODE_MAP\n");
break;
case HFSP_NODE_LEAF :
printf("HFSP_NODE_LEAF\n");
break;
default:
printf("*** Unknown Node type ***\n");
}
}
/** intialize the btree with the first entry in the fork */
static int fscheck_btree_init(btree* bt, volume* vol, hfsp_fork_raw* fork)
{
void *p;
char buf[vol->blksize];
UInt16 node_size;
btree_node_desc* node = &bt->head_node;
int result;
int alloc_size;
bt->vol = vol;
bt->fork = fork;
p = volume_readfromfork(vol, buf, fork, 0, 1,
HFSP_EXTENT_DATA, bt->cnid);
if (!p)
{
printf("Unable to read block 1 of b*tree for cnid:%ld\n", bt->cnid);
return FSCK_ERR;
}
p = btree_readnode(node, p);
if (node->prev != 0)
{
printf("Backlink of header node is not zero (%lX) \n", node->prev);
return FSCK_ERR; // ToDo: We might ignore it but ???
}
if (node->kind != HFSP_NODE_HEAD)
{
printf("Unexpected node kind (%d) for node Header\n", node->kind);
return FSCK_ERR; // ToDo: We might ignore it but ???
}
p = btree_readhead(&bt->head, p);
node_size = bt->head.node_size;
bt->blkpernode = node_size / vol->blksize;
if (bt->blkpernode == 0) // maybe the other way round ?
bt->nodeperblk = vol->blksize / node_size;
else
{
if (bt->blkpernode * vol->blksize != node_size)
{
printf("node_size (%X) is no multiple of block size (%X)\n",
node_size, bt->blkpernode);
return FSCK_ERR; // Thats fatal as of now
}
}
alloc_size = node_size - HEADER_RESERVEDOFFSET; // sizeof(node_desc) + sizeof(header)
/* Sometimes the node_size is bigger than the volume-blocksize
* so here I reread the node when needed */
{ // need new block for allocation
char nodebuf[node_size];
if (bt->blkpernode > 1)
{
p = volume_readfromfork(vol, nodebuf, fork, 0, bt->blkpernode,
HFSP_EXTENT_DATA, bt->cnid);
((char*) p) += HEADER_RESERVEDOFFSET; // skip header
}
bt->alloc_bits = malloc(alloc_size);
if (!bt->alloc_bits)
return ENOMEM;
memcpy(bt->alloc_bits, p, alloc_size);
}
result = fscheck_checkbtree(bt);
if (fsck_data.verbose)
btree_printhead(&bt->head);
node_cache_init(&bt->cache, bt, bt->head.depth + EXTRA_CACHESIZE);
return result;
}
/** Intialize catalog btree */
int fscheck_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork)
{
int result = fscheck_btree_init(bt,vol,fork); // super (...)
bt->cnid = HFSP_CAT_CNID;
bt->kcomp = record_key_compare;
bt->kread = record_readkey;
bt->rread = record_readentry;
bt->max_rec_size = sizeof(hfsp_cat_entry);
return result;
}
/** Intialize catalog btree */
int fscheck_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork)
{
int result = fscheck_btree_init(bt,vol,fork); // super (...)
bt->cnid = HFSP_EXT_CNID;
bt->kcomp = record_extent_key_compare;
bt->kread = record_extent_readkey;
bt->rread = record_extent_readrecord;
bt->max_rec_size = sizeof(hfsp_extent);
return result;
}
/* Used to create the extents btree */
int fscheck_create_extents_tree(volume* vol)
{
btree* result = (btree*) ALLOC(btree*, sizeof(btree));
int retval = 0;
if (!result)
{
printf("No memory for extents btree\n");
return FSCK_ERR;
}
if (FSCK_FATAL & (retval =
fscheck_init_extent(result, vol, &vol->vol.ext_file)))
{
vol->extents = NULL;
return retval;
}
vol->extents = result;
return retval;
}
/* returns pointer to key given by index in current node.
* Same as btree_key_by_index, but with more checks etc.
*
* Assumes that current node is not NODE_HEAD ...
* index may be == num_rec in whcih case a pointer
* to the first free byte is returned ...
*/
static void* checkbtree_key_by_index(btree* bt, UInt32 node, node_buf* buf, UInt16 index)
{
UInt16 node_size, off_pos;
btree_record_offset offset;
if (index > buf->desc.num_rec) // oops out of range
{
fprintf(stderr,"checkbtree_key_by_index: index out of range %u > %u\n",
index, buf->desc.num_rec);
return NULL;
}
node_size = bt->head.node_size;
// The offsets are found at the end of the node ...
off_pos = node_size - (index +1) * sizeof(btree_record_offset);
// position of offset at end of node
if (off_pos >= node_size) // oops out of range
{
fprintf(stderr,"checkbtree_key_by_index: off_pos out of range "
"%X >= %X\n", off_pos, node_size);
return NULL;
}
offset = *((btree_record_offset*) (buf->node + off_pos));
if (offset >= node_size) // oops out of range
{
fprintf (stderr, "checkbtree_key_by_index: offset out of range %X >= %X\n",
offset, node_size);
return NULL;
}
if (fsck_data.verbose)
{
printf("Node %4ld, Record %2d is at pos %04X,"
"Backptr is at offset %04X\n", node, index, offset, off_pos);
}
// now we have the offset and can read the key ...
#if BYTE_ORDER == LITTLE_ENDIAN
return buf->node + bswap_16(offset);
#else
return buf->node + offset;
#endif
}
/* Try to fix a node when the backpointers are broken.
*
* This is done by crawling forward as long as the keys
* are valid and checking/adjusting the backpointers.
* This may result in the loss of records in case a
* key (or record) is damaged.
*/
static int fscheck_fix_node(btree* bt, UInt32 nodeIndex)
{
int result = FSCK_NOERR;
node_buf* node = btree_node_by_index(bt, nodeIndex, NODE_CLEAN);
btree_node_desc* desc = &node->desc;
UInt16 num_rec = desc->num_rec;
UInt16 i;
int isindex = desc->kind == HFSP_NODE_NDX;
void* current = node->node + 0x0E; // sizeof (btree_node_desc)
char kbuf[bt->head.max_key_len]; // dummy key to skip over
char buf[bt->max_rec_size];
fprintf(stderr, "Node %lu with %u records is damaged trying to fix ***\n",
nodeIndex, num_rec);
for (i=0; i < num_rec; i++)
{
void *p = checkbtree_key_by_index(bt, nodeIndex, node, i);
if (!p)
return result | FSCK_ERR;
if (p != current)
{
fprintf(stderr,
"Key %u in Node %lu is damaged "
"rest of keys will be droppend ***\n", i,nodeIndex);
break;
}
p = bt->kread(p, kbuf); // Read the key
if (!isindex)
p = bt->rread(p, buf);
}
if (i < num_rec)
{
fprintf(stderr,
"Code to drop damaged record not yet implemented ***.\n");
}
// ToDo: check for pointer to free area, too
return result;
}
/* recursive function to check a node (given by its index).
*
* In case of an index node is descends into the subnodes.
*/
static int fscheck_btree_node(btree* bt, UInt32 nodeIndex, hfsp_key** key1, hfsp_key** key2)
{
int result = FSCK_NOERR;
node_buf* node = btree_node_by_index(bt, nodeIndex, NODE_CLEAN);
btree_node_desc* desc = &node->desc;
UInt16 num_rec = desc->num_rec;
UInt16 i;
int isindex = desc->kind == HFSP_NODE_NDX;
hfsp_key* tmp;
void* previous = ((char*)node) + 0x0E; // sizeof btree_node_desc
if (fsck_data.verbose)
print_node_desc(nodeIndex, desc);
for (i=0; i= %p)\n", nodeIndex, i, p, previous);
result |= FSCK_FSCORR; // Hope we can correct that later
}
previous = p;
p = bt->kread(p, *key1); // Read the key
if (!p)
{
result |= FSCK_ERR;
// Lets try to fix that Error ....
fscheck_fix_node(bt, nodeIndex);
if (fsck_data.ignoreErr)
continue; // Hope this will work
return result;
}
if ((*key2)->key_length)
{
int comp = bt->kcomp(*key1, *key2);
if (comp > 0)
{
printf("Invalid key order in node %ld record %d\n key1=",
nodeIndex, i);
record_print_key((hfsp_cat_key*) *key1);
printf("Invalid key order key2=\n");
record_print_key((hfsp_cat_key*) *key2);
result |= FSCK_FSCORR; // Hope we can correct that later
}
if (comp == 0 && i > 0) // equal to key in parent node is ok
{
printf("Duplicate key in node %ld record %d key1=\n",
nodeIndex, i);
record_print_key((hfsp_cat_key*) *key1);
printf("Duplicate key key2=\n");
record_print_key((hfsp_cat_key*) *key2);
result |= FSCK_FSCORR; // Hope we can correct that later
}
}
tmp = *key1; // Swap buffers for next compare
*key1 = *key2;
*key2 = tmp;
if (isindex)
{
index = bswabU32_inc(p);
result |= fscheck_btree_node(bt, index, key1, key2);
}
if (result & FSCK_FATAL)
break;
}
return result;
}
/** Check a complete btree by traversing it in-oder */
int fscheck_btree(btree *bt)
{
UInt16 maxkeylen = bt->head.max_key_len;
int result = FSCK_NOERR;
char keybuf1[maxkeylen];
char keybuf2[maxkeylen];
hfsp_key* key1 = (hfsp_key*) keybuf1; // Alternating buffers
hfsp_key* key2 = (hfsp_key*) keybuf2; // for key Compare
key2->key_length = 0; // So first compare can be skipped
result = fscheck_btree_node(bt, bt->head.root, &key1, &key2);
return result;
}
/* print Quickdraw Point */
static void record_print_Point(Point* p)
{
printf("[ v=%d, h=%d ]", p->v, p->h);
}
/* print Quickdraw Rect */
static void record_print_Rect(Rect* r)
{
printf("[ top=%d, left=%d, bottom=%d, right=%d ]",
r->top, r->left, r->bottom, r->right);
}
/* print permissions */
static void record_print_perm(hfsp_perm* perm)
{
printf("owner : %ld\n", perm->owner);
printf("group : %ld\n", perm->group);
printf("perm : 0x%lX\n",perm->mode);
printf("dev : %ld\n", perm->dev);
}
/* print Directory info */
static void record_print_DInfo(DInfo* dinfo)
{
printf( "frRect : "); record_print_Rect(&dinfo->frRect);
printf("\nfrFlags : 0X%X\n", dinfo->frFlags);
printf( "frLocation : "); record_print_Point(&dinfo->frLocation);
printf("\nfrView : 0X%X\n", dinfo->frView);
}
/* print extended Directory info */
static void record_print_DXInfo(DXInfo* xinfo)
{
printf( "frScroll : "); record_print_Point(&xinfo->frScroll);
printf("\nfrOpenChain : %ld\n", xinfo->frOpenChain);
printf( "frUnused : %d\n", xinfo->frUnused);
printf( "frComment : %d\n", xinfo->frComment);
printf( "frPutAway : %ld\n", xinfo->frPutAway);
}
static void record_print_folder(hfsp_cat_folder* folder)
{
printf("flags : 0x%X\n", folder->flags);
printf("valence : 0x%lX\n", folder->valence);
printf("id : %ld\n", folder->id);
printf("create_date : %s", get_atime(folder->create_date));
printf("content_mod_date : %s", get_atime(folder->content_mod_date));
printf("attribute_mod_date : %s", get_atime(folder->attribute_mod_date));
printf("access_date : %s", get_atime(folder->access_date));
printf("backup_date : %s", get_atime(folder->backup_date));
record_print_perm (&folder->permissions);
record_print_DInfo (&folder->user_info);
record_print_DXInfo (&folder->finder_info);
printf("text_encoding : 0x%lX\n", folder->text_encoding);
printf("reserved : 0x%lX\n", folder->reserved);
}
/* print File info */
static void record_print_FInfo(FInfo* finfo)
{
printf( "fdType : %4.4s\n", (char*) &finfo->fdType);
printf( "fdCreator : %4.4s\n", (char*) &finfo->fdCreator);
printf( "fdFlags : 0X%X\n", finfo->fdFlags);
printf( "fdLocation : "); record_print_Point(&finfo->fdLocation);
printf("\nfdFldr : %d\n", finfo->fdFldr);
}
/* print extended File info */
static void record_print_FXInfo(FXInfo* xinfo)
{
printf( "fdIconID : %d\n", xinfo->fdIconID);
// xinfo -> fdUnused;
printf( "fdComment : %d\n", xinfo->fdComment);
printf( "fdPutAway : %ld\n", xinfo->fdPutAway);
}
/* print file entry */
static void record_print_file(hfsp_cat_file* file)
{
printf("flags : 0x%X\n", file->flags);
printf("reserved1 : 0x%lX\n", file->reserved1);
printf("id : %ld\n", file->id);
printf("create_date : %s", get_atime(file->create_date));
printf("content_mod_date : %s", get_atime(file->content_mod_date));
printf("attribute_mod_date : %s", get_atime(file->attribute_mod_date));
printf("access_date : %s", get_atime(file->access_date));
printf("backup_date : %s", get_atime(file->backup_date));
record_print_perm (&file->permissions);
record_print_FInfo (&file->user_info);
record_print_FXInfo (&file->finder_info);
printf("text_encoding : 0x%lX\n", file->text_encoding);
printf("reserved : 0x%lX\n", file->reserved2);
printf("Datafork:\n");
print_fork (&file->data_fork);
printf("Rsrcfork:\n");
print_fork (&file->res_fork);
}
/* print info for a file or folder thread */
static void record_print_thread(hfsp_cat_thread* entry)
{
char buf[255]; // mh this _might_ overflow
unicode_uni2asc(buf, &entry->nodeName, 255);
printf("parent cnid : %ld\n", entry->parentID);
printf("name : %s\n" , buf);
}
/* print the information for a record */
static void record_print_entry(hfsp_cat_entry* entry)
{
switch (entry->type)
{
case HFSP_FOLDER:
printf("=== Folder ===\n");
return record_print_folder(&entry->u.folder);
case HFSP_FILE:
printf("=== File ===\n");
return record_print_file (&entry->u.file);
case HFSP_FOLDER_THREAD:
printf("=== Folder Thread ===\n");
return record_print_thread(&entry->u.thread);
case HFSP_FILE_THREAD:
printf("=== File Thread ==\n");
return record_print_thread(&entry->u.thread);
default:
printf("=== Unknown Record Type ===\n");
};
}
/* Dump all the record information to stdout */
void record_print(record* r)
{
printf ("*** Key index : %u\n", r->keyind);
record_print_key (&r->key);
record_print_entry(&r->record);
}
/** Check the key of a catalog record */
static int fscheck_unistr255(hfsp_unistr255* name)
{
int result = FSCK_NOERR;
if (name->strlen > 255)
{
printf("strlen in name %d > 255\n", name->strlen);
result |= FSCK_FSCORR; // hope we can fix that some time
}
return result;
}
/** Check the key of a catalog record */
static int fscheck_cat_key(record* r)
{
int result = FSCK_NOERR;
hfsp_cat_key* key = &r->key;
hfsp_unistr255* name = &key->name;
volume* vol = r->tree->vol;
UInt32 cnid = vol->vol.next_cnid;
result |= fscheck_unistr255(name);
if (key->key_length != ((name->strlen << 1) + 6))
{
printf("key_length in key %3d does not match %3d name\n",
key->key_length, name->strlen);
result |= FSCK_FSCORR; // hope we can fix that some time
}
if (key->parent_cnid >= cnid)
{
printf("parent_cnid %ld >= volume next cnid %ld\n",
key->parent_cnid, cnid);
result |= FSCK_FSCORR; // hope we can fix that some time
}
return result;
}
/** Check a macintosh time
*
* errname is the anem of the field to show on errror
*/
static int fscheck_mactime(UInt32 time, char* errname)
{
/* This happens so often that be better ignore it
if (!time)
printf("Warning %s is 0\n", errname);
*/
if (time > fsck_data.macNow)
printf("Warning %21.21s is in the future: (%lX) %s",
errname, time, get_atime(time));
return FSCK_NOERR; // Those are not really bad, just annoying
}
/** Check the file part of a catalog record */
static int fscheck_file(btree* tree, hfsp_cat_file* file)
{
volume* vol = tree->vol;
int result = FSCK_NOERR;
UInt32 cnid = vol->vol.next_cnid;
if (file->flags & HFSP_FILE_RESERVED)
printf("Warning unknown file flags: %X\n", file->flags);
if (fsck_data.maxCnid < file->id)
fsck_data.maxCnid = file->id;
// file->reserved1 // Nothing to check here
if (file->id >= cnid)
{
printf("file id %ld >= volume next cnid %ld\n",
file->id, cnid);
result |= FSCK_FSCORR; // hope we can fix that some time
}
result |= fscheck_mactime(file->create_date, "file create_date");
result |= fscheck_mactime(file->content_mod_date, "file content_mod_date");
result |= fscheck_mactime(file->attribute_mod_date, "file attribute_mod_date");
result |= fscheck_mactime(file->access_date, "file access_date");
result |= fscheck_mactime(file->backup_date, "file backup_date");
/*
// folder->permissions // dont know how tho check these
Nothing to be checked here (but finder may become confused, hmm)
file->user_info;
file->finder_info;
file->text_encoding;
file->reserved;
*/
result |= check_forkalloc(vol, &file->data_fork);
result |= check_forkalloc(vol, &file->res_fork);
return result;
}
/** Check the folder part of a catalog record */
static int fscheck_folder(btree* tree, hfsp_cat_folder* folder)
{
UInt32 cnid = tree->vol->vol.next_cnid;
int result = FSCK_NOERR;
if (folder->flags & HFSP_FOLDER_RESERVED)
printf("Warning unknown folder flags: %X\n", folder->flags);
if (fsck_data.maxCnid < folder->id)
fsck_data.maxCnid = folder->id;
// folder->valence // to be checked later
if (folder->id >= cnid)
{
printf("Folder id %ld >= volume next cnid %ld\n",
folder->id, cnid);
result |= FSCK_FSCORR; // hope we can fix that some time
}
result |= fscheck_mactime(folder->create_date, "folder create_date");
result |= fscheck_mactime(folder->content_mod_date, "folder content_mod_date");
result |= fscheck_mactime(folder->attribute_mod_date,"folder attribute_mod_date");
result |= fscheck_mactime(folder->access_date, "folder access_date");
result |= fscheck_mactime(folder->backup_date, "folder backup_date");
/*
// folder->permissions // dont know how tho check these
Nothing to be checked here (but finder may become confused, hmm)
folder->user_info;
folder->finder_info;
folder->text_encoding;
folder->reserved;
*/
return result;
}
/** Check the entry part of a catalog record */
static int fscheck_thread(btree* tree, hfsp_cat_thread* thread)
{
UInt32 cnid = tree->vol->vol.next_cnid;
int result = fscheck_unistr255(&thread->nodeName);
if (thread->parentID >= cnid)
{
printf("Thread parentID %ld >= volume next cnid %ld\n",
thread->parentID, cnid);
result |= FSCK_FSCORR; // hope we can fix that some time
}
return result;
}
/** Check the entry part of a catalog record */
static int fscheck_entry(record* r)
{
hfsp_cat_entry *entry = &r->record;
btree *tree = r->tree;
switch (entry->type)
{
case HFSP_FOLDER:
return fscheck_folder(tree, &entry->u.folder);
case HFSP_FILE:
return fscheck_file (tree, &entry->u.file);
case HFSP_FOLDER_THREAD:
return fscheck_thread(tree, &entry->u.thread);
case HFSP_FILE_THREAD:
return fscheck_thread(tree, &entry->u.thread);
default:
printf("Unknown Record Type %X\n", entry->type);
return FSCK_FSCORR; // Hope we can fix it some time
}
}
/** Check a record as a directory, file, extent_node etc. */
static int fscheck_record(record* r)
{
int result = fscheck_cat_key(r);
result |= fscheck_entry(r);
if (fsck_data.verbose)
record_print(r);
return result;
}
/* find correct node record for given node and *pindex.
*
* index of record in this (or next) node
*/
static node_buf* fscheck_prepare_next(btree* tree, UInt16 node_index,
UInt16* pindex, int* fsckerr)
{
node_buf* buf = btree_node_by_index(tree, node_index, NODE_CLEAN);
btree_node_desc* desc;
UInt32 numrec;
if (!buf)
return buf;
desc = &buf->desc;
numrec = desc->num_rec;
if (*pindex >= numrec) // move on to next node
{
UInt16 next = desc->next;
*pindex = 0;
if (!next /* is there a next node ? */
|| !( buf = btree_node_by_index(tree, next, NODE_CLEAN)))
return NULL;
if (!btree_check_nodealloc(tree, next))
{
printf("node %d not allocated in node Map\n", next);
*fsckerr = *fsckerr | FSCK_FSCORR; /* Maybe we can correct that one time */
}
}
return buf;
}
/* intialize the catalog record with the given index entry in the btree.
*
* Special version to check for consistency of backpointers.
*
* r the record used as read buffer.
* bt the btree we care for
*/
int fscheck_record_init(record* r, btree* bt, node_buf* buf, UInt16 index)
{
void *p,*p1,*p2;
int diff;
r-> tree = bt;
p = p1 = checkbtree_key_by_index(bt,r->node_index,buf,index);
if (!p)
return -1;
p = record_readkey (p, &r->key);
if (!p)
return -1;
p = record_readentry(p, &r->record);
if (!p)
return -1;
r->node_index = buf->index;
r-> keyind = index;
p2 = checkbtree_key_by_index(bt,r->node_index,buf,index+1);
diff = (int) (p2 - p);
if (diff) // The difference may still be correct in case of a hole in the
{ // structure (should happen while debugging only)
fprintf(stderr,
"Unexpected difference in Node %d, Record %d "
": %d (%d/%d) (%p,%p)\n",
r->node_index, index, diff , p - p1, p2 - p1, p, p2);
record_print(r);
}
return 0;
}
/* move record foreward to next entry in leaf nodes.
*
* In case of an error the value of *r is undefined !
*/
int fscheck_record_next(record* r, int* fsckerr)
{
btree* tree = r->tree;
UInt16 index = r->keyind +1;
UInt32 parent;
node_buf* buf = fscheck_prepare_next(
tree, r->node_index, &index, fsckerr);
if (!buf)
return ENOENT; // No (more) such file or directory
parent = r->key.parent_cnid;
if (fscheck_record_init(r, tree, buf, index))
{
printf("Unable to read record %d in node %d"
,index, r->node_index);
return -1;
}
return 0;
}
/** Check all files in leaf nodes */
int fscheck_files(volume* vol)
{
int result = FSCK_NOERR;
btree* catalog = &vol->catalog;
node_buf* buf =
btree_node_by_index(catalog,catalog->head.leaf_head, NODE_CLEAN);
// void* p = btree_key_by_index(catalog,buf,0);
record r;
if (!btree_check_nodealloc(catalog, catalog->head.leaf_head))
{
printf("leaf_head %ld not allocated in node Map\n",
catalog->head.leaf_head);
result |= FSCK_FSCORR; /* Maybe we can correct that one time */
}
if (fscheck_record_init(&r, catalog, buf, 0))
{
printf("Unable to read initial leaf record\n");
return FSCK_ERR;
}
do {
result |= fscheck_record(&r);
if (result & FSCK_FATAL)
return result;
} while (!fscheck_record_next(&r, &result));
return result;
}
hfsplus-1.0.4/libhfsp/src/debug.txt 0100644 0000000 0000000 00000000101 07441220605 015734 0 ustar root root 18725ae
25ce < perm
25de < Dinfo
25ee < DXinfo
2606
hfsplus-1.0.4/libhfsp/src/fscheck.c 0100644 0000000 0000000 00000042570 07447643325 015715 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes
*
* This code checks the structures of a HFS+ volume for correctnes.
*
* ToDo: care come about HPFSCHK_IGNOREERR
*
* Copyright (C) 2000 Klaus Halfmann
* Original 1996-1998 Robert Leslie
* Additional work by Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: fscheck.c,v 1.2 2002/03/25 15:48:37 klaus Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include
# include
# include
# include
# include
# include
# include "libhfsp.h"
# include "fscheck.h"
# include "volume.h"
# include "btree.h"
# include "record.h"
# include "hfstime.h"
# include "unicode.h"
# include "os.h"
# include "swab.h"
/* Dump all raw fork information to stdout */
void print_fork(hfsp_fork_raw* f)
{
int i;
hfsp_extent* e;
printf("total_size : %#LX\n" , f->total_size);
printf("clump_size : %#lX\n" , f->clump_size);
printf("total_blocks : %#lX\n" , f->total_blocks);
printf("extents : ");
for (i=0; i < 8; i++)
{
e = &f->extents[i];
printf("(%#lX+%#lX) " , e->start_block,e->block_count);
}
printf("\n");
}
/** helper function to print those Apple 4 byte Signatures */
static inline void print_sig(UInt32 sig)
{
printf("%c%c%c%c" ,
((char*)&sig)[0], ((char*)&sig)[1],
((char*)&sig)[2], ((char*)&sig)[3]);
}
/* Dump all the volume information to stdout */
void volume_print(hfsp_vh* vh)
{
printf("signature : %c%c\n" , ((char*)&vh->signature)[0],
((char*)&vh->signature)[1]);
printf("version : %u\n" , vh->version);
printf("attributes : %#lX\n" , vh->attributes);
printf("last_mount_vers : "); print_sig(vh->last_mount_vers);
printf("\nreserved : %lu\n" , vh->reserved);
/* Hmm this is in local, apple time ... */
printf("create_date : %s" , get_atime(vh->create_date));
printf("modify_date : %s" , get_atime(vh->modify_date));
printf("backup_date : %s" , get_atime(vh->backup_date));
printf("checked_date : %s" , get_atime(vh->checked_date));
printf("file_count : %lu\n" , vh->file_count);
printf("folder_count : %lu\n" , vh->folder_count);
printf("blocksize : %lX\n" , vh->blocksize);
printf("total_blocks : %lu\n" , vh->total_blocks);
printf("free_blocks : %lu\n" , vh->free_blocks);
printf("next_alloc : %lu\n" , vh->next_alloc);
printf("rsrc_clump_sz : %lu\n" , vh->rsrc_clump_sz);
printf("data_clump_sz : %lu\n" , vh->data_clump_sz);
printf("next_cnid : %lu\n" , vh->next_cnid);
printf("write_count : %lu\n" , vh->write_count);
printf("encodings_bmp : %#LX\n" , vh->encodings_bmp);
/* vv->finder_info, p, 32); */
printf(" Allocation file\n");
print_fork(&vh->alloc_file);
printf(" Extension file\n");
print_fork(&vh->ext_file);
printf(" Catalog file\n");
print_fork(&vh->cat_file);
printf(" Attribute file\n");
print_fork(&vh->attr_file);
printf(" Start file\n");
print_fork(&vh->start_file);
}
/* Check all fields of the volume header.
*/
static int fscheck_volume_header(volume * vol, hfsp_vh* vh)
{
UInt32 attributes = vh->attributes;
int result = 0;
// vh->signature // already checked in read
// vh->version // Current is 4 but I wont check that
if (attributes & HFSPLUS_VOL_RESERVED1)
printf("Reserved attribute in use: %lX\n",
vh->attributes & HFSPLUS_VOL_RESERVED1);
if (! (attributes & HFSPLUS_VOL_UNMNT))
printf("Volume was not cleanly unmounted\n");
if (fsck_data.verbose && (attributes & HFSPLUS_VOL_SPARE_BLK))
printf("Volume has spare (bad) blocks\n");
if (fsck_data.verbose && (attributes & HFSPLUS_VOL_NOCACHE))
printf("Volume should not be cached (ignored)\n");
if (attributes & HFSPLUS_VOL_INCNSTNT)
printf("Volume is inconsistent\n");
if (attributes & HFSPLUS_VOL_RESERVED2)
printf("Reserved attribute in use: %lX\n",
vh->attributes & HFSPLUS_VOL_RESERVED2);
if (fsck_data.verbose && (attributes & HFSPLUS_VOL_SOFTLOCK))
printf("Volume is soft locked");
if (attributes & HFSPLUS_VOL_RESERVED3)
printf("Reserved attribute in use: %lX\n",
vh->attributes & HFSPLUS_VOL_RESERVED3);
switch (vh->last_mount_vers)
{
case HPAPPLE_SIGNATURE:
if (fsck_data.verbose)
{
printf("Volume was last Mounted by Apple:\n");
print_sig(vh->last_mount_vers);
}
break;
case HPLS_SIGNATURE:
if (fsck_data.verbose)
{
printf("Volume was last Mounted by hfsplusutils: \n");
print_sig(vh->last_mount_vers);
}
break;
case HPLS_SIGRES1:
if (fsck_data.verbose)
{
printf("Volume was last Mounted by hfsplus kernel module: \n");
print_sig(vh->last_mount_vers);
}
break;
default:
printf("Volume was last Mounted by unknnown implemenatation: \n");
print_sig(vh->last_mount_vers);
}
// vh->reserved // not checked
// vh->file_count // To be checked later
// vh->folder_count // To be checked later
if (0 != (vh->blocksize % HFSP_BLOCKSZ)) // must be multiple of BLKSZ
{
printf("Invalid Blocksize %lX\n", vh->blocksize);
result = FSCK_ERR; // Wont try to correct that, yet.
}
{
UInt64 totalbytes = vh->total_blocks * vh->blocksize;
UInt64 expectedbytes = vol->maxblocks << vol->blksize_bits;
if (totalbytes > expectedbytes)
printf("\nInvalid total blocks %lX, expected %lX",
vh->total_blocks, (UInt32)(expectedbytes / vh->blocksize));
}
if (vh->free_blocks > vh->total_blocks)
printf("More free blocks (%lX) than total (%lX) ?\n",
vh->free_blocks, vh->total_blocks);
// Check more later
// vh->next_alloc // to be checked later
// vh->rsrc_clump_sz // no check needed, is a hint only
// vh->data_clump_sz // no check needed, is a hint only
if (vh->next_cnid <= HFSP_MIN_CNID) // wil hopefully be fixed later
printf("Invalid next_cnid: %ld\n", vh->next_cnid);
// Check more later
// vh->write_count // no check possible
// vh->encodings_bmp // no check needed, is a hint only
// vh->finder_info // not checked (why should I?)
// vh->alloc_file // to be checked later
// vh->ext_file // to be checked later
// vh->cat_file // to be checked later
// vh->attr_file // to be checked later
// vh->start_file // to be checked later
return result;
}
/* Read the volume from the given buffer and swap the bytes.
*/
static int fscheck_volume_readbuf(volume * vol, hfsp_vh* vh, void* p)
{
if ( (vh->signature = bswabU16_inc(p)) != HFSP_VOLHEAD_SIG)
{
printf("Unexpected Volume signature '%2s' expected 'H+'\n",
(char*) &vh->signature);
HFSP_ERROR(-1, "This is not a HFS+ volume");
}
vh->version = bswabU16_inc(p);
vh->attributes = bswabU32_inc(p);
vh->last_mount_vers = bswabU32_inc(p);
vh->reserved = bswabU32_inc(p);
vh->create_date = bswabU32_inc(p);
vh->modify_date = bswabU32_inc(p);
vh->backup_date = bswabU32_inc(p);
vh->checked_date = bswabU32_inc(p);
vh->file_count = bswabU32_inc(p);
vh->folder_count = bswabU32_inc(p);
vh->blocksize = bswabU32_inc(p);
vh->total_blocks = bswabU32_inc(p);
vh->free_blocks = bswabU32_inc(p);
vh->next_alloc = bswabU32_inc(p);
vh->rsrc_clump_sz = bswabU32_inc(p);
vh->data_clump_sz = bswabU32_inc(p);
vh->next_cnid = bswabU32_inc(p);
vh->write_count = bswabU32_inc(p);
vh->encodings_bmp = bswabU64_inc(p);
memcpy(vh->finder_info, p, 32);
((char*) p) += 32; // So finderinfo must be swapped later, ***
p = volume_readfork(p, &vh->alloc_file );
p = volume_readfork(p, &vh->ext_file );
p = volume_readfork(p, &vh->cat_file );
p = volume_readfork(p, &vh->attr_file );
p = volume_readfork(p, &vh->start_file );
if (fsck_data.verbose)
volume_print(vh);
return 0;
fail:
return -1;
}
/* Read the volume from the given block */
static int fscheck_volume_read(volume * vol, hfsp_vh* vh, UInt32 block)
{
char buf[vol->blksize];
if (volume_readinbuf(vol, buf, block))
return -1;
return fscheck_volume_readbuf(vol, vh, buf);
}
/* Find out wether the volume is wrapped and unwrap it eventually */
static int fscheck_read_wrapper(volume * vol, hfsp_vh* vh)
{
UInt16 signature;
char buf[vol->blksize];
void *p = buf;
if( volume_readinbuf(vol, buf, 2) ) // Wrapper or volume header starts here
return -1;
signature = bswabU16_inc(p);
if (signature == HFS_VOLHEAD_SIG) /* Wrapper */
{
UInt32 drAlBlkSiz; /* size (in bytes) of allocation blocks */
UInt32 sect_per_block; /* how may block build an hfs sector */
UInt16 drAlBlSt; /* first allocation block in volume */
UInt16 embeds, embedl; /* Start/lenght of embedded area in blocks */
if (fsck_data.verbose)
printf("Volume is wrapped in HFS volume "
" (use hfsck to check this)\n");
((char*) p) += 0x12; /* skip unneded HFS vol fields */
drAlBlkSiz = bswabU32_inc(p); /* offset 0x14 */
((char*) p) += 0x4; /* skip unneded HFS vol fields */
drAlBlSt = bswabU16_inc(p); /* offset 0x1C */
((char*) p) += 0x5E; /* skip unneded HFS vol fields */
signature = bswabU16_inc(p); /* offset 0x7C, drEmbedSigWord */
if (signature != HFSP_VOLHEAD_SIG)
HFSP_ERROR(-1, "This looks like a normal HFS volume");
embeds = bswabU16_inc(p);
embedl = bswabU16_inc(p);
sect_per_block = (drAlBlkSiz / HFSP_BLOCKSZ);
if ((sect_per_block * HFSP_BLOCKSZ) != drAlBlkSiz)
{
printf("HFS Blocksize %lX is not multiple of %X\n",
drAlBlkSiz, HFSP_BLOCKSZ);
return FSCK_ERR; // Cant help it (for now)
}
// end is absolute (not relative to HFS+ start)
vol->maxblocks = embedl * sect_per_block;
os_offset = ((UInt64) (drAlBlSt + embeds * sect_per_block))
<< HFS_BLOCKSZ_BITS;
/* Now we can try to read the embedded HFS+ volume header */
if (fsck_data.verbose)
printf("Embedded HFS+ volume at 0x%LX (0x%lX) of 0x%X sized Blocks\n",
os_offset, vol->maxblocks, HFSP_BLOCKSZ);
return fscheck_volume_read(vol,vh,2);
}
else if (signature == HFSP_VOLHEAD_SIG) /* Native HFS+ volume */
{
if (fsck_data.verbose)
printf("This HFS+ volume is not wrapped.\n");
p = buf; // Restore to begin of block
return fscheck_volume_readbuf(vol, vh, p);
} else
HFSP_ERROR(-1, "Neither Wrapper nor native HFS+ volume header found");
fail:
return FSCK_ERR;
}
/* Check wether all blocks of a fork are marked as allocated.
*
* returns number of errors found.
*/
int check_forkalloc(volume* vol, hfsp_fork_raw* fork)
{
int i;
hfsp_extent* e;
UInt32 block, count;
int errcount = 0;
for (i=0; i < 8; i++)
{
e = &fork->extents[i];
block = e->start_block;
count = e->block_count;
while (count > 0)
{
if (!volume_allocated(vol, block))
{
printf("Warning block %lX not marked as allocated\n",block);
errcount++;
}
count --;
block ++;
}
} // Hope we can correct that some time
return errcount > 0 ? FSCK_FSCORR : FSCK_NOERR;
}
/* Check allocation of the volume (part1).
The raw blocks in the voume header are checked. */
static int check_alloc1(volume* vol)
{
hfsp_vh* vh = &vol->vol;
int result = 0;
result |= check_forkalloc(vol, &vh->alloc_file);
result |= check_forkalloc(vol, &vh->ext_file);
result |= check_forkalloc(vol, &vh->cat_file);
result |= check_forkalloc(vol, &vh->attr_file);
result |= check_forkalloc(vol, &vh->start_file);
return result;
}
/* internal function used to create the extents btree */
static int fscheck_create_extents_tree(volume* vol)
{
btree* result = (btree*) ALLOC(btree*, sizeof(btree));
int retval = 0;
if (!result)
{
printf("No memory for extents btree\n");
return FSCK_ERR;
}
if (FSCK_FATAL & (retval =
fscheck_init_extent(result, vol, &vol->vol.ext_file)))
{
vol->extents = NULL;
return retval;
}
vol->extents = result;
return retval;
}
/* Open the device, read and verify the volume header,
* check the extents and catalog b-tree. */
int fscheck_volume_open(volume* vol, char* devname, int rw)
{
hfsp_vh backup; /* backup volume found at second to last block */
long sect_per_block;
int shift;
int result = 0;
vol->blksize_bits = HFSP_BLOCKSZ_BITS;
vol->blksize = HFSP_BLOCKSZ;
vol->extents = NULL; /* Thanks to Jeremias Sauceda */
/* vol->maxblocks = os_seek(&vol->fd, -1, HFSP_BLOCKSZ_BITS); */
/* This wont work for /dev/... but we do not really need it */
vol->maxblocks = 3;
btree_reset(&vol->catalog);
if (os_open(&vol->fd, devname, rw))
return FSCK_ERR | result;
printf("*** Checking Volume Header:\n");
if (fscheck_read_wrapper(vol, &vol->vol))
return FSCK_ERR | result;
result |= fscheck_volume_header(vol, &vol->vol);
printf("\t\t\t\t\t\tDone ***\n");
printf("*** Checking Backup Volume Header:\n");
if (fscheck_volume_read(vol, &backup, vol->maxblocks - 2))
return FSCK_ERR | result;
result |= fscheck_volume_header(vol, &backup);
printf("\t\t\t\t\t\tDone ***\n");
if (result & FSCK_FATAL)
{
printf("\t\t\t\t*** Check stopped ***\n");
return result; // Further checking impossible
}
/* Now switch blksize from HFSP_BLOCKSZ (512) to value given in header
and adjust depend values accordingly, after that a block always
means a HFS+ allocation size */
/* Usually 4096 / 512 == 8 */
sect_per_block = vol->vol.blocksize / HFSP_BLOCKSZ;
shift = 0;
if (sect_per_block > 1)
{
shift = 1;
while (sect_per_block > 2)
{
sect_per_block >>=1;
shift++;
} /* shift = 3 */
}
vol -> blksize_bits += shift;
vol -> blksize = 1 << vol->blksize_bits;
vol -> maxblocks = vol->vol.total_blocks; /* cant calculate via shift ? */
result |= check_alloc1(vol); // This should not be fatal ..
// For fschek the extents tree is created first
printf("*** Checking Extents Btree:\n");
result |= fscheck_create_extents_tree(vol);
if ( !(result & FSCK_FATAL))
result |= fscheck_btree(vol->extents);
if ((result & FSCK_FATAL) && !fsck_data.ignoreErr)
{
printf("\t\t\t\t*** Check stopped ***\n");
return result; // Further checking impossible
}
printf("\t\t\t\t\t\tDone ***\n");
printf("*** Checking Catalog Btree:\n");
result |= fscheck_init_cat(&vol->catalog, vol, &vol->vol.cat_file);
if ( !(result & FSCK_FATAL) || !fsck_data.ignoreErr)
result |= fscheck_btree(&vol->catalog);
if ((result & FSCK_FATAL) && !fsck_data.ignoreErr)
{
printf("\t\t\t\t*** Check stopped ***\n");
return result; // Further checking impossible
}
printf("\t\t\t\t\t\tDone ***\n");
return result;
}
/* Initialize fsck_data to some default values */
static void fsck_init()
{
fsck_data.maxCnid = 0;
fsck_data.verbose = 0;
fsck_data.ignoreErr = 0;
}
/* Do the minimal check required after an unclean mount.
*
* The volume should be mounted readonly.
*
* returns the highest cnid found. 0 denotes an error.
* In case of error the volume should not be used at all.
*/
UInt32 minimal_check(volume* vol)
{
fsck_init(); // minimal check is not verbose
// An additional check for allocation wont hurt
if (fscheck_files(vol))
fsck_data.maxCnid = 0;
return fsck_data.maxCnid;
}
/* Do usefull checks, practice will tell what this is.
*
* returns the highest cnid found. 0 denotes an error.
* In case of error the volume may still be useable.
*/
int hfsplus_check(char* device, int flags)
{
volume vol;
int result;
fsck_init();
fsck_data.verbose = 0 != (flags & HFSPCHECK_VERBOSE);
fsck_data.ignoreErr = 0 != (flags & HFSPCHECK_IGNOREERR);
fsck_data.macNow = HFSPTIMEDIFF + time(NULL);
result = fscheck_volume_open(&vol, device, HFSP_MODE_RDONLY);
if (! (result & FSCK_FATAL))
{
printf("*** Checking files and directories in catalog:\n");
result |= fscheck_files(&vol);
}
volume_close(&vol);
return result;
}
/* Do every check that can be imagined (or more :)
*
* returns the highest cnid found. 0 denotes an error.
* In case of error the volume may still be useable.
*/
int maximum_check(char* device, int flags)
{
volume vol;
int result;
fsck_init();
fsck_data.verbose = 0 != (flags & HFSPCHECK_VERBOSE);
fsck_data.macNow = HFSPTIMEDIFF + time(NULL);
result = fscheck_volume_open(&vol, device, HFSP_MODE_RDONLY);
if (! (result & FSCK_FATAL))
{
printf("*** Checking files and directories in catalog:\n");
result |= fscheck_files(&vol);
}
volume_close(&vol);
return result;
}
hfsplus-1.0.4/libhfsp/src/fscheck.h 0100644 0000000 0000000 00000007100 07441220604 015671 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes.
*
* This code checks the structures of a HFS+ volume for correctnes
*
* Copyright (C) 2000 Klaus Halfmann
* Original 1996-1998 Robert Leslie
* Additional work by Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: fscheck.h,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
*/
/* Bitflags for check operations */
/* Show normal output only */
#define HFSPCHECK_NORMAL 0x0000
/* Try to fix any error autmatically (but not yet ...) */
#define HFSPCHECK_AUTO 0x0001
/* verbose, show more output about almost everything */
#define HFSPCHECK_VERBOSE 0x0002
/* ignore errros (if possible) default stop after first error */
#define HFSPCHECK_IGNOREERR 0x0004
/* On return this variable is set to a
* combination of the flags below */
extern int hfspcheck_error;
/* Id like to include those but found no definitions */
#define FSCK_NOERR 0 // No errors
#define FSCK_FSCORR 1 // File system errors corrected
#define FSCK_REBOOT 2 // System should be rebooted
#define FSCK_ERR 4 // File system errors left uncorrected
#define FSCK_ERROPR 8 // Operational error
#define FSCK_USAGE 16 // Usage or syntax error
#define FSCK_SHARED 128 // Shared library error
#define FSCK_FATAL (FSCK_ERR | FSCK_ERROPR | FSCK_USAGE | FSCK_SHARED)
// Will not continue checking when one of these is found
/* Do the minimal check required after an unclean mount.
*
* The volume should be mounted readonly.
*
* returns the highest cnid found. 0 denotes an error.
* In case of error the volume should not be used at all.
*/
extern UInt32 minimal_check(volume* vol);
/* Do every check that can be imagined (or more :)
*
* returns the highest cnid found. 0 denotes an error.
* In case of error the volume may still be useable.
*/
extern int maximum_check(char* path, int flags);
/* Do usefull checks, practice will tell what this is.
*
* returns the highest cnid found. 0 denotes an error.
* In case of error the volume may still be useable.
*/
extern int hfsplus_check(char* path, int flags);
/* Dump all raw fork information to stdout */
extern void print_fork(hfsp_fork_raw* f);
/* Check wether all blocks of a fork are marked as allocated.
*
* returns number of errors found.
*/
extern int check_forkalloc(volume* vol, hfsp_fork_raw* fork);
/**** Defined in btreecheck.c ****/
/** Intialize catalog btree */
int fscheck_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork);
/** Intialize catalog btree */
int fscheck_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork);
/** Check a complete btree by traversing it in-oder */
int fscheck_btree(btree *bt);
/** Check all files in leaf nodes */
int fscheck_files(volume* vol);
/** global data used during fsck */
struct {
UInt32 maxCnid;
UInt32 macNow; // current date in mac-offset
int verbose;
int ignoreErr;
} fsck_data;
hfsplus-1.0.4/libhfsp/src/hfs.h 0100644 0000000 0000000 00000002336 07441220604 015051 0 ustar root root /*
* libhfsp - library for reading and writing Macintosh HFS+ volumes
*
* This file includes definitions for access to old HFS structures.
*
* Copyright (C) 2000 Klaus Halfmann
* Original code 1996-1998 by Robert Leslie
* other work 2000 from Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: hfs.h,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
*/
#define HFS_BLOCKSZ 512
/* A sector for Apple is always 512 bytes */
#define HFS_BLOCKSZ_BITS 9 /* 1<<9 == 512 */
#define HFS_VOLHEAD_SIG 0x4244 /* 'BD' */
hfsplus-1.0.4/libhfsp/src/hfsp.h 0100644 0000000 0000000 00000026210 07441220604 015226 0 ustar root root /*
* libhfsp - library for reading and writing Macintosh HFS+ volumes
*
* This file includes definitions for the structures found on
* HFS+ Volumes. The structures are further wrapped by struct
* found in libhfsp.h. fucntions on those enhanced structures
* are found in files mentioned in comments below.
*
* Copyright (C) 2000 Klaus Halfmann
* Original code 1996-1998 by Robert Leslie
* other work 2000 from Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: hfsp.h,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
*/
/* # include */
#define HFSP_BLOCKSZ 512 /* A sector for Apple is always 512 bytes */
#define HFSP_BLOCKSZ_BITS 9 /* 1<<9 == 512 */
#define HFSP_VOLHEAD_SIG 0x482B /* 'H+' */
// Minimum Key size for all btrees
#define HFSP_CAT_KEY_MIN_LEN 6
// Maximum Key size for all btrees
#define HFSP_CAT_KEY_MAX_LEN 516
/* HFS+ includes POSIX permissions , although marked as reserved they will be
* used as such. Is ignored by MacOS 8-9 but probably not by MacOS X.
*/
typedef struct {
UInt32 owner;
UInt32 group;
UInt32 mode;
UInt32 dev;
} hfsp_perm;
/* A single contiguous area (fragment) of a file */
typedef struct {
UInt32 start_block;
UInt32 block_count;
} hfsp_extent;
/* A file may contain up to 8 normale extents, all other
are found in some extra extent area */
typedef hfsp_extent hfsp_extent_rec[8];
/* Information for a "Fork" in a file
* Forks are the "usual" DATA and RSRC forks or special files
* (e.g. the Volume Bitmap)
*/
typedef struct {
UInt64 total_size; // logical size
UInt32 clump_size; // number of bytes to preallocate
UInt32 total_blocks;
hfsp_extent_rec extents; // initial (8) extents
} hfsp_fork_raw;
/* HFS+ Volume Header
* Always found at block 2 of the disk, a copy is stored
* at the second to last block of the disk.
*/
typedef struct hfsp_vh {
UInt16 signature; // must be HFSPLUS_VOLHEAD_SIG 'H+'
UInt16 version; // currently 4, ignored
UInt32 attributes; // See bit constants below
UInt32 last_mount_vers;
// Use a registered creator code here (See libhfsp.h)
// Mac OS uses '8.10' well
UInt32 reserved;
UInt32 create_date; // local time !
UInt32 modify_date; // GMT (?)
UInt32 backup_date; // GMT (?)
UInt32 checked_date; // GMT (?) fsck ?
UInt32 file_count;
// not including special files but including DATA and RSRC forks
UInt32 folder_count; // excluding the root folder
UInt32 blocksize;
// must be multiple of HFSPLUS_SECTOR_SIZE,
// should be a multiple of 4k for harddisk
UInt32 total_blocks;
UInt32 free_blocks;
// The total number of unused allocation blocks on the disk.
UInt32 next_alloc;
// hint where to search for next allocation blocks
UInt32 rsrc_clump_sz;
// default clump size for rsrc forks
UInt32 data_clump_sz;
// default clump size for data forks
UInt32 next_cnid;
// next unused catalog id
UInt32 write_count;
// increment on every mount (and write ?)
UInt64 encodings_bmp;
// for every encoding used on the disk a bit is set
// ignored but eventually must be cared for
Char finder_info[32];
hfsp_fork_raw alloc_file;
// stores bitmap of use/free blocks
hfsp_fork_raw ext_file;
// stores oferflow extents
hfsp_fork_raw cat_file;
// This contains the root directory
hfsp_fork_raw attr_file;
hfsp_fork_raw start_file;
// a special startup file may be described here (used by ?)
} hfsp_vh;
/* HFS+ volume attributes */
/* 0-6 reserved, may be used in memory only */
#define HFSPLUS_VOL_RESERVED1 0x000000FF
#define HFSPLUS_VOL_HARDLOCK 0x00000080 // Used in Memory by finder only
#define HFSPLUS_VOL_UNMNT 0x00000100
// clear this bit when mounting, set as last step of unmounting
// This is checked by (slower) ROM code
#define HFSPLUS_VOL_SPARE_BLK 0x00000200
#define HFSPLUS_VOL_NOCACHE 0x00000400
// in case of RAM or ROM disk (try a HFS+ Ramdisk :)
#define HFSPLUS_VOL_INCNSTNT 0x00000800
// Reverse meaning as of HFSPLUS_VOL_UNMNT
// This is checked by (faster) Mac OS code
/* 12-14 reserved */
#define HFSPLUS_VOL_RESERVED2 0x00007000
#define HFSPLUS_VOL_SOFTLOCK 0x00008000
#define HFSPLUS_VOL_RESERVED3 0xFFFF0000
/* HFS+ Btree node descriptor */
typedef struct {
UInt32 next; /* pointer to next node of this kind, or 0 */
/* Header Node points to first MAP node */
UInt32 prev; /* pointer to previous node of this kind, or 0 */
UInt8 kind; /* see below */
UInt8 height; /* root node starts with 0 */
UInt16 num_rec; /* number of records in this node */
UInt16 reserved; /* fill up to 4 byte alignment */
} btree_node_desc;
/* HFS+ Btree Node types */
#define HFSP_NODE_NDX 0x00
#define HFSP_NODE_HEAD 0x01
#define HFSP_NODE_MAP 0x02
#define HFSP_NODE_LEAF 0xFF
#define HFSP_CATALOG_MIN_NODE_SIZE 0x1000
#define HFSP_ATTRMIN_DOE_SIZE 0x1000
/* The record offsets are found at the end of the fork
* containing the Btree */
typedef UInt16 btree_record_offset;
typedef struct {
UInt16 depth;
// equal to height of btree_node_desc
UInt32 root;
// root node of the hierarchy
UInt32 leaf_count;
// number of leaf Records (not nodes)
UInt32 leaf_head;
// first leaf node
UInt32 leaf_tail;
// last leaf node
UInt16 node_size;
// node size of _all_ nodes in this fork
UInt16 max_key_len;
// maximum (or fixed) length of keys in this btree
UInt32 node_count;
// count of all (free and used) nodes in tree
UInt32 free_nodes;
UInt16 reserved1;
UInt32 clump_size;
// ignored my MacOS used by ?
UInt8 btree_type;
// always 0 for HFS+
UInt8 reserved2;
UInt32 attributes;
// see below
UInt32 reserved3[16];
} btree_head;
/* BTree attributes */
#define HFSPLUS_BAD_CLOSE 0x01
// Btree was not properly closed and should be checked
// not used for HFS+ but reserved
#define HFSPLUS_TREE_BIGKEYS 0x02
// always set for HFS+
#define HFSPLUS_TREE_VAR_NDXKEY_SIZE 0x04
// use variable length index nodes, always set for catalog btree,
// always cleared for extents btree.
#define HFSPLUS_TREE_RESERVED 0xFFFFFFF8
// Reserved bits in Attributes
#define HFSPLUS_TREE_UNUSED 0xFFFFFFF8
/* Some special File ID numbers */
#define HFSP_POR_CNID 1 /* Parent Of the Root */
#define HFSP_ROOT_CNID 2 /* ROOT directory */
#define HFSP_EXT_CNID 3 /* EXTents B-tree */
#define HFSP_CAT_CNID 4 /* CATalog B-tree */
#define HFSP_BAD_CNID 5 /* BAD blocks file */
#define HFSP_ALLOC_CNID 6 /* ALLOCation file */
#define HFSP_START_CNID 7 /* STARTup file */
#define HFSP_ATTR_CNID 8 /* ATTRibutes file */
#define HFSP_EXCH_CNID 15 /* ExchangeFiles temp id */
#define HFSP_MIN_CNID 15 /* Minimum expected value */
/* Unicode String */
typedef struct {
UInt16 strlen;
UInt16 name[255]; // unicode characters
} hfsp_unistr255;
/* HFS+ key "superclass" for follwoing keys ...*/
typedef struct {
UInt16 key_length; /* excluding length */
char data[0];
} hfsp_key;
/* HFS+ catalog entry key */
typedef struct {
UInt16 key_length; /* excluding length */
UInt32 parent_cnid;
hfsp_unistr255 name;
} hfsp_cat_key;
/* HFS+ extends entry key */
typedef struct {
UInt16 key_length; /* excluding length */
UInt8 fork_type; /* Seee below */
UInt8 filler;
UInt32 file_id;
UInt32 start_block;
} hfsp_extent_key;
#define HFSP_EXTENT_DATA 0x00
#define HFSP_EXTENT_RSRC 0xFF
/* The key is followed by a record, an index or some other data */
/* The types of these records are defined as follows */
#define HFSP_FOLDER 0x0001 // entry fo a Folder
#define HFSP_FILE 0x0002 // entry for a File
#define HFSP_FOLDER_THREAD 0x0003
// Like '.' in unix, identifies the folder by its id, only
#define HFSP_FILE_THREAD 0x0004
#define HFSP_THREAD_OFFSET 0x0002
// add to create a thread type from a simple type
/* HFS+ folder data (part of an hfsp_cat_entry) */
typedef struct {
UInt16 flags; /* no flags defined yet */
UInt32 valence; /* Numer of files and folders contained in folder */
UInt32 id;
UInt32 create_date; // GMT
UInt32 content_mod_date; // GMT
UInt32 attribute_mod_date; // GMT
UInt32 access_date; // GMT
UInt32 backup_date; // GMT
hfsp_perm permissions;
DInfo user_info;
DXInfo finder_info;
UInt32 text_encoding;
// hint fo the finder what encoding to use, unused here
UInt32 reserved;
} hfsp_cat_folder;
#define HFSP_FOLDER_RESERVED 0xFFFF // all are reserved :)
/* HFS+ file data (part of a cat_entry) */
typedef struct {
UInt16 flags; /* See below */
UInt32 reserved1;
UInt32 id;
UInt32 create_date;
UInt32 content_mod_date;
UInt32 attribute_mod_date;
UInt32 access_date;
UInt32 backup_date;
hfsp_perm permissions;
FInfo user_info;
FXInfo finder_info;
UInt32 text_encoding;
UInt32 reserved2;
hfsp_fork_raw data_fork;
hfsp_fork_raw res_fork;
} hfsp_cat_file;
/* File attribute bits */
#define HFSP_FILE_LOCKED 0x0001
#define HFSP_THREAD_EXISTS 0x0002 /* Always set in HFS+ */
#define HFSP_FILE_RESERVED 0xFFFC
/* HFS+ catalog thread (part of a cat_entry) */
/* In fact this is a almost a hfsp_cat_key */
typedef struct {
UInt16 reserved;
UInt32 parentID;
hfsp_unistr255 nodeName;
} hfsp_cat_thread;
/* A data record in the catalog tree */
typedef struct {
UInt16 type;
union {
hfsp_cat_folder folder;
hfsp_cat_file file;
hfsp_cat_thread thread;
} u;
} hfsp_cat_entry;
hfsplus-1.0.4/libhfsp/src/hfstime.c 0100644 0000000 0000000 00000003022 07441220604 015714 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes
* Copyright (C) 2000 Klaus Halfmann ^
* Original 1996-1998 Robert Leslie
* other work 2000 from Brad Boyer (flar@pants.nu)
*
* The HFS+ dates are stored as UInt32 containing the number of seconds since
* midnight, January 1, 1904, GMT. This is slightly different from HFS,
* where the value represents local time. A notable exception is the
* creationdate !. Linux uses times in GMT starting at January 1, 1970
*
* 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.
*
* $Id: hfstime.c,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
#include "apple.h"
#include "hfstime.h"
/* return the given apple time as printable UNIX time */
char* get_atime(UInt32 atime)
{
time_t t = atime;
t -= HFSPTIMEDIFF;
return ctime(&t);
}
hfsplus-1.0.4/libhfsp/src/hfstime.h 0100644 0000000 0000000 00000002740 07441220604 015727 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes
*
* Copyright (C) 2000 Klaus Halfmann
* Original 1996-1998 Robert Leslie
* other work 2000 from Brad Boyer (flar@pants.nu)
*
* The HFS+ dates are stored as UInt32 containing the number of seconds since
* midnight, January 1, 1904, GMT. This is slightly different from HFS,
* where the value represents local time. A notable exception is the
* creationdate !. Linux uses times in GMT starting at January 1, 1970
*
* 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.
*
* $Id: hfstime.h,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
*/
#include
/* The number of seconds between 1.1.1904 and 1.1.1970 */
#define HFSPTIMEDIFF 2082844800U
/* return the given apple time as UNIX time */
extern char* get_atime(UInt32 atime);
hfsplus-1.0.4/libhfsp/src/libhfsp.c 0100644 0000000 0000000 00000002644 07441220604 015715 0 ustar root root /*
* libhfsp - library for reading and writing Macintosh HFS+ volumes
*
* Copyright (C) 2000-2001 Klaus Halfmann
* Original 1996-1998 Robert Leslie
*
* Thi file contains utitlity functions to manage the features of
* the hfs+ library.
*
* 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.
*
* $Id: libhfsp.c,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include "libhfsp.h"
const char *hfsp_error = "no error"; /* static error string */
/** helper function to create those Apple 4 byte Signatures */
UInt32 sig(char c0, char c1, char c2, char c3)
{
UInt32 sig;
((char*)&sig)[0] = c0;
((char*)&sig)[1] = c1;
((char*)&sig)[2] = c2;
((char*)&sig)[3] = c3;
return sig;
}
hfsplus-1.0.4/libhfsp/src/libhfsp.h 0100644 0000000 0000000 00000021262 07447643325 015736 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes
*
* Copyright (C) 2000 Klaus Halfmann (klaus.halfmann@feri.de)
* Original work by 1996-1998 Robert Leslie (rob@mars.org)
*
* This file defines constants,structs etc needed for this library.
* Everything found here is usually not related to Apple defintions.
*
* 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.
*
* $Id: libhfsp.h,v 1.3 2002/03/25 15:48:37 klaus Exp $
*/
#ifndef APPLE_H
# include "apple.h"
#endif
# include "hfs.h"
# include "hfsp.h"
extern int errno;
/* Last error is eventually found here */
extern const char *hfsp_error;
# define HFSP_ERROR(code, str) \
do { hfsp_error = (str), errno = (code); goto fail; } while (0)
# ifdef DEBUG
# define ASSERT(cond) do { if (! (cond)) abort(); } while (0)
# else
# define ASSERT(cond) /* nothing */
# endif
# 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(ptr, type, n) : (FREE(ptr), (type *) 0))
# define STRINGIZE(x) #x
# define STR(x) STRINGIZE(x)
/* These macros will eventually be filled for a kernel-module or
* a multithreaded environement */
#define HFSP_READLOCK 1
#define HFSP_WRITELOCK 2
#define HFSP_SYNC_START(mode, whatever) /* to be filled */
#define HFSP_SYNC_END(mode, whatever) /* to be filled */
/* Flags for volume header */
/* used by internal routines to specify the open modes */
# define HFSP_MODE_RDONLY 0x00
# define HFSP_MODE_RDWR 0x01
/** need to write backup volume header, due to significant change */
# define HFSP_BACKUP_DIRTY 0x02
/* Signatures registered with Apple to identify this driver */
/* Identifies the userland implementation */
# define HPLS_SIGNATURE 0x482B4C58 // 'H+LX'
# define HFSPLUS_VERS 0x0004 // Current version of HFS+ Specification
/* Identifies the kernel module by Brad Boyer (flar@pants.nu) */
# define HPLS_SIGRES1 0x482B4C78 // 'H+Lx'
/* not jet in use ... */
# define HPLS_SIGRES2 0x482B6C78 // 'H+lx'
/* Signature used by Apple */
# define HPAPPLE_SIGNATURE 0x382e3130 // '8.10'
/* Version used for this implementation of HFS+. This is not related
* to the VERSION file found at the top-level of this package,
* but designates the version of the low level code */
#define HPLS_VERSION 1 /* must fit in a short */
/** helper function to create those Apple 4 byte Signatures */
extern inline UInt32 sig(char c0, char c1, char c2, char c3)
{
UInt32 sig;
((char*)&sig)[0] = c0;
((char*)&sig)[1] = c1;
((char*)&sig)[2] = c2;
((char*)&sig)[3] = c3;
return sig;
}
/* Other Signatures may follow for informational purposes */
/* prototype for key comparing functions. */
typedef int (*hfsp_key_compare) (void* key1, void* key2);
/* The read functions alaways retur the positiion right after
* reading (and swapping) the variable amount of bytes needed
* prototype for key reading (necessary for byte swapping) */
typedef void* (*hfsp_key_read) (void* p, void* key);
/* prototype for record reading (including byte swapping) */
typedef void* (*hfsp_rec_read) (void* p, void* key);
struct volume; /* foreward declaration for btree needed */
/* Structures for a node cache. The cache is an array
* with linear search. (So making it to big may make
* things slower). It is searched in a round robin
* fashion.
*/
typedef struct
{
UInt32 priority;
// as lower this number as higher the priority.
// decremetned on any sucessfull usage
// incremented else, intial value height*DEPTHFACTOR
UInt16 index; // of node in fork
// 0 means empty, since first node is node header
UInt16 flags; // like DIRTY etc.
} node_entry;
/* an Entry is dirty and must be written back */
#define NODE_DIRTY 0x0001
/* opposite of dirty */
#define NODE_CLEAN 0x0000
typedef struct
{
UInt32 index; // duplicate of above
btree_node_desc desc; // header of node
char node[0]; // size is actual node_size
// contents of node in original byte order
} node_buf;
typedef struct
{
int size; // number of nodes in the cache
int currindex; // round robin index
int nodebufsize; // size of complete node_buf, including node
node_entry *entries;
char *buffers; // actually *node_buf
} node_cache;
typedef struct
{ // "virtual" member functions
hfsp_key_compare kcomp;
/* function used for key compare in _this_ btree */
hfsp_key_read kread;
/* function used to read a key in _this_ btree */
hfsp_rec_read rread;
/* function used to read a record in _this_ btree */
btree_node_desc head_node;
/* Node descriptor for header node */
btree_head head;
struct volume* vol; /* pointer to volume this tree is part of */
hfsp_fork_raw* fork; /* pointer to fork this tree is part of */
UInt32 cnid; /* (pseudo) file id for the fork */
UInt32 attributes; /* see bits below */
/* Header node (contains most important parts of btree) */
char* alloc_bits;
/* All the rest of node 0 including the reserved area,
* the first part of the allocation bit-map found in Map Nodes
* and the two bakpointers needed for the header node, so this
* memory + head represent the header node */
UInt16 blkpernode;
/* Number of volume blocks per node (usually 0-4)
0 indicates, that nodeperblk should be used */
UInt16 nodeperblk;
/* Sometimes a block may contain more than one node */
UInt16 max_rec_size;
/* Maximum Size of a leaf record */
UInt16 filler;
node_cache cache;
} btree;
/* The Btree header is dirty and must be written back */
#define BTREE_HEADDIRTY 0x0001
/* The reserved Record starts at this offset in the header header node */
#define HEADER_RESERVEDOFFSET 120
/* The first map node eventually starts at this offset in the
* header node */
#define HEADER_MAPOFFSET 248
/* Function on btrees are defined in btree.h */
/* A Wrapper around the raw hfs+ volume header for additional information
* needed by this library.
*/
typedef struct volume
{
void *fd; /* OS dependend reference to device */
UInt16 blksize_bits; /* blocksize of device = 1 << blksize_bits */
UInt16 flags; /* as of now only HFSP_MODE_RDWR */
UInt32 blksize; /* always 1 << blksize_bits */
UInt32 maxblocks; /* maximum number of blocks in device */
hfsp_vh vol; /* raw volume data */
btree* extents; /* is NULL by default and intialized when needed */
btree catalog; /* This is always neeeded */
} volume;
/* Functions on volumes are defined in volume.h */
typedef struct { // may not be used as found here
btree* tree; // tree where this record is contained in.
UInt16 node_index; /* index of node in btree */
UInt16 keyind; /* index of current key in node */
/* Warning node_index and keyind are private. They can become
* invalid when the btree changes */
hfsp_cat_key key; /* current key */
UInt32 child; /* child node belonging to this key */
} index_record;
typedef struct {
btree* tree; // tree where this record is contained in.
UInt16 node_index; /* index of node in btree */
UInt16 keyind; /* index of current key in node */
/* Warning node_index and keyind are private. They can become
* invalid when the btree changes */
hfsp_extent_key key; /* current key */
hfsp_extent_rec extent; /* The payload carried around */
} extent_record;
typedef struct {
btree* tree; // tree where this record is contained in.
UInt16 node_index; /* index of node in btree */
UInt16 keyind; /* index of current key in node */
/* Warning node_index and keyind are private. They can become
* invalid when the btree changes */
hfsp_cat_key key; /* current key */
hfsp_cat_entry record; /* current record */
} record;
/* Functions on records are defined in record.h */
hfsplus-1.0.4/libhfsp/src/os.c 0100644 0000000 0000000 00000012061 07447643325 014720 0 ustar root root /*
* libhfsp - library for reading and writing Macintosh HFS+ volumes
*
* Copyright (C) 2000-2001 Klaus Halfmann
* Original Copyright (C) 1996-1998 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.
*
* $Id: os.c,v 1.2 2002/03/25 15:48:37 klaus Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
#define _FILE_OFFSET_BITS 64
# ifdef HAVE_FCNTL_H
# include
# else
int open(const char *, int, ...);
int fcntl(int, int, ...);
# endif
# ifdef HAVE_UNISTD_H
# include
# else
int close(int);
off_t lseek(int, off_t, int);
size_t read(int, void *, size_t);
size_t write(int, const char *, size_t);
int stat(const char *, struct stat *);
int fstat(int, struct stat *);
# endif
# include
# include
# include
// need BLKGETSIZE ioctl call
// # include
# include "libhfsp.h"
# include "os.h"
/** Offset that is silently used by os_seek.
* Nedded to transparaently support things like partitions */
UInt64 os_offset;
/*
* NAME: os->open()
* DESCRIPTION: open and lock a new descriptor from the given path and mode
*/
int os_open(void **priv, const char *path, int mode)
{
int fd;
struct flock lock;
int c;
switch (mode)
{
case HFSP_MODE_RDONLY:
mode = O_RDONLY;
break;
case HFSP_MODE_RDWR:
default:
fprintf(stderr,"*** Warning: You are about to open '%s' "
"for writing ***\n", path);
fprintf(stderr,"*** Do you really want to do that ? (y/n) ***\n");
do
c = getchar();
while (c != 'y' && c != 'n');
if (c != 'y')
exit(1);
mode = O_RDWR;
break;
}
fd = open(path, mode);
if (fd == -1)
HFSP_ERROR(errno, "error opening medium");
/* lock descriptor against concurrent access */
lock.l_type = (mode == O_RDONLY) ? F_RDLCK : F_WRLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
if (fcntl(fd, F_SETLK, &lock) == -1 &&
(errno == EACCES || errno == EAGAIN))
HFSP_ERROR(EAGAIN, "unable to obtain lock for medium");
*priv = (void *) fd;
return 0;
fail:
if (fd != -1)
close(fd);
return -1;
}
/*
* NAME: os->close()
* DESCRIPTION: close an open descriptor
*/
int os_close(void **priv)
{
int fd = (int) *priv;
*priv = (void *) -1;
if (close(fd) == -1)
HFSP_ERROR(errno, "error closing medium");
return 0;
fail:
return -1;
}
/*
* NAME: os->same()
* DESCRIPTION: return 1 iff path is same as the open descriptor
*/
int os_same(void **priv, const char *path)
{
int fd = (int) *priv;
struct stat fdev, dev;
if (fstat(fd, &fdev) == -1 ||
stat(path, &dev) == -1)
HFSP_ERROR(errno, "can't get path information");
return fdev.st_dev == dev.st_dev &&
fdev.st_ino == dev.st_ino;
fail:
return -1;
}
/*
* NAME: os->seek()
* DESCRIPTION: set a descriptor's seek pointer (offset in blocks) and returns
* this offset if everything went well
*/
unsigned long os_seek(void **priv, unsigned long offset, int blksize_bits)
{
int fd = (int) *priv;
off_t result, where = offset;
where = os_offset + (where << blksize_bits);
result = lseek(fd, where, SEEK_SET) - os_offset;
result = result >> blksize_bits;
return (unsigned long) result;
}
/*
* NAME: os->read()
* DESCRIPTION: read blocks from an open descriptor
*
* @param **priv is a pointer to the file descriptor
* @param *buf buffer to put the content in
* @param len number of buffers to read
* @param blksize_bits blocksize as a power of 2 (e.g. 9 for 512)
*
* @return number of read blocks or -1 on error
*/
unsigned long os_read(void **priv, void *buf, unsigned long len, int blksize_bits)
{
int fd = (int) *priv;
size_t result= 0;
int num= len << blksize_bits;
while( result< num) {
size_t size = read(fd, &((char *)buf)[ result], num- result);
if (size <= 0) /* EOF == 0 should not happen, too */
HFSP_ERROR(errno, "error reading from medium");
result += size;
}
return (unsigned long) result >> blksize_bits;
fail:
return -1;
}
/*
* NAME: os->write()
* DESCRIPTION: write blocks to an open descriptor
*/
unsigned long os_write(void **priv, const void *buf, unsigned long len, int blksize_bits)
{
int fd = (int) *priv;
size_t result;
result = write(fd, buf, len << blksize_bits);
if (result == -1)
HFSP_ERROR(errno, "error writing to medium");
return (unsigned long) result >> blksize_bits;
fail:
return -1;
}
hfsplus-1.0.4/libhfsp/src/os.h 0100644 0000000 0000000 00000003555 07447643325 014735 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes
* Copyright (C) 1996-1998 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.
*
* $Id: os.h,v 1.2 2002/03/25 15:48:37 klaus Exp $
*/
/*
* NAME: os->open()
* DESCRIPTION: open and lock a new descriptor from the given path and mode
*/
int os_open(void **priv, const char *path, int mode);
/*
* NAME: os->close()
* DESCRIPTION: close an open descriptor
*/
int os_close(void **priv);
/*
* NAME: os->same()
* DESCRIPTION: return 1 iff path is same as the open descriptor
*/
int os_same(void **priv, const char *path);
/** Offset that is silently used by os_seek.
* Needed to transparaently support things like partitions */
extern UInt64 os_offset;
/*
* NAME: os->seek()
* DESCRIPTION: set a descriptor's seek pointer (offset in blocks)
*/
unsigned long os_seek(void **priv, unsigned long offset, int blksize_bits);
/*
* NAME: os->read()
* DESCRIPTION: read blocks from an open descriptor
*/
unsigned long os_read(void **priv, void *buf, unsigned long len, int blksize_bits);
/*
* NAME: os->write()
* DESCRIPTION: write blocks to an open descriptor
*/
unsigned long os_write(void **priv, const void *buf, unsigned long len, int blksize_bits);
hfsplus-1.0.4/libhfsp/src/partitions.c 0100644 0000000 0000000 00000012476 07450133475 016477 0 ustar root root /*
* hfsutils - tools for reading and writing Macintosh HFS volumes
* Copyright (C) 2000 Klaus Halfmann
*
* Structures and Functions for accessing the mac partition map
* Copyright (C) 2002 Michael Schulze
*
* 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.
*
* $Id: partitions.c,v 1.7 2002/03/26 18:00:29 klaus Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
#include "swab.h"
#include "partitions.h"
#include "os.h"
#include "libhfsp.h"
#include
/*
* Returns the number of partitions in the given partition map.
* probably we don't need this since we have map->numparts
*/
int partition_getnparts( partition_map *map) {
return map->partitions[ 0]->pmMapBlkCnt;
}
/*
* Copies bytes from the beginning of source to dest.
* source will be incrementet to the byte after length.
*/
static int splitCharArray( char **source, char *dest, int length) {
memcpy( dest, *source, length);
dest[ length- 1]= 0; /* force last byte to null */
(*source)+= length;
return 0;
}
int partition_fillstruct( Partition *p, char *buf) {
p->pmSig = bswabU16_inc( buf);
p->pmSigPad = bswabU16_inc( buf);
p->pmMapBlkCnt = bswabU32_inc( buf);
p->pmPyPartStart = bswabU32_inc( buf);
p->pmPartBlkCnt = bswabU32_inc( buf);
splitCharArray( &buf, p->pmPartName, 32);
splitCharArray( &buf, p->pmPartType, 32);
p->pmLgDataStart = bswabU32_inc( buf);
p->pmDataCnt = bswabU32_inc( buf);
p->pmPartStatus = bswabU32_inc( buf);
p->pmLgBootStart = bswabU32_inc( buf);
p->pmBootSize = bswabU32_inc( buf);
p->pmBootAddr = bswabU32_inc( buf);
p->pmBootAddr2 = bswabU32_inc( buf);
p->pmBootEntry = bswabU32_inc( buf);
p->pmBootEntry2 = bswabU32_inc( buf);
p->pmBootCksum = bswabU32_inc( buf);
return 0;
}
/* sort the partitions according to their occurance on disc
* hasi: we'd better use qsort instead of reinventing the wheel ....*/
void partition_sort( partition_map *map) {
Partition **partitions = map->partitions;
Partition *min;
int i, j, numparts= map->numparts;
for( i= 0; i < numparts; i++) {
for( j= i+ 1; j< numparts; j++) {
if( partitions[ j]->pmPyPartStart< partitions[ i]->pmPyPartStart) {
min= partitions[ j];
partitions[ j]= partitions[ i];
partitions[ i]= min;
}
}
}
}
/*
* Returns the partition map of the given device
*
* @param fd filedescripator (see os.h) must already be opened.
*/
int partition_getPartitionMap( partition_map *map, void *fd) {
char buf[ HFSP_BLOCKSZ];
Partition first; /* we use that to get the number of partitions in the map */
int i, numparts;
if( os_seek( &fd, 1, HFSP_BLOCKSZ_BITS)!= 1)
return -1;
/* read the first partition info from the map */
if( os_read( &fd, buf, 1, HFSP_BLOCKSZ_BITS)!= 1)
return -1;
if( partition_fillstruct( &first, buf))
return -1;
/* check if this is a partition map */
if( first.pmSig!= PARTITION_SIG) {
map->numparts= 0;
return 0;
}
/* set the number of partitions and allocate memory */
map->numparts = numparts = first.pmMapBlkCnt;
map->parray = ( Partition *)malloc( numparts* sizeof( Partition));
map->partitions = ( Partition **)malloc( numparts* sizeof( void *));
/* copy the first partition info to map */
memcpy( map->parray, &first, sizeof( Partition));
map->partitions[ 0]= map->parray;
for( i= 1; i < numparts; i++) {
if( ( os_read( &fd, buf, 1, HFSP_BLOCKSZ_BITS)!= 1) ||
( partition_fillstruct( &( map->parray[ i]), buf))) {
free( map->partitions);
free( map->parray);
map->numparts = 0; // so partition_release() will work correctly
return -1;
}
map->partitions[ i]= &( map->parray[ i]);
}
partition_sort( map);
return numparts;
}
/*
* Returns the startblock of the th partition of the given type from the given
* Partition Map.
* @param map Partition map to get the information from
* @param type type of the desired partition
* @param num number of the desired partition (starting with 1)
* @return the start block of the partition or 0 if no such partition could be found
*/
UInt32 partition_getStartBlock( partition_map *map, const char *type, int num) {
int i, startblock = 0;
Partition **partitions = map->partitions;
for( i= 0; i< map->numparts && num> 0; i++) {
if( !strcmp( partitions[ i]->pmPartType, type)) {
startblock= partitions[ i]->pmPyPartStart;
num--;
}
}
return num ? 0 : startblock;
}
/*
* cleanup and free allocated memory.
*/
void partition_release( partition_map *map) {
if( map->numparts > 0) {
free( map->partitions);
free( map->parray);
map->numparts = 0;
}
}
hfsplus-1.0.4/libhfsp/src/partitions.h 0100644 0000000 0000000 00000004113 07450133475 016471 0 ustar root root /*
* hfsutils - tools for reading and writing Macintosh HFS volumes
* Copyright (C) 2000 Klaus Halfmann
*
* Structures and Functions for accessing the mac partition map
* Copyright (C) 2002 Michael Schulze
*
* 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.
*
* $Id: partitions.h,v 1.5 2002/03/26 18:00:29 klaus Exp $
*/
#ifndef APPLE_H
#include "apple.h"
#endif
typedef struct {
int numparts; /* number of partitions found */
Partition *parray; /* only used for mem mngmnt */
Partition **partitions; /* partition descriptions */
} partition_map;
/*
* Returns the number of partitions in the given partition map or 0 if no partitions were found
* @param map Partition map to get the information from.
*/
int partition_getnparts( partition_map *map);
/*
* Returns the startblock of the th partition of the given type from the given
* Partition Map.
*
* @param map Partition map to get the information from
* @param type type of the desired partition
* @param num number of the desired partition (starting with 1)
*
* @return the start block of the partition or 0 if no such partition could be found
*/
UInt32 partition_getStartBlock( partition_map *map, const char *type, int num);
/*
* Returns the partition map of the given device
*/
int partition_getPartitionMap( partition_map *map, void *fd);
/*
* cleanup and free allocated memory.
*/
void partition_release( partition_map *map);
hfsplus-1.0.4/libhfsp/src/record.c 0100644 0000000 0000000 00000110605 07445150101 015537 0 ustar root root /*
* libhfsp - library for reading and writing Macintosh HFS+ volumes.
*
* a record contains a key and a folder or file and is part
* of a btree. This file conatins various methods to read and
* write the record related HFS+ structures from/to memory.
*
* Copyright (C) 2000-2001 Klaus Halfmann
* Original 1996-1998 Robert Leslie
* Additional work by Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: record.c,v 1.2 2002/03/17 17:20:01 klaus Exp $
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
# endif
#include
#include
#include "libhfsp.h"
#include "hfstime.h"
#include "record.h"
#include "volume.h"
#include "btree.h"
#include "unicode.h"
#include "swab.h"
/* read a hfsp_cat_key from memory, check for correct length
*
* @param p buffer in memory to read from
* @param buf buffer containing the correctly swapped structure
*
* @return pointer to next byte after structure, NULL on failure
*/
void* record_readkey(void* p, void* buf)
{
hfsp_cat_key* key = (hfsp_cat_key*) buf;
const void* check;
UInt16 key_length, len,i;
UInt16* cp;
key->key_length = key_length = bswabU16_inc(p);
check = p;
key->parent_cnid = bswabU32_inc(p);
key->name.strlen = len = bswabU16_inc(p);
cp = key->name.name;
for (i=0; i < len; i++, cp++)
*cp = bswabU16_inc(p);
/* check if keylenght was correct */
if (key_length != ((char*) p) - ((char*) check))
HFSP_ERROR(EINVAL, "Invalid key length in record_readkey");
return p;
fail:
return NULL;
}
/* write a hfsp_cat_key back to memory, check for correct length.
*
* @param p buffer in memory to write to
* @param buf memory containing the (swapped) key.
*
* @return pointer to byte after the structure or NULL on failure.
*
*/
void* record_writekey(void* p, void* buf)
{
hfsp_cat_key* key = (hfsp_cat_key*) buf;
UInt16 key_length, len,i;
UInt16* cp;
key_length = key->key_length;
len = key->name.strlen;
cp = key->name.name;
if (key_length != (6 + len * 2))
HFSP_ERROR(EINVAL, "Invalid key length in record_writekey");
bstoreU16_inc(p, key_length);
bstoreU32_inc(p, key->parent_cnid);
bstoreU16_inc(p, len);
for (i=0; i < len; i++, cp++)
bstoreU16_inc(p, *cp);
return p;
fail:
return NULL;
}
/* read a hfsp_extent_key from memory */
void* record_extent_readkey(void* p, void* buf)
{
hfsp_extent_key* key = (hfsp_extent_key*) buf;
UInt16 key_length;
key->key_length = key_length = bswabU16_inc(p);
key->fork_type = bswabU8_inc(p);
key->filler = bswabU8_inc(p);
if (key_length != 10)
HFSP_ERROR(-1, "Invalid key length in record_extent_readkey");
key->file_id = bswabU32_inc(p);
key->start_block = bswabU32_inc(p);
return p;
fail:
return NULL;
}
/* write a hfsp_extent_key to memory */
void* record_extent_writekey(void* p, void* buf)
{
hfsp_extent_key* key = (hfsp_extent_key*) buf;
UInt16 key_length = key->key_length;
if (key_length != 10)
HFSP_ERROR(-1, "Invalid key length in record_extent_writekey");
bstoreU16_inc (p, key_length);
bstoreU8_inc (p, key->fork_type);
bstoreU8_inc (p, key->filler);
bstoreU32_inc (p, key->file_id);
bstoreU32_inc (p, key->start_block);
return p;
fail:
return NULL;
}
/* read posix permission from memory */
static inline void* record_readperm(void *p, hfsp_perm* perm)
{
perm->owner= bswabU32_inc(p);
perm->group= bswabU32_inc(p);
perm->mode = bswabU32_inc(p);
perm->dev = bswabU32_inc(p);
return p;
}
/* write posix permission to memory */
static inline void* record_writeperm(void *p, hfsp_perm* perm)
{
bstoreU32_inc (p, perm->owner);
bstoreU32_inc (p, perm->group);
bstoreU32_inc (p, perm->mode );
bstoreU32_inc (p, perm->dev );
return p;
}
/* intialize posix permission from memory.
*
* TODO use current umask, user, group, etc.
*/
static inline void record_initperm(hfsp_perm* perm)
{
perm->owner= 0;
perm->group= 0;
perm->mode = 0;
perm->dev = 0;
}
/* read directory info */
static inline void* record_readDInfo(void *p, DInfo* info)
{
info->frRect.top = bswabU16_inc(p);
info->frRect.left = bswabU16_inc(p);
info->frRect.bottom = bswabU16_inc(p);
info->frRect.right = bswabU16_inc(p);
info->frFlags = bswabU16_inc(p);
info->frLocation.v = bswabU16_inc(p);
info->frLocation.h = bswabU16_inc(p);
info->frView = bswabU16_inc(p);
return p;
}
/* write directory info */
static inline void* record_writeDInfo(void *p, DInfo* info)
{
bstoreU16_inc (p, info->frRect.top );
bstoreU16_inc (p, info->frRect.left );
bstoreU16_inc (p, info->frRect.bottom);
bstoreU16_inc (p, info->frRect.right);
bstoreU16_inc (p, info->frFlags );
bstoreU16_inc (p, info->frLocation.v);
bstoreU16_inc (p, info->frLocation.h);
bstoreU16_inc (p, info->frView );
return p;
}
/* initialize directory info */
static inline void record_initDInfo(DInfo* info)
{
// Hope the finder will not choke on these values
memset(info, 0, sizeof(DInfo));
/*
info->frRect.top = 0;
info->frRect.left = 0;
info->frRect.bottom = 0;
info->frRect.right = 0;
info->frFlags = 0;
info->frLocation.v = 0;
info->frLocation.h = 0;
info->frView = 0;
*/
}
/* read extra Directory info */
static inline void* record_readDXInfo(void *p, DXInfo* xinfo)
{
xinfo->frScroll.v = bswabU16_inc(p);
xinfo->frScroll.h = bswabU16_inc(p);
xinfo->frOpenChain = bswabU32_inc(p);
xinfo->frUnused = bswabU16_inc(p);
xinfo->frComment = bswabU16_inc(p);
xinfo->frPutAway = bswabU32_inc(p);
return p;
}
/* write extra Directory info */
static inline void* record_writeDXInfo(void *p, DXInfo* xinfo)
{
bstoreU16_inc (p, xinfo->frScroll.v );
bstoreU16_inc (p, xinfo->frScroll.h );
bstoreU32_inc (p, xinfo->frOpenChain);
bstoreU16_inc (p, xinfo->frUnused );
bstoreU16_inc (p, xinfo->frComment );
bstoreU32_inc (p, xinfo->frPutAway );
return p;
}
/* initialize extra Directory info */
static inline void record_initDXInfo(DXInfo* xinfo)
{
// Hope the finder will not choke on these values
memset(xinfo, 0, sizeof(DXInfo));
/*
xinfo->frScroll.v = 0;
xinfo->frScroll.h = 0;
xinfo->frOpenChain= 0;
xinfo->frUnused = 0;
xinfo->frComment = 0;
xinfo->frPutAway = 0;
*/
}
/* read a hfsp_cat_folder from memory */
static void* record_readfolder(void *p, hfsp_cat_folder* folder)
{
folder->flags = bswabU16_inc(p);
folder->valence = bswabU32_inc(p);
folder->id = bswabU32_inc(p);
folder->create_date = bswabU32_inc(p);
folder->content_mod_date = bswabU32_inc(p);
folder->attribute_mod_date = bswabU32_inc(p);
folder->access_date = bswabU32_inc(p);
folder->backup_date = bswabU32_inc(p);
p = record_readperm (p, &folder->permissions);
p = record_readDInfo (p, &folder->user_info);
p = record_readDXInfo (p, &folder->finder_info);
folder->text_encoding = bswabU32_inc(p);
folder->reserved = bswabU32_inc(p);
return p;
}
/* write a hfsp_cat_folder to memory */
static void* record_writefolder(void *p, hfsp_cat_folder* folder)
{
bstoreU16_inc (p, folder->flags );
bstoreU32_inc (p, folder->valence );
bstoreU32_inc (p, folder->id );
bstoreU32_inc (p, folder->create_date );
bstoreU32_inc (p, folder->content_mod_date );
bstoreU32_inc (p, folder->attribute_mod_date);
bstoreU32_inc (p, folder->access_date );
bstoreU32_inc (p, folder->backup_date );
p = record_writeperm (p, &folder->permissions);
p = record_writeDInfo (p, &folder->user_info);
p = record_writeDXInfo (p, &folder->finder_info);
bstoreU32_inc (p, folder->text_encoding );
bstoreU32_inc (p, folder->reserved );
return p;
}
/* initialize a hfsp_cat_folder with given values.
*
* @vol is needed to create a new record Id.
* @return 0 on sucess anything else on error.
*/
static int record_initfolder(volume* vol, hfsp_cat_folder* folder)
{
UInt32 macNow = HFSPTIMEDIFF + time(NULL);
folder->flags = 0;
folder->valence = 0; // no subfiles/folders yet
if (! (folder->id = volume_get_nextid(vol))) // oops possible wrap around overflow
return -1;
folder->create_date = macNow;
folder->content_mod_date = macNow;
folder->attribute_mod_date = macNow;
folder->access_date = macNow;
folder->backup_date = 0;
record_initperm (&folder->permissions);
record_initDInfo (&folder->user_info);
record_initDXInfo (&folder->finder_info);
folder->text_encoding = 0; // Not supported, sorry
folder->reserved = 0;
return 0;
}
/* read file info */
static inline void* record_readFInfo(void *p, FInfo* info)
{
info->fdType = bswabU32_inc(p);
info->fdCreator = bswabU32_inc(p);
info->fdFlags = bswabU16_inc(p);
info->fdLocation.v = bswabU16_inc(p);
info->fdLocation.h = bswabU16_inc(p);
info->fdFldr = bswabU16_inc(p);
return p;
}
/* write file info */
static inline void* record_writeFInfo(void *p, FInfo* info)
{
bstoreU32_inc (p, info->fdType );
bstoreU32_inc (p, info->fdCreator );
bstoreU16_inc (p, info->fdFlags );
bstoreU16_inc (p, info->fdLocation.v);
bstoreU16_inc (p, info->fdLocation.h);
bstoreU16_inc (p, info->fdFldr );
return p;
}
/* initialize file info */
static inline void record_initFInfo(FInfo* info)
{
// should use something better somehow
info->fdType = sig('T','E','X','T');
info->fdCreator = HPLS_SIGNATURE;
info->fdFlags = 0; // dunno any finder flags
info->fdLocation.v = 0;
info->fdLocation.h = 0;
info->fdFldr = 0;
}
/* read extra File info */
static inline void* record_readFXInfo(void *p, FXInfo* xinfo)
{
xinfo->fdIconID = bswabU16_inc(p);
xinfo->fdUnused[0] = bswabU16_inc(p);
xinfo->fdUnused[1] = bswabU16_inc(p);
xinfo->fdUnused[2] = bswabU16_inc(p);
xinfo->fdUnused[3] = bswabU16_inc(p);
xinfo->fdComment = bswabU16_inc(p);
xinfo->fdPutAway = bswabU32_inc(p);
return p;
}
/* write extra File info */
static inline void* record_writeFXInfo(void *p, FXInfo* xinfo)
{
bstoreU16_inc (p, xinfo->fdIconID);
bstoreU16_inc (p, xinfo->fdUnused[0]);
bstoreU16_inc (p, xinfo->fdUnused[1]);
bstoreU16_inc (p, xinfo->fdUnused[2]);
bstoreU16_inc (p, xinfo->fdUnused[3]);
bstoreU16_inc (p, xinfo->fdComment);
bstoreU16_inc (p, xinfo->fdPutAway);
return p;
}
/* initialize extra File info */
static inline void record_initFXInfo(FXInfo* xinfo)
{
// Hope the finder will not choke on these values
memset(xinfo, 0, sizeof(FXInfo));
/*
xinfo->fdIconID = 0;
xinfo->fdUnused[0] = 0;
xinfo->fdUnused[1] = 0;
xinfo->fdUnused[2] = 0;
xinfo->fdUnused[3] = 0;
xinfo->fdComment = 0;
xinfo->fdPutAway = 0;
*/
}
/* read a hfsp_cat_file from memory */
static void* record_readfile(void *p, hfsp_cat_file* file)
{
file->flags = bswabU16_inc(p);
file->reserved1 = bswabU32_inc(p);
file->id = bswabU32_inc(p);
file->create_date = bswabU32_inc(p);
file->content_mod_date = bswabU32_inc(p);
file->attribute_mod_date = bswabU32_inc(p);
file->access_date = bswabU32_inc(p);
file->backup_date = bswabU32_inc(p);
p = record_readperm (p, &file->permissions);
p = record_readFInfo (p, &file->user_info);
p = record_readFXInfo (p, &file->finder_info);
file->text_encoding = bswabU32_inc(p);
file->reserved2 = bswabU32_inc(p);
p = volume_readfork (p, &file->data_fork);
return volume_readfork (p, &file->res_fork);
}
/* write a hfsp_cat_file to memory */
static void* record_writefile(void *p, hfsp_cat_file* file)
{
bstoreU16_inc(p, file->flags);
bstoreU16_inc(p, file->reserved1);
bstoreU16_inc(p, file->id);
bstoreU16_inc(p, file->create_date);
bstoreU16_inc(p, file->content_mod_date);
bstoreU16_inc(p, file->attribute_mod_date);
bstoreU16_inc(p, file->access_date);
bstoreU16_inc(p, file->backup_date);
p = record_writeperm (p, &file->permissions);
p = record_writeFInfo (p, &file->user_info);
p = record_writeFXInfo (p, &file->finder_info);
bstoreU16_inc(p, file->text_encoding);
bstoreU16_inc(p, file->reserved2 );
p = volume_writefork (p, &file->data_fork);
return volume_writefork (p, &file->res_fork);
}
/* initialize a hfsp_cat_file with given values.
*
* vol needed to create new Id
*/
static int record_initfile(volume* vol, hfsp_cat_file* file)
{
UInt32 macNow = HFSPTIMEDIFF + time(NULL);
file->flags = 0;
file->reserved1 = 0; // no subfiles/folders yet
if (! (file->id = volume_get_nextid(vol))) // oops possible wrap around overflow
return -1;
file->create_date = macNow;
file->content_mod_date = macNow;
file->attribute_mod_date = macNow;
file->access_date = macNow;
file->backup_date = 0;
record_initperm (&file->permissions);
record_initFInfo (&file->user_info);
record_initFXInfo (&file->finder_info);
file->text_encoding = 0; // Not supported, sorry
file->reserved2 = 0;
volume_initfork(vol,&file->data_fork, HFSP_EXTENT_DATA);
volume_initfork(vol,&file->res_fork, HFSP_EXTENT_RSRC);
return 0;
}
/* read a hfsp_cat_thread from memory */
static void* record_readthread(void *p, hfsp_cat_thread* entry)
{
int i;
UInt16 len;
UInt16* cp;
entry-> reserved = bswabU16_inc(p);
entry-> parentID = bswabU32_inc(p);
entry->nodeName.strlen = len= bswabU16_inc(p);
cp = entry->nodeName.name;
if (len > 255)
HFSP_ERROR(-1, "Invalid key length in record_thread");
for (i=0; i < len; i++, cp++)
*cp = bswabU16_inc(p);
return p;
fail:
return NULL;
}
/* write a hfsp_cat_thread to memory */
static void* record_writethread(void *p, hfsp_cat_thread* entry)
{
int i;
UInt16 len;
UInt16* cp;
bstoreU16_inc(p, entry->reserved);
bstoreU32_inc(p, entry->parentID);
bstoreU16_inc(p, len = entry->nodeName.strlen);
cp = entry->nodeName.name;
if (len > 255)
HFSP_ERROR(-1, "Invalid key length in record_thread");
for (i=0; i < len; i++, cp++)
bstoreU16_inc(p, *cp);
return p;
fail:
return NULL;
}
/* read a hfsp_cat_entry from memory */
void* record_readentry(void *p, void* entry)
{
UInt16 type = bswabU16_inc(p);
hfsp_cat_entry* e = (hfsp_cat_entry*) entry;
e->type = type;
switch (type)
{
case HFSP_FOLDER:
return record_readfolder(p, &e->u.folder);
case HFSP_FILE:
return record_readfile (p, &e->u.file);
case HFSP_FOLDER_THREAD:
case HFSP_FILE_THREAD:
return record_readthread(p, &e->u.thread);
default:
HFSP_ERROR(-1, "Unexpected record type in record_readentry");
} ;
fail:
return NULL;
}
/* write a hfsp_cat_entry to memory */
void* record_writeentry(void *p, hfsp_cat_entry* entry)
{
UInt16 type = entry->type;
bstoreU16_inc(p, type);
switch (type)
{
case HFSP_FOLDER:
return record_writefolder(p, &entry->u.folder);
case HFSP_FILE:
return record_writefile (p, &entry->u.file);
case HFSP_FOLDER_THREAD:
case HFSP_FILE_THREAD:
return record_writethread(p, &entry->u.thread);
default:
HFSP_ERROR(-1, "Unexpected record type in record_writeentry");
} ;
fail:
return NULL;
}
/* read an extent record from memory */
// For dependency reasons this actually is found in volume.h
void* record_extent_readrecord(void *p, void* entry)
{
return volume_readextent(p, (hfsp_extent*) entry);
}
/* intialize the record with the given index entry in the btree. */
int record_init(record* r, btree* bt, node_buf* buf, UInt16 index)
{
void *p;
r-> tree = bt;
p = btree_key_by_index(bt,buf,index);
if (!p)
return -1;
p = record_readkey (p, &r->key);
if (!p)
return -1;
/* void *help = p; // se comment below */
p = record_readentry(p, &r->record);
/* This was for testing write cache only
void * help;
help = record_writeentry(help, &r->record);
if (p != help)
HFSP_ERROR(-1, "Error in write entry");
*/
if (!p)
return -1;
r->node_index = buf->index;
r-> keyind = index;
return 0;
/*
fail:
return -1;
*/
}
/* Update the record using its node- and key-index.
*
* Only use this function with a write lock, directly
* after reading the record, otherwise use update_bykey().
*/
int record_update(record* r)
{
btree *tree= r->tree;
node_buf *buf = btree_node_by_index(tree, r->node_index, NODE_DIRTY);
void *p = btree_key_by_index (tree, buf, r->keyind);
if (!p)
return -1;
p = record_writekey (p, &r->key);
if (!p)
return -1;
p = record_writeentry(p, &r->record);
if (!p)
return -1;
return 0;
}
/* intialize the record with the given index entry in the btree. */
static int record_init_extent(extent_record* r, btree* bt, node_buf* buf, UInt16 index)
{
void *p;
r-> tree = bt;
p = btree_key_by_index(bt, buf,index);
if (!p)
return -1;
p = record_extent_readkey(p, &r->key);
if (!p)
return -1;
p = volume_readextent(p, r->extent);
if (!p)
return -1;
r->node_index = buf->index;
r-> keyind = index;
return 0;
}
/* intialize the record to the first record of the tree
* which is (per design) the root node.
*/
int record_init_root(record* r, btree* tree)
{
// Position to first leaf node ...
UInt32 leaf_head = tree->head.leaf_head;
node_buf* buf = btree_node_by_index(tree, leaf_head, NODE_CLEAN);
if (!buf)
return -1;
return record_init(r, tree, buf, 0);
}
/* initialize a (catalog) record with given type and (ascii) name.
* parent must be a HFSP_FOLDER or FOLDER_THREAD
* You should normally call record_insert afterwards.
*/
int record_init_string(record* r, UInt16 type, char* name, record* parent)
{
int result = 0;
hfsp_cat_key* key = &r->key;
hfsp_cat_entry* entry = &r->record;
UInt16 ptype = parent->record.type;
memset(r, sizeof(record), 0); // **** Debugging only
r->tree = parent->tree;
r->node_index = 0;
r->keyind = 0;
key->key_length = 6 + 2 * unicode_asc2uni(&key->name,name);
// 6 for minumum size
if (ptype == HFSP_FOLDER)
key->parent_cnid= parent->record.u.folder.id;
else if (ptype == HFSP_FOLDER_THREAD)
key->parent_cnid= parent->key.parent_cnid;
else // no kind of folder ??
{
hfsp_error = "parent for record_init_string is not a folder.";
return EINVAL;
}
switch(type)
{
case HFSP_FOLDER :
entry->type = type;
record_initfolder(parent->tree->vol, &entry->u.folder);
break;
case HFSP_FILE :
entry->type = type;
record_initfile(parent->tree->vol, &entry->u.file);
break;
// Those are unsupported use the types above instead
// record_init will care about the threads
case HFSP_FOLDER_THREAD :
case HFSP_FILE_THREAD :
default:
hfsp_error = "Unsupported type for record_init_string()";
result = -1;
}
return result;
}
/* initialize a (catalog) record thread by its original record
* used internally by record_insert.
*/
static int record_init_thread(record* r, record* template)
{
int result = 0;
hfsp_cat_key* key = &r->key;
hfsp_cat_entry* entry = &r->record;
UInt16 type = template->record.type;
hfsp_cat_thread* thread;
r->tree = template->tree;
r->node_index = 0;
r->keyind = 0;
key->key_length = 6; // empty name is ok for a thread
key->parent_cnid= template->record.u.folder.id;
thread = &entry->u.thread;
switch(type)
{
case HFSP_FOLDER :
case HFSP_FILE :
entry->type = type + HFSP_THREAD_OFFSET;
thread->reserved = 0;
thread->parentID = template->key.parent_cnid;
thread->nodeName = template->key.name;
break;
case HFSP_FOLDER_THREAD :
case HFSP_FILE_THREAD :
default:
hfsp_error = "Cannot create a thread for a thread";
result = -1;
}
return result;
}
/* Compare two cat_keys ... */
int record_key_compare(void* k1, void* k2)
{
hfsp_cat_key* key1 = (hfsp_cat_key*) k1;
hfsp_cat_key* key2 = (hfsp_cat_key*) k2;
int diff = key2->parent_cnid - key1->parent_cnid;
if (!diff) // same parent
diff = fast_unicode_compare(&key1->name, &key2->name);
return diff;
}
/* Compare two extent_keys ... */
int record_extent_key_compare(void* k1, void* k2)
{
hfsp_extent_key* key1 = (hfsp_extent_key*) k1;
hfsp_extent_key* key2 = (hfsp_extent_key*) k2;
int diff = key2->fork_type - key1->fork_type;
if (!diff) // same type
{
diff = key2->file_id - key1->file_id;
if (!diff) // same file
diff = key2->start_block - key1->start_block;
}
return diff;
}
/* Position node in btree so that key might be inside */
static node_buf* record_find_node(btree* tree, void *key)
{
int start, end, mid, comp; // components of a binary search
void *p = NULL;
char curr_key[tree->head.max_key_len];
// The current key under examination
hfsp_key_read readkey = tree->kread;
hfsp_key_compare key_compare = tree->kcomp;
UInt32 index;
node_buf* node =
btree_node_by_index(tree, tree->head.root, NODE_CLEAN);
HFSP_SYNC_START(HFSP_READLOCK, node);
if (!node)
HFSP_ERROR(-1, "record_find_node: Cant position to root node");
while (node->desc.kind == HFSP_NODE_NDX)
{
mid = start = 0;
end = node->desc.num_rec;
comp = -1;
while (start < end)
{
mid = (start + end) >> 1;
p = btree_key_by_index(tree, node, mid);
if (!p)
HFSP_ERROR(-1, "record_find_node: unexpected error");
p = readkey (p, curr_key);
if (!p)
HFSP_ERROR(-1, "record_find_node: unexpected error");
comp = key_compare(curr_key, key);
if (comp > 0)
start = mid + 1;
else if (comp < 0)
end = mid;
else
break;
}
if (!p) // Empty tree, fascinating ...
HFSP_ERROR(-1, "record_find_node: unexpected empty node");
if (comp < 0) // mmh interesting key is before this key ...
{
if (mid == 0)
return NULL; // nothing before this key ..
p = btree_key_by_index(tree, node, mid-1);
if (!p)
HFSP_ERROR(-1, "record_find_node: unexpected error");
p = readkey (p, curr_key);
if (!p)
HFSP_ERROR(-1, "record_find_node: unexpected error");
}
index = bswabU32_inc(p);
node = btree_node_by_index(tree, index, NODE_CLEAN);
}
HFSP_SYNC_END(HFSP_READLOCK, node);
return node; // go on and use the found node
fail:
HFSP_SYNC_END(HFSP_READLOCK, node);
return NULL;
}
/* search for the given key in the btree.
*
* returns pointer to memory just after key or NULL.
*
* *keyind recives the index where the key was found
* (or could be inserted.)
* *node_index is the index of the node where key was found/might
* be inserted before
*/
void* record_find_key(btree* tree, void* key, int* keyind, UInt16* node_index)
{
node_buf* buf = record_find_node(tree, key);
if (buf)
{
int comp = -1;
int start = 0; // components of a binary search
int end = buf->desc.num_rec;
int mid = -1;
void *p = NULL;
char curr_key[tree->head.max_key_len];
hfsp_key_read readkey = tree->kread;
hfsp_key_compare key_compare = tree->kcomp;
HFSP_SYNC_START(HFSP_READLOCK, node);
while (start < end)
{
mid = (start + end) >> 1;
p = btree_key_by_index(tree, buf, mid);
if (!p)
HFSP_ERROR(-1, "record_find_key: unexpected error");
p = readkey (p, curr_key);
if (!p)
goto fail;
comp = key_compare(curr_key, key);
if (comp > 0)
start = mid + 1;
else if (comp < 0)
end = mid;
else
break;
}
if (!p) // Empty tree, fascinating ...
HFSP_ERROR(ENOENT, "record_find_key: unexpected empty node");
*node_index = buf->index;
if (!comp) // found something ...
{
*keyind = mid; // Thats where we found it
HFSP_SYNC_END(HFSP_READLOCK, node);
return p;
}
*keyind = end; // Here we can insert a new key
}
HFSP_ERROR(ENOENT, NULL);
fail:
HFSP_SYNC_END(HFSP_READLOCK, node);
return NULL;
}
/* intialize the record by searching for the given key in the btree.
*
* r is umodified on error.
*/
int record_init_key(record* r, btree* tree, hfsp_cat_key* key)
{
int keyind;
UInt16 node_index;
void *p = record_find_key(tree, key, &keyind, &node_index);
if (p)
{
r -> tree = tree;
r -> node_index= node_index;
r -> keyind = keyind;
r -> key = *key; // Better use a record_key_copy ...
p = record_readentry(p, &r->record);
if (!p)
HFSP_ERROR(-1, "record_init_key: unexpected error");
return 0;
}
fail:
return -1;
}
/* intialize the extent_record to the extent identified by the
* (first) blockindex.
*
* forktype: either HFSP_EXTEND_DATA or HFSP_EXTEND_RSRC
*/
int record_init_file(extent_record* r, btree* tree,
UInt8 forktype, UInt32 fileId, UInt32 blockindex)
{
int keyind;
UInt16 node_index;
hfsp_extent_key key = { 10, forktype, 0, fileId, blockindex };
void *p = record_find_key(tree, &key, &keyind, &node_index);
if (p)
{
r -> tree = tree;
r -> node_index= node_index;
r -> keyind = keyind;
r -> key = key; // Better use a record_key_copy ...
p = volume_readextent(p, r->extent);
if (!p)
HFSP_ERROR(-1, "record_init_file: unexpected error");
return 0;
}
fail:
return -1;
}
/* intialize the record to the folder identified by cnid
*/
int record_init_cnid(record* r, btree* tree, UInt32 cnid)
{
hfsp_cat_key thread_key; // the thread is the first record
thread_key.key_length = 6; // null name (like '.' in unix )
thread_key.parent_cnid = cnid;
thread_key.name.strlen = 0;
return record_init_key(r, tree, &thread_key);
}
/* intialize the record to the first record of the parent.
*/
int record_init_parent(record* r, record* parent)
{
if (parent->record.type == HFSP_FOLDER)
return record_init_cnid(r, parent->tree, parent->record.u.folder.id);
else if(parent->record.type == HFSP_FOLDER_THREAD)
{
if (r != parent)
*r = *parent; // The folder thread is in fact the first entry, like '.'
return 0;
}
HFSP_ERROR(EINVAL,
"record_init_parent: parent is neither folder nor folder thread.");
fail:
return EINVAL;
}
/* intialize the record to the parent directory of the given record.
*/
int record_find_parent(record* r, record* from)
{
UInt16 type = from->record.type;
btree* bt = from->tree;
hfsp_cat_key parentKey;
if (type == HFSP_FOLDER || type == HFSP_FILE)
if (record_init_cnid(r, bt, from->key.parent_cnid))
goto fail;
// r now is the folder thread, position to the real folder
parentKey.key_length = 6 + r->record.u.thread.nodeName.strlen * 2;
parentKey.parent_cnid = r->record.u.thread.parentID;
parentKey.name = r->record.u.thread.nodeName;
if (record_init_key(r, bt, &parentKey))
goto fail;
return 0;
fail:
return -1;
}
/* find correct node record for given node and *pindex.
*
* index of record in this (or next) node
*/
static node_buf* prepare_next(btree* tree, UInt16 node_index, UInt16* pindex)
{
node_buf* buf = btree_node_by_index(tree, node_index, NODE_CLEAN);
btree_node_desc* desc = &buf->desc;
UInt32 numrec = desc->num_rec;
if (*pindex >= numrec) // move on to next node
{
UInt16 next = desc->next;
*pindex = 0;
if (!next /* is there a next node ? */
|| !( buf = btree_node_by_index(tree, next, NODE_CLEAN)))
return NULL;
}
return buf;
}
/* move record foreward to next entry.
*
* In case of an error the value of *r is undefined !
*/
int record_next(record* r)
{
btree* tree = r->tree;
UInt16 index = r->keyind +1;
UInt32 parent;
node_buf* buf = prepare_next(tree, r->node_index, &index);
if (!buf)
return ENOENT; // No (more) such file or directory
parent = r->key.parent_cnid;
if (record_init(r, tree, buf, index))
return -1;
if (r->key.parent_cnid != parent || // end of current directory
index != r->keyind) // internal error ?
return ENOENT; // No (more) such file or directory
return 0;
}
/* move record foreward to next extent record.
*
* In case of an error the value of *r is undefined !
*/
int record_next_extent(extent_record* r)
{
btree* tree = r->tree;
UInt16 index = r->keyind +1;
UInt32 file_id;
UInt8 fork_type;
node_buf* buf = prepare_next(tree, r->node_index, &index);
if (!buf)
return ENOENT; // No (more) such file or directory
file_id = r->key.file_id;
fork_type = r->key.fork_type;
if (record_init_extent(r, tree, buf, index))
return -1;
if (r->key.file_id != file_id || // end of current file
r->key.fork_type != fork_type || // end of current fork
index != r->keyind) // internal error ?
return ENOENT; // No (more) such file or directory
return 0;
}
/* intialize the record by searching for the given string in the given folder.
*
* parent and r may be the same.
*/
int record_init_string_parent(record* r, record* parent, char* name)
{
hfsp_cat_key key;
if (parent->record.type == HFSP_FOLDER)
key.parent_cnid = parent->record.u.folder.id;
else if(parent->record.type == HFSP_FOLDER_THREAD)
key.parent_cnid = parent->key.parent_cnid;
else
HFSP_ERROR(-1, "record_init_string_parent: parent is not a folder.");
key.key_length = 6 + unicode_asc2uni(&key.name,name); // 6 for minumum size
return record_init_key(r, parent->tree, &key);
fail:
return -1;
}
/* move record up in folder hierarchy (if possible) */
int record_up(record* r)
{
if (r->record.type == HFSP_FOLDER)
{
// locate folder thread
if (record_init_cnid(r, r->tree, r->record.u.folder.id))
return -1;
}
else if(r->record.type == HFSP_FOLDER_THREAD)
{
// do nothing were are already where we want to be
}
else
HFSP_ERROR(-1, "record_up: record is neither folder nor folder thread.");
if(r->record.type != HFSP_FOLDER_THREAD)
HFSP_ERROR(-1, "record_up: unable to locate parent");
return record_init_cnid(r, r->tree, r->record.u.thread.parentID);
fail:
return -1;
}
/* Delete the record from the tree but dont care about its type.
* helper function for record_delete */
static int record_delete_direct(record *r)
{
btree *bt = r->tree;
record parent; // Parent folder of the deleted record
UInt16 type = r->record.type;
hfsp_vh *volheader;
HFSP_SYNC_START(HFSP_WRITELOCK, bt);
// Must reload record it may bave become invalid..
if (record_init_key(r, bt, &r->key))
goto fail;
btree_remove_record(bt, r->node_index, r->keyind);
// Care about valence only when not using threads ...
if (type <= HFSP_THREAD_OFFSET)
{
if (record_find_parent(&parent, r))
goto fail;
if (parent.record.u.folder.valence == 0)
fprintf(stderr, "Deleting item from folder with 0 items !?\n");
else
{
parent.record.u.folder.valence --;
parent.record.u.folder.content_mod_date = HFSPTIMEDIFF + time(NULL);
// write back that folder ...
record_update(&parent);
}
}
volheader = &bt->vol->vol;
HFSP_SYNC_END(HFSP_WRITELOCK, bt);
// Update header depending on type
if (type == HFSP_FOLDER_THREAD)
volheader->folder_count--;
else if (type == HFSP_FILE)
volheader->file_count--;
return 0;
fail:
HFSP_SYNC_END(HFSP_WRITELOCK, bt);
return -1;
}
/* recursivly remove contents of folder from btree
*
* r must be a folder thread.
*/
static int record_delete_recurse(record* r, int flags)
{
record iter = *r; // iterator for entries
int result = 0;
if (r->record.type != HFSP_FOLDER_THREAD)
return -1; // should not happen !
while (!result && !record_next(&iter))
{
if (flags & RECORD_DELETE_RECURSE)
result = record_delete(&iter, flags);
// Mmh, this will fail as soon as the b*tree is reorganized :(
else
return ENOTEMPTY; // must not delete non-empty directory
iter = *r; // reset iterator
}
return 0;
}
/* remove record from btree, It does not care about any
* forks associated with a file (yet) */
int record_delete(record* r, int flags)
{
btree *bt = r->tree;
record parent; // Parent folder of the deleted record
hfsp_cat_key parentKey;
UInt16 type = r->record.type;
int result = 0;
if (type == HFSP_FOLDER && !(flags & RECORD_DELETE_DIRECT))
{
record thread;
// locate folder thread and delete it
result = record_init_cnid(&thread, bt, r->record.u.folder.id);
if (!result)
result = record_delete(&thread, flags | RECORD_DELETE_DIRECT);
// failing to delete the folder now will leave the
// btree inconsistant, but this should not happen any more
}
if (type == HFSP_FOLDER_THREAD)
{
// will result in error in case folder is not empty
result = record_delete_recurse(r, flags & ~RECORD_DELETE_DIRECT);
if (!result && !(flags & RECORD_DELETE_DIRECT))
{
record folder;
hfsp_cat_key folderKey;
// locate folder for thread
folderKey.key_length = 6 + r->record.u.thread.nodeName.strlen * 2;
folderKey.parent_cnid = r->record.u.thread.parentID;
folderKey.name = r->record.u.thread.nodeName;
result = record_init_key(&parent, bt, &parentKey);
if (!result) // shortcut recursive call
result = record_delete_direct(&folder);
// failing to delete the folder thread now will leave the
// btree inconsistant, but this should not happen any more
}
}
if (!result)
result = record_delete_direct(r);
return result;
}
/* insert record into btree, It does not care about any
* forks associated with a file (yet)
* ToDo: Care about parent and header counts
*
*/
int record_insert(record* r)
{
btree *bt = r->tree;
record parent; // Parent folder of the new record
UInt16 type = r->record.type;
int result = 0;
char buf[sizeof(record)]; // a bit too long, well
char* p = buf;
int len; // actual len of buffer used
int keyind; // index where key should be inserted
UInt16 nodeind; // node where record should be inserted
hfsp_vh *volheader;
// now insert thread for file/folder
if (type == HFSP_FOLDER || type == HFSP_FILE)
{
record thread;
// create folder thread and insert it
result = record_init_thread(&thread, r);
if (!result)
result = record_insert(&thread);
}
HFSP_SYNC_START(HFSP_WRITELOCK, bt);
// Find out where to insert the record
if (record_find_key(bt, &r->key, &keyind, &nodeind))
HFSP_ERROR(EEXIST,
hfsp_error = "File/Folder already exists");
// Create memory image
p = record_writekey (p, &r->key);
if (!p)
return -1; // ????
p = record_writeentry(p, &r->record);
if (!p)
return -1; // ????
// Insert the buffer
len = p - buf;
if (len > bt->max_rec_size) // Emergency bail out, sorry
{
fprintf(stderr,"Unexpected Buffer overflow in record_insert %d > %d",
len, sizeof(bt->max_rec_size));
exit(-1);
}
if (btree_insert_record(bt,nodeind,keyind,buf,len))
HFSP_ERROR(ENOSPC, "Unable to insert record into tree (volume full ?)");
// Ignore threads for valence and file/folder counts
if (type == HFSP_FOLDER || type == HFSP_FILE)
{
// Update parent valence
if (record_find_parent(&parent, r))
goto fail;
parent.record.u.folder.valence ++;
parent.record.u.folder.content_mod_date = HFSPTIMEDIFF + time(NULL);
// write back that folder ...
record_update(&parent);
volheader = &bt->vol->vol;
// Update header depending on type
if (type == HFSP_FOLDER)
volheader->folder_count++;
else if (type == HFSP_FILE)
volheader->file_count++;
}
HFSP_SYNC_END(HFSP_WRITELOCK, bt);
return result;
fail:
HFSP_SYNC_END(HFSP_WRITELOCK, bt);
return -1;
}
hfsplus-1.0.4/libhfsp/src/record.h 0100644 0000000 0000000 00000007771 07441220605 015560 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes.
*
* a record contains a key and a folder or file and is part
* of a btree.
*
* Copyright (C) 2000 Klaus Halfmann
* Original 1996-1998 Robert Leslie
* Additional work by Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: record.h,v 1.1.1.1 2002/03/05 19:50:29 klaus Exp $
*/
/* Compare two cat_keys ... */
extern int record_key_compare(void* k1, void* k2);
/* Compare two extent_keys ... */
extern int record_extent_key_compare(void* k1, void* k2);
/* read a catalog key into a given buffer */
extern void* record_readkey(void* p, void* buf);
/* read an extent key into a given buffer */
extern void* record_extent_readkey(void* p, void* buf);
/* read a hfsp_cat_entry (catalog record) from memory */
extern void* record_readentry(void *p, void* entry);
/* read an extent record from memory */
// For dependency reasons this actually is found in volume.c
extern void* record_extent_readrecord(void *p, void* entry);
/* intialize the record to the first record of the tree
* which is (per design) the root node.
*/
extern int record_init_root(record* r, btree* tree);
/* intialize the record to the folder given by cnid.
*/
extern int record_init_cnid(record* r, btree* tree, UInt32 cnid);
/* intialize the record to the first record of the parent.
*/
extern int record_init_parent(record* r, record* parent);
/* intialize the record to the parent directory of the given record.
*/
extern int record_find_parent(record* r, record* from);
/* intialize the record by searching for the given string in the given folder.
*
* parent and r may be the same.
*/
extern int record_init_string_parent(record* r, record* parent, char* key);
/* initialize a new (catalog) record with given type and (ascii) name.
* parent must be a HFSP_FOLDER or FOLDER_THREAD
* You should normally call record_insert afterwards.
*/
extern int record_init_string(record* r, UInt16 type, char* name, record* parent);
/* move record up in folder hierarchy (if possible) */
extern int record_up(record* r);
/* move record foreward to next entry.
*
* In case of an error the value of *r is undefined !
*/
extern int record_next(record* r);
/* intialize the extent_record to the extent identified by
* a given file */
extern int record_init_file(extent_record* r, btree* tree,
UInt8 forktype, UInt32 fileId, UInt32 blockindex);
/* move foreward to next entent record. */
extern int record_next_extent(extent_record *r);
/* intialize the record with the given index entry in the btree.
*
* needed by fscheck, do not use in normal code.
*/
extern int record_init(record* r, btree* bt, node_buf* buf, UInt16 index);
/* remove record from btree, It does not (yet) care about any
* forks associated with a file, see below for flags */
extern int record_delete(record* r, int flags);
/* insert record into btree, It does not care about any
* forks associated with a file (yet) */
extern int record_insert(record* r);
/* Do not care about files/folders/threads, needed internally */
#define RECORD_DELETE_DIRECT 0x0001
/* Similar to the rm -f flag, may not be supported */
#define RECORD_DELETE_FORCE 0x0002
/* Descend recursivly in directories and delete them (like rm -R)
* Non-empty directories can not be deleted otherwise */
#define RECORD_DELETE_RECURSE 0x0004
hfsplus-1.0.4/libhfsp/src/swab.h 0100644 0000000 0000000 00000004252 07441220605 015225 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes
*
* Copyright (C) 2000 Klaus Halfmann
* Original work 1996-1998 Robert Leslie
*
* This file defines some byte swapping function. I did not find this
* in any standard or linux way.
*
* 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.
*
* $Id: swab.h,v 1.1.1.1 2002/03/05 19:50:29 klaus Exp $
*/
#include
#include
/* basic fuction:
value = swab_inc(ptr);
ptr is afterwards incremented by sizeof(value)
*/
#if BYTE_ORDER == LITTLE_ENDIAN
#define bswabU16(val) bswap_16(val)
#define bswabU16_inc(ptr) bswap_16(*((UInt16*) (ptr))++)
#define bswabU32_inc(ptr) bswap_32(*((UInt32*) (ptr))++)
#define bswabU64_inc(ptr) bswap_64(*((UInt64*) (ptr))++)
#define bstoreU16_inc(ptr, val) (*((UInt16*) (ptr))++) = bswap_16(val)
#define bstoreU32_inc(ptr, val) (*((UInt32*) (ptr))++) = bswap_32(val)
#define bstoreU64_inc(ptr, val) (*((UInt64*) (ptr))++) = bswap_64(val)
#else // BYTE_ORDER == BIG_ENDIAN
#define bswabU16(val) val
#define bswabU16_inc(ptr) (*((UInt16*) (ptr))++)
#define bswabU32_inc(ptr) (*((UInt32*) (ptr))++)
#define bswabU64_inc(ptr) (*((UInt64*) (ptr))++)
#define bstoreU16_inc(ptr, val) (*((UInt16*) (ptr))++) = val
#define bstoreU32_inc(ptr, val) (*((UInt32*) (ptr))++) = val
#define bstoreU64_inc(ptr, val) (*((UInt64*) (ptr))++) = val
#endif
/* for the sake of compleetness and readability */
#define bswabU8_inc(ptr) (*((UInt8*) (ptr))++)
#define bstoreU8_inc(ptr,val) (*((UInt8*) (ptr))++) = val
hfsplus-1.0.4/libhfsp/src/unicode.c 0100644 0000000 0000000 00000075403 07441220605 015720 0 ustar root root /*
* linux/fs/hfsplus/unicode.c
*
* Copyright (C) 1999-2000 Brad Boyer (flar@pants.nu)
* This file may be distributed under the terms of the GNU Public License.
*
* The routines found here convert hfs-unicode string into ascii Strings
* and vice versa. And the correct comparison between Strings.
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
#include
#include
#include
#include
#define __USE_GNU
/* need wcsrtomb */
#include
#include "libhfsp.h"
#include "unicode.h"
/* convert the asci string astr into a unicode string given by ustr.
*
* ToDo: Think about better error handling ?
*/
int unicode_asc2uni(hfsp_unistr255 *ustr, const char* astr)
{
mbstate_t mbstate = { 0 }; /* Multibyte state */
UInt16* name = ustr->name;
int total = 0;
wchar_t wc;
int len;
while (*astr && total < 255)
{
len = mbrtowc(&wc, astr, MB_CUR_MAX, &mbstate);
if (!len) // eof
break;
if (len < 0) // error
continue;
astr ++;
total += len;
*name ++= wc;
}
return ustr->strlen = total;
}
/* Convert an unicode string ustr to a ascii string astr of given maximum len.
*
* returns actual length of convertet string.
* Eventual conversion errors are ignored.
*/
int unicode_uni2asc(char *astr, const hfsp_unistr255 *ustr, int maxlen)
{
mbstate_t mbstate = { 0 }; /* Multibyte state */
int strlen = ustr->strlen;
const UInt16* name = ustr->name;
int len;
int total;
maxlen -= (MB_CUR_MAX + 1); // leave space for a '\0' and overflow
total = 0;
while ((strlen > 0) && (maxlen > 0))
{
wchar_t wc = *name++;
len = wcrtomb(astr, wc, &mbstate);
strlen--;
if (len < 0) // ignore error ...
continue;
maxlen -= len;
astr += len;
total += len;
}
wcrtomb(astr, 0, &mbstate); // care about rest of state
*astr ='\0';
return total;
}
/* The following code is almost as published by Apple, only
small modifications where made to match some linux styles ...
fastUnicodeCompare - Compare two Unicode strings; produce a relative ordering
*/
static UInt16 gLowerCaseTable[];
SInt32 fast_unicode_compare ( const hfsp_unistr255 *ustr1,
const hfsp_unistr255 *ustr2)
{
register UInt16 c1,c2;
register SInt32 diff;
register UInt16 temp;
register UInt16 length1 = ustr1->strlen;
register UInt16 length2 = ustr2->strlen;
register UInt16* lowerCaseTable = gLowerCaseTable;
register UInt16* str1 = ustr1->name;
register UInt16* str2 = ustr2->name;
while (1) {
// Set default values for c1, c2 in case there are no more valid chars
c1 = c2 = 0;
// Find next non-ignorable char from str1, or zero if no more
while (length1 && c1 == 0) {
c1 = *(str1++);
--length1;
if ((temp = lowerCaseTable[c1>>8]) != 0) // is there a subtable
// for this upper byte?
c1 = lowerCaseTable[temp + (c1 & 0x00FF)]; // yes, so fold the char
}
// Find next non-ignorable char from str2, or zero if no more
while (length2 && c2 == 0) {
c2 = *(str2++);
--length2;
if ((temp = lowerCaseTable[c2>>8]) != 0) // is there a subtable
// for this upper byte?
c2 = lowerCaseTable[temp + (c2 & 0x00FF)]; // yes, so fold the char
}
diff = c2-c1;
if (diff) // found a difference, so stop looping
break;
if (c1 == 0) // did we reach the end of both strings at the same time?
return 0; // yes, so strings are equal
}
return diff;
}
/* The lower case table consists of a 256-entry high-byte table followed by
some number of 256-entry subtables. The high-byte table contains either an
offset to the subtable for characters with that high byte or zero, which
means that there are no case mappings or ignored characters in that block.
Ignored characters are mapped to zero.
*/
static UInt16 gLowerCaseTable[] = {
// High-byte indices ( == 0 iff no case mapping and no ignorables )
/* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 1 */ 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 2 */ 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 3 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 4 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 5 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 6 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 9 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* E */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* F */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00,
// Table 1 (for high byte 0x00)
/* 0 */ 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
/* 1 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
/* 2 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
/* 3 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
/* 4 */ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
/* 5 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
/* 6 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
/* 7 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
/* 8 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
/* 9 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
/* A */ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
/* B */ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
/* C */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7,
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
/* D */ 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF,
/* E */ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
/* F */ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
// Table 2 (for high byte 0x01)
/* 0 */ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F,
/* 1 */ 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117,
0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F,
/* 2 */ 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127,
0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F,
/* 3 */ 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137,
0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140,
/* 4 */ 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F,
/* 5 */ 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157,
0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F,
/* 6 */ 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167,
0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F,
/* 7 */ 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177,
0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F,
/* 8 */ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
/* 9 */ 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
/* A */ 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8,
0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF,
/* B */ 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
/* C */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF,
/* D */ 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7,
0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF,
/* E */ 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7,
0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF,
/* F */ 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7,
0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF,
// Table 3 (for high byte 0x03)
/* 0 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
/* 1 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F,
/* 2 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F,
/* 3 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F,
/* 4 */ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F,
/* 5 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F,
/* 6 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F,
/* 7 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F,
/* 8 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,
0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,
/* 9 */ 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
/* A */ 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
/* B */ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
/* C */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF,
/* D */ 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,
/* E */ 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
/* F */ 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,
0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,
// Table 4 (for high byte 0x04)
/* 0 */ 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407,
0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F,
/* 1 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
/* 2 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
/* 3 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
/* 4 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
/* 5 */ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F,
/* 6 */ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467,
0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F,
/* 7 */ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477,
0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F,
/* 8 */ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,
/* 9 */ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497,
0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F,
/* A */ 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7,
0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF,
/* B */ 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7,
0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF,
/* C */ 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8,
0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF,
/* D */ 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7,
0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF,
/* E */ 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7,
0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF,
/* F */ 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7,
0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF,
// Table 5 (for high byte 0x05)
/* 0 */ 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507,
0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F,
/* 1 */ 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517,
0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,
/* 2 */ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,
/* 3 */ 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
/* 4 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
/* 5 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557,
0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,
/* 6 */ 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
/* 7 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
/* 8 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587,
0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F,
/* 9 */ 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597,
0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F,
/* A */ 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7,
0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF,
/* B */ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
/* C */ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7,
0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF,
/* D */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
/* E */ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF,
/* F */ 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7,
0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF,
// Table 6 (for high byte 0x10)
/* 0 */ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F,
/* 1 */ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017,
0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F,
/* 2 */ 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F,
/* 3 */ 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037,
0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F,
/* 4 */ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047,
0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F,
/* 5 */ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057,
0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F,
/* 6 */ 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067,
0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F,
/* 7 */ 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077,
0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F,
/* 8 */ 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087,
0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F,
/* 9 */ 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097,
0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F,
/* A */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
/* B */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
/* C */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7,
0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF,
/* D */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
/* E */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
/* F */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7,
0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF,
// Table 7 (for high byte 0x20)
/* 0 */ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000,
/* 1 */ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017,
0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F,
/* 2 */ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027,
0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F,
/* 3 */ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037,
0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F,
/* 4 */ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047,
0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F,
/* 5 */ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057,
0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F,
/* 6 */ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067,
0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* 7 */ 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077,
0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F,
/* 8 */ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087,
0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F,
/* 9 */ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097,
0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F,
/* A */ 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7,
0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF,
/* B */ 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7,
0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF,
/* C */ 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7,
0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF,
/* D */ 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7,
0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF,
/* E */ 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7,
0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF,
/* F */ 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7,
0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF,
// Table 8 (for high byte 0x21)
/* 0 */ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107,
0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F,
/* 1 */ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117,
0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F,
/* 2 */ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127,
0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F,
/* 3 */ 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137,
0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F,
/* 4 */ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,
0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,
/* 5 */ 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,
0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,
/* 6 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
/* 7 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
/* 8 */ 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187,
0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F,
/* 9 */ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197,
0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F,
/* A */ 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7,
0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF,
/* B */ 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7,
0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF,
/* C */ 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7,
0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF,
/* D */ 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7,
0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF,
/* E */ 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7,
0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF,
/* F */ 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7,
0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF,
// Table 9 (for high byte 0xFE)
/* 0 */ 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07,
0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F,
/* 1 */ 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17,
0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F,
/* 2 */ 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27,
0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F,
/* 3 */ 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37,
0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F,
/* 4 */ 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47,
0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F,
/* 5 */ 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57,
0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F,
/* 6 */ 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67,
0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F,
/* 7 */ 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77,
0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F,
/* 8 */ 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87,
0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F,
/* 9 */ 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97,
0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F,
/* A */ 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7,
0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF,
/* B */ 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7,
0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF,
/* C */ 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7,
0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF,
/* D */ 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7,
0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF,
/* E */ 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7,
0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
/* F */ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7,
0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000,
// Table 10 (for high byte 0xFF)
/* 0 */ 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07,
0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,
/* 1 */ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,
/* 2 */ 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
/* 3 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
/* 4 */ 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
/* 5 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F,
/* 6 */ 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
/* 7 */ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
/* 8 */ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87,
0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
/* 9 */ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97,
0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
/* A */ 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7,
0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF,
/* B */ 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7,
0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF,
/* C */ 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7,
0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF,
/* D */ 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7,
0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF,
/* E */ 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7,
0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF,
/* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7,
0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF,
};
hfsplus-1.0.4/libhfsp/src/unicode.h 0100644 0000000 0000000 00000001534 07441220605 015717 0 ustar root root /*
* linux/fs/hfsplus/unicode.c
*
* Copyright (C) 1999-2000 Brad Boyer (flar@pants.nu)
* This file may be distributed under the terms of the GNU Public License.
*
* The routines found here convert hfs-unicode string into ascii Strings
* and vice versa. Tehy allow the correct comparison between Strings.
*/
/* convert the asci string astr into a unicode string given by ustr.
*
* returns actual length of convertet string.
*/
int unicode_asc2uni(hfsp_unistr255 *ustr, const char *astr);
/* Convert an unicode string ustr to a ascii string astr of given maximum len
*
* returns actual length of convertet string.
*/
int unicode_uni2asc(char *astr, const hfsp_unistr255 *ustr, int maxlen);
/* similar to strcmp for unicode, pascal strings */
SInt32 fast_unicode_compare (const hfsp_unistr255 *ustr1,
const hfsp_unistr255 *ustr2);
hfsplus-1.0.4/libhfsp/src/volume.c 0100644 0000000 0000000 00000043554 07450133475 015613 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes
*
* Code to acces the basic volume information of a HFS+ volume.
*
* Copyright (C) 2000 Klaus Halfmann
* Original work by 1996-1998 Robert Leslie
* other work 2000 from Brad Boyer (flar@pants.nu)
*
* 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.
*
* $Id: volume.c,v 1.6 2002/03/26 18:00:29 klaus Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include
# include
# include
# include
# include
# include "libhfsp.h"
# include "volume.h"
# include "record.h"
# include "btree.h"
# include "blockiter.h"
# include "os.h"
# include "swab.h"
# include "hfstime.h"
# include "partitions.h"
/* Fill a given buffer with the given block in volume.
*/
int volume_readinbuf(volume * vol,void* buf, long block)
{
UInt16 blksize_bits;
ASSERT( block < vol->maxblocks);
blksize_bits = vol->blksize_bits;
// printf("Reading from %lx\n", block << blksize_bits);
if (os_seek(&vol->fd, block, blksize_bits) == block)
if (1 == os_read(&vol->fd, buf, 1, blksize_bits))
return 0;
return -1;
}
/* Write buffer to given block on medium.
*/
int volume_writetobuf(volume * vol,void* buf, long block)
{
UInt16 blksize_bits;
ASSERT( block < vol->maxblocks);
blksize_bits = vol->blksize_bits;
// printf("Writing to %lx\n", block << blksize_bits);
if (os_seek(&vol->fd, block, blksize_bits) == block)
if (1 == os_write(&vol->fd, buf, 1, blksize_bits))
return 0;
return -1;
}
/* read multiple blocks of a fork into given memory.
*
* block realtive index in fork to start with
* count number of blocks to read
* forktype usually HFSP_EXTENT_DATA or HFSP_EXTENT_RSRC
* fileId id (needed) in case extents must be fetched
*
* returns given pinter or NULL on failure.
*/
void* volume_readfromfork(volume* vol, void* buf,
hfsp_fork_raw* f, UInt32 block,
UInt32 count, UInt8 forktype, UInt32 fileId)
{
blockiter iter;
char* cbuf = buf;
blockiter_init(&iter, vol, f, forktype, fileId);
if (blockiter_skip(&iter, block))
return NULL;
while (count > 0)
{
--count;
if (volume_readinbuf(vol, cbuf, blockiter_curr(&iter)))
return NULL;
cbuf += vol->blksize;
if (count > 0 && blockiter_next(&iter))
return NULL;
}
return buf;
}
/* write multiple blocks of a fork buf to medium.
* The caller is responsible for allocating a suffient
* large fork and eventually needed extends records for now.
*
* block realtive index in fork to start with
* count number of blocks to write
* forktype usually HFSP_EXTENT_DATA or HFSP_EXTENT_RSRC
* fileId id (needed) in case extents must be written
*
* returns value != 0 on error.
*/
int volume_writetofork(volume* vol, void* buf,
hfsp_fork_raw* f, UInt32 block,
UInt32 count, UInt8 forktype, UInt32 fileId)
{
blockiter iter;
char* cbuf = buf;
blockiter_init(&iter, vol, f, forktype, fileId);
if (blockiter_skip(&iter, block))
return -1;
while (count > 0)
{
--count;
if (volume_writetobuf(vol, cbuf, blockiter_curr(&iter)))
return -1;
cbuf += vol->blksize;
if (count > 0 && blockiter_next(&iter))
return -1;
}
return 0;
}
/* Check in Allocation file if given block is allocated.
*/
int volume_allocated(volume* vol, UInt32 block)
{
int bit = block & 0x07;
int mask,index;
char* bits;
char buf[vol->blksize];
// if (block >= vol->maxblocks)
// HFSP_ERROR(-1, "Allocation block out of range.");
block >>= 3;
mask = (1 << vol->blksize_bits) -1; /* Usually 0x0FFF */
index = block & mask;
block >>= vol->blksize_bits; // block in allocation file
bits = (char*) volume_readfromfork(vol, buf, &vol->vol.alloc_file,
block, 1, HFSP_EXTENT_DATA, HFSP_ALLOC_CNID);
if (!bits)
HFSP_ERROR(-1, "Allocation block not found !?");
return (bits[index] & (0x80 >> bit)); /* Bit one is 0x80 ! */
return 0;
fail:
return -1;
}
/* Mark in Allocation file a given block as allocated.
*
* ToDo: optimize for adjacent blocks ...
* use cache directly
*/
int volume_allocate(volume* vol, UInt32 block)
{
int bit = block & 0x07;
int mask,index;
char* bits;
char buf[vol->blksize];
int shift = 0x80 >> bit; /* Bit one is 0x80 */
// if (block >= vol->maxblocks)
// HFSP_ERROR(-1, "Allocation block out of range.");
block >>= 3;
mask = (1 << vol->blksize_bits) -1; /* Usually 0x0FFF */
index = block & mask;
block >>= vol->blksize_bits; // block in allocation file
bits = (char*) volume_readfromfork(vol, buf, &vol->vol.alloc_file,
block, 1, HFSP_EXTENT_DATA, HFSP_ALLOC_CNID);
if (!bits)
HFSP_ERROR(-1, "Allocation block not found !?");
if (bits[index] & shift)
HFSP_ERROR(-1, "volume_allocate: Block already allocated");
bits[index] |= shift;
return volume_writetofork(vol, buf, &vol->vol.alloc_file,
block, 1, HFSP_EXTENT_DATA, HFSP_ALLOC_CNID);
fail:
return -1;
}
/* Mark in Allocation file a given block as freee.
*
* ToDo: optimize for adjacent blocks ...
* use cache directly
*/
int volume_deallocate(volume* vol, UInt32 block)
{
int bit = block & 0x07;
int mask,index;
char* bits;
char buf[vol->blksize];
int shift = 0x80 >> bit; /* Bit one is 0x80 */
// if (block >= vol->maxblocks)
// HFSP_ERROR(-1, "Allocation block out of range.");
block >>= 3;
mask = (1 << vol->blksize_bits) -1; /* Usually 0x0FFF */
index = block & mask;
block >>= vol->blksize_bits; // block in allocation file
bits = (char*) volume_readfromfork(vol, buf, &vol->vol.alloc_file,
block, 1, HFSP_EXTENT_DATA, HFSP_ALLOC_CNID);
if (!bits)
HFSP_ERROR(-1, "Allocation block not found !?");
if (!(bits[index] & shift))
HFSP_ERROR(-1, "volume_allocate: Block already free");
bits[index] &= ~shift;
return volume_writetofork(vol, buf, &vol->vol.alloc_file,
block, 1, HFSP_EXTENT_DATA, HFSP_ALLOC_CNID);
fail:
return -1;
}
/* Initialize a raw hfsp_extent_rec.
*/
static void volume_initextent(hfsp_extent_rec er)
{
memset(er, 0, 8 * sizeof(hfsp_extent));
/*
int i;
hfsp_extent* e;
for (i=0; i < 8; i++)
{
e = &er[i];
e->start_block = 0;
e->block_count = 0;
}
*/
}
/** Initalize an (empty !) fork, you may later request additional space
*/
void volume_initfork(volume* vol, hfsp_fork_raw* f, UInt16 fork_type)
{
f->total_size = 0;
if (fork_type == HFSP_EXTENT_DATA)
f->clump_size = vol->vol.data_clump_sz;
else
f->clump_size = vol->vol.rsrc_clump_sz;
f->total_blocks = 0;
volume_initextent(f->extents);
}
/* Read a raw hfsp_extent_rec from memory.
*
* return pointer right after the structure.
*/
void* volume_readextent(void *p, hfsp_extent_rec er)
{
int i;
hfsp_extent* e;
for (i=0; i < 8; i++)
{
e = &er[i];
e->start_block = bswabU32_inc(p);
e->block_count = bswabU32_inc(p);
}
return p;
}
/* Write a raw hfsp_extent_rec to memory.
*
* return pointer right after the structure.
*/
void* volume_writeextent(void *p, hfsp_extent_rec er)
{
int i;
hfsp_extent* e;
for (i=0; i < 8; i++)
{
e = &er[i];
bstoreU32_inc(p, e->start_block );
bstoreU32_inc(p, e->block_count );
}
return p;
}
/* Read a raw hfsp_fork from memory.
*
* return pointer right after the structure.
*/
void* volume_readfork(void *p, hfsp_fork_raw* f)
{
f->total_size = bswabU64_inc(p);
f->clump_size = bswabU32_inc(p);
f->total_blocks = bswabU32_inc(p);
return volume_readextent(p, f->extents);
}
/* Write a raw hfsp_fork to memory.
*
* return pointer right after the structure.
*/
void* volume_writefork(void *p, hfsp_fork_raw* f)
{
bstoreU64_inc(p, f->total_size );
bstoreU32_inc(p, f->clump_size );
bstoreU32_inc(p, f->total_blocks);
return volume_writeextent(p, f->extents);
}
/* Read the volume from the given buffer and swap the bytes.
*/
static int volume_readbuf(hfsp_vh* vh, void* p)
{
if ( (vh->signature = bswabU16_inc(p)) != HFSP_VOLHEAD_SIG)
HFSP_ERROR(-1, "This is not a HFS+ volume");
vh->version = bswabU16_inc(p);
vh->attributes = bswabU32_inc(p);
vh->last_mount_vers = bswabU32_inc(p);
vh->reserved = bswabU32_inc(p);
vh->create_date = bswabU32_inc(p);
vh->modify_date = bswabU32_inc(p);
vh->backup_date = bswabU32_inc(p);
vh->checked_date = bswabU32_inc(p);
vh->file_count = bswabU32_inc(p);
vh->folder_count = bswabU32_inc(p);
vh->blocksize = bswabU32_inc(p);
vh->total_blocks = bswabU32_inc(p);
vh->free_blocks = bswabU32_inc(p);
vh->next_alloc = bswabU32_inc(p);
vh->rsrc_clump_sz = bswabU32_inc(p);
vh->data_clump_sz = bswabU32_inc(p);
vh->next_cnid = bswabU32_inc(p);
vh->write_count = bswabU32_inc(p);
vh->encodings_bmp = bswabU64_inc(p);
memcpy(vh->finder_info, p, 32);
((char*) p) += 32; // finderinfo is not used by now
p = volume_readfork(p, &vh->alloc_file );
p = volume_readfork(p, &vh->ext_file );
p = volume_readfork(p, &vh->cat_file );
p = volume_readfork(p, &vh->attr_file );
p = volume_readfork(p, &vh->start_file );
return 0;
fail:
return -1;
}
/* Write the volume to the given buffer and swap the bytes.
*/
static int volume_writebuf(hfsp_vh* vh, void* p)
{
bstoreU16_inc(p, vh->signature );
bstoreU16_inc(p, vh->version );
bstoreU32_inc(p, vh->attributes );
bstoreU32_inc(p, vh->last_mount_vers);
bstoreU32_inc(p, vh->reserved );
bstoreU32_inc(p, vh->create_date );
bstoreU32_inc(p, vh->modify_date );
bstoreU32_inc(p, vh->backup_date );
bstoreU32_inc(p, vh->checked_date );
bstoreU32_inc(p, vh->file_count );
bstoreU32_inc(p, vh->folder_count );
bstoreU32_inc(p, vh->blocksize );
bstoreU32_inc(p, vh->total_blocks );
bstoreU32_inc(p, vh->free_blocks );
bstoreU32_inc(p, vh->next_alloc );
bstoreU32_inc(p, vh->rsrc_clump_sz );
bstoreU32_inc(p, vh->data_clump_sz );
bstoreU32_inc(p, vh->next_cnid );
bstoreU32_inc(p, vh->write_count );
bstoreU64_inc(p, vh->encodings_bmp );
memcpy(p, vh->finder_info, 32);
((char*) p) += 32; // finderinfo is not used by now
p = volume_writefork(p, &vh->alloc_file );
p = volume_writefork(p, &vh->ext_file );
p = volume_writefork(p, &vh->cat_file );
p = volume_writefork(p, &vh->attr_file );
p = volume_writefork(p, &vh->start_file );
return 0;
}
/* Read the volume from the given block */
static int volume_read(volume * vol, hfsp_vh* vh, UInt32 block)
{
char buf[vol->blksize];
if (volume_readinbuf(vol, buf, block))
return -1;
return volume_readbuf(vh, buf);
}
/* Find out wether the volume is wrapped and unwrap it eventually */
static int volume_read_wrapper(volume * vol, hfsp_vh* vh)
{
UInt16 signature;
char buf[vol->blksize];
void *p = buf;
if( volume_readinbuf(vol, buf, 2) ) // Wrapper or volume header starts here
return -1;
signature = bswabU16_inc(p);
if (signature == HFS_VOLHEAD_SIG) /* Wrapper */
{
UInt32 drAlBlkSiz; /* size (in bytes) of allocation blocks */
UInt32 sect_per_block; /* how may block build an hfs sector */
UInt16 drAlBlSt; /* first allocation block in volume */
UInt16 embeds, embedl; /* Start/lenght of embedded area in blocks */
((char*) p) += 0x12; /* skip unneeded HFS vol fields */
drAlBlkSiz = bswabU32_inc(p); /* offset 0x14 */
((char*) p) += 0x4; /* skip unneeded HFS vol fields */
drAlBlSt = bswabU16_inc(p); /* offset 0x1C */
((char*) p) += 0x5E; /* skip unneeded HFS vol fields */
signature = bswabU16_inc(p); /* offset 0x7C, drEmbedSigWord */
if (signature != HFSP_VOLHEAD_SIG)
HFSP_ERROR(-1, "This looks like a normal HFS volume");
embeds = bswabU16_inc(p);
embedl = bswabU16_inc(p);
sect_per_block = (drAlBlkSiz / HFSP_BLOCKSZ);
// end is absolute (not relative to HFS+ start)
vol->maxblocks = embedl * sect_per_block;
os_offset += ((UInt64) (drAlBlSt + embeds * sect_per_block))
<< HFS_BLOCKSZ_BITS;
/* Now we can try to read the embedded HFS+ volume header */
return volume_read(vol,vh,2);
}
else if (signature == HFSP_VOLHEAD_SIG) /* Native HFS+ volume */
{
p = buf; // Restore to begin of block
return volume_readbuf(vh, p);
} else
HFSP_ERROR(-1, "Neither Wrapper nor native HFS+ volume header found");
fail:
return -1;
}
/** Mark the volume as modified by setting its modfied date */
void volume_modified(volume* vol)
{
time_t now;
hfsp_vh* head;
gmtime(&now);
head = &vol->vol;
head->modify_date = now + HFSPTIMEDIFF;
}
/** Mark this volume as used by Linux by modifying the header */
void volume_linux_mark(volume* vol)
{
hfsp_vh* head = &vol->vol;
// *** Debugging ***
vol ->flags |= HFSP_BACKUP_DIRTY;
// MacOS does not like that :(
// head->version = HPUTILS_VERS;
head->last_mount_vers = HPLS_SIGNATURE;
// For now I always mark the volume as inconsistent ...
head->attributes |= HFSPLUS_VOL_INCNSTNT;
volume_modified(vol);
}
/* Open the device, read and verify the volume header
(and its backup) */
int volume_open(volume* vol, char* devname, int partition, int rw)
{
hfsp_vh backup; /* backup volume found at second to last block */
int shift;
int blksize_bits;
vol->blksize_bits = HFSP_BLOCKSZ_BITS;
vol->flags = 0;
vol->blksize = HFSP_BLOCKSZ;
vol->maxblocks = 3;
/* this should be enough until we find the volume descriptor */
vol->extents = NULL; /* Thanks to Jeremias Sauceda */
btree_reset(&vol->catalog);
if (os_open(&vol->fd, devname, rw))
return -1;
/* set the offset to the first block of the given partition */
if( partition!= 0) {
partition_map map;
int block;
if( partition_getPartitionMap( &map, vol->fd)== -1)
HFSP_ERROR(-1, "No Apple partition map found");
block = partition_getStartBlock( &map, "Apple_HFS", partition);
if (block == 0)
HFSP_ERROR(-1, "No valid Apple_HFS partition found");
os_offset = ((UInt64)block) << HFSP_BLOCKSZ_BITS;
}
vol->flags |= rw & HFSP_MODE_RDWR;
if (volume_read_wrapper(vol, &vol->vol))
return -1;
if (volume_read(vol, &backup, vol->maxblocks - 2))
return -1;
/* Now switch blksize from HFSP_BLOCKSZ (512) to value given in header
and adjust depend values accordingly, after that a block always
means a HFS+ allocation size */
/* Usually blocksize is 4096 */
blksize_bits = ffs(vol->vol.blocksize) -1;
shift = blksize_bits - vol->blksize_bits;
vol -> blksize = vol->vol.blocksize;
vol -> blksize_bits = blksize_bits;
vol -> maxblocks = vol->vol.total_blocks; /* cant calculate via shift ? */
if (vol->flags & HFSP_MODE_RDWR)
{
char buf[HFSP_BLOCKSZ];
void *p = buf;
volume_linux_mark(vol);
// write back (dirty) volume header
if (volume_writebuf(&vol->vol, p))
return -1; // evil, but will never happen
volume_writetobuf(vol, buf, 2); // This is always block 2
}
if (btree_init_cat(&vol->catalog, vol, &vol->vol.cat_file))
return -1;
return 0;
fail:
return -1;
}
/* Write back all data eventually cached and close the device */
int volume_close(volume* vol)
{
btree_close(&vol->catalog);
if (vol->extents)
{
btree_close(vol->extents);
FREE(vol->extents);
}
if (vol->flags & HFSP_MODE_RDWR) // volume was opened for writing,
{
/* Switch back to HFSP_BLOCKSZ (512) */
int shift = vol->blksize_bits - HFSP_BLOCKSZ_BITS;
char buf[HFSP_BLOCKSZ];
void *p = buf;
hfsp_vh* head = &vol->vol;
// Clear inconsistent flag
head->attributes &= ~HFSPLUS_VOL_INCNSTNT;
// set Unmounted flag
head->attributes |= HFSPLUS_VOL_UNMNT;
vol->blksize_bits = HFSP_BLOCKSZ_BITS;
vol -> maxblocks <<= shift; /* cant calculate via shift ? */
if (volume_writebuf(&vol->vol, p))
return -1; // evil, but will never happen
volume_writetobuf(vol, buf, 2); // This is always block 2
if (vol->flags & HFSP_BACKUP_DIRTY) // need to write backup block, too
{
// !!! Need to check this with larger volumes, too !!!
volume_writetobuf(vol, buf, vol->maxblocks-2);
}
}
return os_close(&vol->fd);
}
/* internal fucntion used to create the extents btree,
is called by inline function when needed */
void volume_create_extents_tree(volume* vol)
{
btree* result = (btree*) ALLOC(btree*, sizeof(btree));
if (!result)
HFSP_ERROR(ENOMEM, "No memory for extents btree");
if (!btree_init_extent(result, vol, &vol->vol.ext_file))
{
vol->extents = result;
return;
}
fail:
vol->extents = NULL;
}
/* accessor for entends btree, is created on demand */
/* inline */ btree* volume_get_extents_tree(volume* vol)
{
if (!vol->extents)
volume_create_extents_tree(vol);
return vol->extents;
}
/* return new Id for files/folder and check for overflow.
*
* retun 0 on error .
*/
UInt32 volume_get_nextid(volume* vol)
{
UInt32 result = vol->vol.next_cnid;
if (result < HFSP_MIN_CNID) // oops possible wrap around overflow
{
hfsp_error = "Maximum number of node IDs exhausted, sorry";
return 0;
}
vol->vol.next_cnid = 1 + result;
return result;
}
hfsplus-1.0.4/libhfsp/src/volume.h 0100644 0000000 0000000 00000006127 07444577574 015632 0 ustar root root /*
* libhfs - library for reading and writing Macintosh HFS volumes
*
* Copyright (C) 2000 Klaus Halfmann
* Original 1996-1998 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.
*
* $Id: volume.h,v 1.2 2002/03/16 08:17:00 klaus Exp $
*/
/* Open the device, read and verify the volume header
(and its backup) */
extern int volume_open(volume* vol, char* devname, int partition, int rw);
/* Write back all data eventually cached and close the device. */
extern int volume_close(volume* vol);
/* read multiple blocks into given memory.
*
* returns given pointer or NULL on failure.
*/
extern void* volume_readfromfork(volume* vol, void* buf,
hfsp_fork_raw* f, UInt32 block,
UInt32 count, UInt8 forktype, UInt32 fileId);
/* write multiple blocks of a fork buf to medium.
* The caller is responsible for allocating a suffient
* large fork and eventually needed extends records for now.
*
* block realtive index in fork to start with
* count number of blocks to write
* forktype usually HFSP_EXTENT_DATA or HFSP_EXTENT_RSRC
* fileId id (needed) in case extents must be written
*
* returns value != 0 on error.
*/
int volume_writetofork(volume* vol, void* buf,
hfsp_fork_raw* f, UInt32 block,
UInt32 count, UInt8 forktype, UInt32 fileId);
/* Fill a given buffer with the given block in volume.
*/
int volume_readinbuf(volume * vol,void* buf, long block);
/* Check in Allocation file if given block is allocated. */
extern int volume_allocated(volume* v, UInt32 block);
/* Read a raw hfsp_extent_rec from memory. */
extern void* volume_readextent(void *p, hfsp_extent_rec er);
/* Read fork information from raw memory */
extern void* volume_readfork(void *p, hfsp_fork_raw* f);
/* Write fork information to raw memory */
extern void* volume_writefork(void *p, hfsp_fork_raw* f);
/* Initialize for to all zero, you may allocate later */
void volume_initfork(volume* vol, hfsp_fork_raw* f, UInt16 fork_type);
/* internal function used to create the extents btree,
is called by following inline function when needed */
extern void volume_create_extents_tree(volume* vol);
/* accessor for entends btree, is created on demand */
extern inline btree* volume_get_extents_tree(volume* vol)
{
if (!vol->extents)
volume_create_extents_tree(vol);
return vol->extents;
}
/* return new Id for files/folder and check for overflow.
*
* retun 0 on error .
*/
extern UInt32 volume_get_nextid(volume* vol);
hfsplus-1.0.4/libhfsp/.cvsignore 0100644 0000000 0000000 00000000237 07441220604 015327 0 ustar root root Makefile
Makefile.in
configure
config.h
config.cache
config.status
config.sub
config.guess
ltconfig
ltmain.sh
stamp-h
stamp-h.in
libtool
config.log
aclocal.m4
hfsplus-1.0.4/libhfsp/Makefile.am 0100644 0000000 0000000 00000000313 07441220604 015356 0 ustar root root #
# Makefile.am for hfsplus
#
# Created by Klaus Kaempf and
# Klaus Halfmann
#
# $Id: Makefile.am,v 1.1.1.1 2002/03/05 19:50:28 klaus Exp $
SUBDIRS = src
hfsplus-1.0.4/libhfsp/test/ 0040755 0000000 0000000 00000000000 07450157145 014320 5 ustar root root hfsplus-1.0.4/libhfsp/test/.cvsignore 0100644 0000000 0000000 00000000101 07441220605 016275 0 ustar root root Makefile
Makefile.in
*.o
*.lo
.deps
.libs
*.a
*.la
hfsptest
core
hfsplus-1.0.4/libhfsp/test/Makefile.am 0100644 0000000 0000000 00000002130 07441220605 016335 0 ustar root root #
# Makefile.am for libhfsp/test
# Created by Klaus Kaempf
#
#
# libhfsp+ - library for reading and writing Macintosh HFS+ volumes
# Copyright (C) 1996-1998 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.
#
# $Id: Makefile.am,v 1.1.1.1 2002/03/05 19:50:29 klaus Exp $
#
testdir = .
test_PROGRAMS = hfsptest
hfsptest_SOURCES = test.c
hfsptest_LDADD = ../src/libhfsp.la
INCLUDES = -I../src
clean-local:
rm -f hfsptest
EXTRA_DIST = volumes
hfsplus-1.0.4/libhfsp/test/dump1.txt 0100644 0000000 0000000 00000065730 07441220605 016107 0 ustar root root
# This is a commented dump of an freshly formatted HFS+ volume
# (Thanks to Hollis Blanchard for providing it.)
#
# $Id: dump1.txt,v 1.1.1.1 2002/03/05 19:50:29 klaus Exp $
#
# This dump was created using xxd -a (not od, not hexdump)
#
0 1 2 3 4 5 6 7 8 9 A B C D E F
0000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
A master volume record is always found on block 2 2*0x200 = 0x4000
The HFS Wrapper for the HFS volume starts here ('BD')
0000400: 4244 b5ad f194 b5ad f337 8200 0006 0003 BD.......7......
# 0x12 (drNmAlBlks) number of allocation blocks: 7ff9
# 0x14 (drAlBlkSiz) is the blocksize: 0x00000400
# 0x1C (drAlBlSt) is the first allocation block 0x000B
0000410: 000d 7ff9 0000 0400 0000 0400 000b 0000 ................
0000420: 0016 0000 0564 6973 6b31 7573 0000 0000 .....disk1us....
0000430: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000440: 0000 0000 0000 0000 000f 0000 1000 0000 ................
0000450: 1000 0000 0000 0006 0000 0000 0000 0002 ................
0000460: 0000 0000 0000 0000 0000 0000 0000 0000 ................
# 0x7C: H+ indicates that this is a HFS wrapper
# 0x7E: Start block of embedded HFS+ system in Wrapper: 0x0024
# Starblock 0x53 = 0x0b + 0x024 * 2 (blocksize / 0x200 = def blocksize)
# Startadr 0x53 * 0x200 = 0xa600
0000470: 0000 0000 0000 0000 0000 0000 482b 0024 ............H+.$
# 0x80 end of embedded filesystem 0x7fd5
# Lastblock 0xfffd = 0x0b + 0x7fd5 * 2 (blocksize / 0x200 = def blocksize)
# Lastadr (0xfffd + 1) * 0x200 = 0x1FFFC00
0000480: 7fd5 0000 1000 0000 0004 0000 0000 0000 ................
0000490: 0000 0000 1000 0004 0004 0000 0000 0000 ................
00004a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
0000600: ffff ffff ffff ffff ffff ffff ffff ffff ................
*
# This is the hfs volume bitmap marking the wrapper
# as reserverd. A real waste of space uuuh
#
00015e0: ffff ffff ffff ffff ffff ffff ffff ffff ................
00015f0: ffff ffff ffff ffff ffff ffff ffff ff80 ................
*
# More parts of the HFS Wrapper omnitted ...
*
# This text explains the function of the wrapper
0003a00: 5768 7920 6361 6e27 7420 796f 7520 7365 Why can't you se
0003a10: 6520 796f 7572 2066 696c 6573 3f0d 0d54 e your files?..T
0003a20: 6869 7320 6861 7264 2064 6973 6b20 6973 his hard disk is
0003a30: 2066 6f72 6d61 7474 6564 2077 6974 6820 formatted with
0003a40: 7468 6520 4d61 6320 4f53 2045 7874 656e the Mac OS Exten
0003a50: 6465 6420 666f 726d 6174 2e20 596f 7572 ded format. Your
# ...
# A small, pseudo System folder is included ...
0005310: 0072 5468 6973 2073 7461 7274 7570 2064 .rThis startup d
0005320: 6973 6b20 7769 6c6c 206e 6f74 2077 6f72 isk will not wor
0005330: 6b20 6f6e 2074 6869 7320 636f 6d70 7574 k on this comput
0005340: 6572 2e2f 4120 506f 7765 7220 5043 2062 er./A Power PC b
# ...
The Wrapper was formatted on on a japanese OS8 or 9
(thanks to Hollis Blanchard), and theirefore contained
a Kanji readme, too ...)
*
000a600: # Start of the embedded HFS+ volume
*
# A master volume record is always found on block 2 2*0x200+a600 = 0xaa00
# 0x00 Signture: 'H+'
# 0x02 Version: A04
# 0x04 Attributes: HFSPLUS_VOL_UNMNT (sucessfully unmounted ...)
# 0x08 Last Mounted Version '8.10' (others seen ?)
000aa00: 482b 0004 0000 0100 382e 3130 0000 0000 H+......8.10....
# Variant whem mounted from HFSUTILS
# 0x00 Signture: 'H+'
# 0x02 Version: 0x0102 -> Version 1.0.2
# 0x04 Attributes: HFSPLUS_VOL_UNMNT (sucessfully unmounted ...)
# 0x08 Last Mounted Version 'H+LX' Version of our tools
000aa00: 482b 0102 0000 0000 482b 4c58 0000 0000 H+......H+LX....
# Several Dates in MacOS format
000aa10: b5ad f194 b5ad 7322 0000 0000 b5ad 7304 ......s"......s.
# 0x20: File count 3, 0x24 Folder count 3
# 0x28: Blocksize: 0x200 (usually 0x1000)
# 0x2C: total blocks 0xffaa (0xffaa * 0x200= 1FF5400 = AC00 Overhead)
000aa20: 0000 0003 0000 0003 0000 0200 0000 ffaa ................
# 0x30: free blocks: fb04
# 0x34: search for next allocation block at: 0x06a3
# 0x38: rsrc clump (preallocation-) size 0x2000
# 0x3C: data clump (preallocation-) size 0x2000
000aa30: 0000 fb04 0000 06a3 0000 2000 0000 2000 .......... ... .
# 0x40: next (unique) cnid 0x16
# 0x44: number of mounts so far: 0x16
# 0x48: encodings Bitmap: MacJapanese (0x02 , Bit 1)
000aa40: 0000 0016 0000 0016 0000 00000000 0002 ................
# Finder Info (Seems that the volume was never opened by Finder ...)
000aa50: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000aa60: 0000 0000 0000 0000 0000 0000 0000 0000 ................
# Fork info for allocation file
# 0x70: Total size (64 Bits) 0x2000 bytes
# 0x78: clumpsize 0x2000
# 0x7c: totalblocks 0x10 (* 0x200 = 0x2000 fits exactly)
000aa70: 0000 0000 0000 2000 0000 2000 0000 0010 ...... ... .....
# 0x80 - 0xc0 8 extends, first (and only) from 0x03 , 0x10 blocks
# this is sufficient for 0x010000 bits
# location starts at 0xa600 + 0x03*0x200 = 0xac00
# location ends at 0xa600 + (0x03 + 0x10) *0x200 = 0xcc00
000aa80: 0000 0003 0000 0010 0000 0000 0000 0000 ................
000aa90: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000aaa0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000aab0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
# Fork information for extends file (wonder why this is needed ?)
# 0xC0: Total size (64 bits) 0x40000 bytes
# 0xC8: ClumpSize 0x4000 bytes
# 0xCC: totalblocks 0x200 (* 0x200 = 0x40000 fits exactly)
000aac0: 0000 0000 0004 0000 0004 0000 0000 0200 ................
# 0xaD0 - 0xb10 8 extends, first (and only) from 0x13, 0x200 blocks
# location starts at 0xa600 + 0x13 *0x200=0x0CC00
# location ends at 0xa600 + (0x13+0x200)*0x200=0x4CC00
000aad0: 0000 0013 0000 0200 0000 0000 0000 0000 ................
000aae0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000aaf0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000ab00: 0000 0000 0000 0000 0000 0000 0000 0000 ................
# Fork information for catalog file
# 0x10: Total size (64 bits) 0x40000 bytes
# 0x18: ClumpSize 0x4000 bytes
# 0x1C: totalblocks 0x200 (* 0x200 = 0x40000 fits exactly)
000ab10: 0000 0000 0004 0000 0004 0000 0000 0200 ................
# 0x20 - 0x40 8 extends, first (and only) from 0x213, 0x200 blocks
# location starts at 0xa600 + 0x213 *0x200=0x4CC00
# location ends at 0xa600 + (0x213+0x200)*0x200=0x8CC00
000ab20: 0000 0213 0000 0200 0000 0000 0000 0000 ................
000ab30: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000ab40: 0000 0000 0000 0000 0000 0000 0000 0000 ................
No attr-fork, No boot-fork
000ab50: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
# Allocation Bitmap starts here
# This marks blocks 0x0000 - 0x007F as allocated
000ac00: ffff ffff ffff ffff ffff ffff ffff ffff ................
# This marks blocks 0x0080 - 0x00ff as allocated
000ac10: ffff ffff ffff ffff ffff ffff ffff ffff ................
# This marks blocks 0x0100 - 0x017f as allocated
000ac20: ffff ffff ffff ffff ffff ffff ffff ffff ................
000ac30: ffff ffff ffff ffff ffff ffff ffff ffff ................
000ac40: ffff ffff ffff ffff ffff ffff ffff ffff ................
000ac50: ffff ffff ffff ffff ffff ffff ffff ffff ................
000ac60: ffff ffff ffff ffff ffff ffff ffff ffff ................
000ac70: ffff ffff ffff ffff ffff ffff ffff ffff ................
# This marks blocks 0x0600 - 0x067f as allocated
000ac80: ffff e000 0000 0000 0000 0000 0000 0000 ................
# This marks blocks 0x0680 - 0x06A3 as allocated
# First free block should be at 0x06a4 *0x200 + 0xa600 = 0xdee00
000ac90: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000aca0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000acb0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000acc0: 0000 1fff ffff ffff ffff ffff ffff ffff ................
# This marks blocks 0x0884 - 0x08FF as allocated
000acd0: ffff ffff f000 0000 0000 0000 0000 0000 ................
# This marks blocks 0x0927 - 0x097F as allocated
000ace0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
000cbf0: 0000 0000 00c0 0000 0000 0000 0000 0000 ................
# Marks 0xFFA8 - i0xFFA9 as allocated FFA8*0x200 + 0xa600 = 1FFF600
# end of allocation file - begin of extends file
000cc00: 0000 0000 0000 0000 0100 0003 0000 0000 ................
000cc10: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000cc20: 0400 000a 0000 0100 0000 00ff 0000 0004 ................
000cc30: 0000 0000 0000 0002 0000 0000 0000 0000 ................
000cc40: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
000ccf0: 0000 0000 0000 0000 8000 0000 0000 0000 ................
000cd00: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
000cff0: 0000 0000 0000 0000 03f8 00f8 0078 000e .............x..
000d000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
# end of extends file - begin of catalog file
# Btree Node Descriptor:
# 0x00 : next 0x00 -> (no additional map node)
# 0x04 : prev 0x00 -> single, top node, well
# 0x08 : kind 0x01 = HFSP_NODE_HEAD
# 0x09 : height 0x00
# 0x0A : num_rec 0x003
# 0x0C : reserved 0
# Btree header (expected in type HFSP_NODE_HEAD)
# 0x0E : depth 0x01
004cc00: 0000 0000 0000 0000 0100 0003 0000 0001 ................
# 0x00 : root 0x00000001
# 0x04 : leaf_count 0x0000004e = 64 records ?
# 0x08 : leaf_head 0x00000001
# 0x0C : leaf_tail 0x00000001
004cc10: 0000 0001 0000 000e 0000 0001 0000 0001 ................
# 0x20 : node_size 0x1000 -> end of node at 0x4dc00 ?
# 0x22 : max_key_len 0x204 = 516 ( pretty large, hmmm)
# 0x24 : node_count 0x40 -> lenght of btree 0x40 * 0x1000 = 0x400000
# 0x28 : free_nodes 0x3e
# 0x2c : reserved
# 0x2e : clump_size 0x40000 (misaligned)
004cc20: 1000 0204 0000 0040 0000 003e 0000 0004 .......@...>....
# 0x32 : btree_type: 0
# 0x33 : reserved: 0
# 0x34 : attributes: 0x06 : HFSPLUS_TREE_BIGKEYS, HFSPLUS_TREE_VAR_NDXKEY_SIZE
# 0x38 - 0x88 : reserved
004cc30: 0000 0000 0000 0006 0000 0000 0000 0000 ................
*
# 0x88 Start of reserverd record
004cc80: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
# 0xF8 End of reserved record , start of B-Tree Map record
# Size = 0x400000 / 0x1000 / 0x08 bits = 0x80 bytes
004ccf0: 0000 0000 0000 0000 c000 0000 0000 0000 ................
004cd00: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
# Backpointers in reverse Order
# 0xFE : 0x000E pointer to start at 0xCC0E
# 0xFC : 0x0078 pointer to reserved record at 0xCC78
# 0xFA : 0x00f8 pointer to Map Record at 0xCCF8
# 0xF8 : 0x0ff8 pointer to Freee Space 0xDBF8 -> no more space, ok
004dbf0: 0000 0000 0000 0000 0ff8 00f8 0078 000e .............x..
# 0x00 : Begin of node 1, Node descriptor
# 0x00 : next 0x00
# 0x04 : prev 0x00 -> no further Map Node
# 0x08 : kind 0xff = HFSP_NODE_LEAF
# 0x09 : height 0x01 -> Leaf one below root, well
# 0x0A : num_rec 0x00e -> 14 entries
# 0x0C : reserved 0
# 0x0e : length of key 0x0010
004dc00: 0000 0000 0000 0000 ff01 000e 0000 0010 ................
# 0x10 : Parent cnid 0x00000001 HFSP_POR_CNID : Parent of root
# 0x12 : lenght of (Unicode) string
# 0x14 - 0x20 : String 'disk1'
004dc10: 0000 0001 0005 0064 0069 0073 006b 0031 .......d.i.s.k.1
# 0x00 : RecordType : HFSP_FOLDER
# 0x02 : flags 0x00
# 0x04 : valence 0x00000005
# 0x08 : id 0x00000002 : HFSP_ROOT_CNID
# 0x0c : create date 0xB5AD7304
004dc20: 0001 0000 0000 0005 0000 0002 b5ad 7304 ..............s.
# 0x00 : content_mod_date : 0xB5AD7314
# 0x04 : attribute_mod_date : 0
# 0x08 : acces_date : 0
# 0x0c : backup_date : 0
004dc30: b5ad 7314 0000 0000 0000 0000 0000 0000 ..s.............
# 0x00 : permission 0,0,0,0
004dc40: 0000 0000 0000 0000 0000 0000 0000 0000 ................
# 0x00 : DInfo, No rect,
# 0x08 : frFlags: 0x03e0 = ???
# 0x0A : frLocation: 190, 960 (usual place at upper right corner)
# 0x0C : frView: 0010e
004dc50: 0000 0000 0000 0000 03e0 00be 03c0 010e ................
# 0x00 : DXInfo , frScroll 0,0
# 0x04 : frOpenChain : 0xE1000000
# 0x08 : frUnused : 0x0000
# 0x0A : frComment : 0x0000
# 0x0C : frPutAway : 0x00000000
004dc60: 0000 0000 e100 0000 0000 0000 0000 0000 ................
# 0x00 : Text encoding : 0x00000001 (Mac Roman ?)
# 0x04 : reserved : 0x00000000 ???
# 0x08 : Start of record 1 : key_len = 6
# 0x0A : parent Id: 0x00000002 HFSP_ROOT_CNID
# 0x0E : strlen = 0 Mhh
004dc70: 0000 0001 0000 0000 0006 0000 0002 0000 ................
# 0x00 : 0x0003 Folder thread
# 0x02 : 0x0000 reserved
# 0x04 : parentID 0x00000001 HFSP_POR_CNID
# 0x08 : length of String : 5 'disk1'
004dc80: 0003 0000 0000 0001 0005 0064 0069 0073 ...........d.i.s
# 0x94 : Begin of record 2 : Length of key 1a
# 0x98 : paren cnid : 0x00000002 HFSP_ROOT_CNID , well
# 0x9C : Lenght of String : 10 'Desktop DB'
004dc90: 006b 0031 001a 0000 0002 000a 0044 0065 .k.1.........D.e
004dca0: 0073 006b 0074 006f 0070 0020 0044 0042 .s.k.t.o.p. .D.B
# 0xb0 : type of record 0x0002 : HFSP File
# 0xb2 : flags: 0x0002 HFSP_THREAD_EXISTS
# 0xb4 : reserved: 0x00000000
# 0xb8 : id i: 0x00000012 (Reserved by Apple, ok for Desktop DB)
# 0xba : create date
004dcb0: 0002 0002 0000 0000 0000 0012 b5ad 7314 ..............s.
# 0xc0 : content_mod_date
# 0xc4 : attribute_mod_date : 0
# 0xc8 : acces_date : 0
# 0xcc : backup_date : 0
004dcc0: b5ad 7314 0000 0000 0000 0000 0000 0000 ..s.............
# 0x00 : permission 0,0,0,0
004dcd0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
# Finfo:
# 0x00 : fdType 'BTFL' fdCreator 'DMGR'
# 0x08 : fdFlags : 0x4000 (probably invisible ...)
# 0x0A : no point (is invisible anyway ..)
# 0x0e : fdFldr 0x0000 (not in any window)
004dce0: 4254 464c 444d 4752 4000 0000 0000 0000 BTFLDMGR@.......
# FXInfo: all 0 (never displayed ...)
004dcf0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
# 0x00 : Text encoding 0x00000001 : ??? (Mac Roman ?)
# 0x04 : reserved2
# 0x08 : datafork, total size 0x0000000000002000
004dd00: 0000 0001 0000 0000 0000 0000 0000 2000 .............. .
# 0x00 : clumpsize 0 (not used ?)
# 0x04 : total blocks 0x00010 (0x10 * 0x200 = 0x2000 fits exactly)
# 0x08 : first block 0x613, length 0x10
-> Starts at 0xa600 + 0x613*0x200 = 0xCCC00
-> Ends at 0xa600 + 0x623*0x200 = 0xCEC00
004dd10: 0000 0000 0000 0010 0000 0613 0000 0010 ................
004dd20: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004dd30: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004dd40: 0000 0000 0000 0000 0000 0000 0000 0000 ................
# 0x58 : rsrcfork (none)
004dd50: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004dd60: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004dd70: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004dd80: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004dd90: 0000 0000 0000 0000 0000 0000 0000 0000 ................
# 0xa8 : end of rsrcfork
# 0xa8 : File: 'Desktop DF'
004dda0: 0000 0000 0000 0000 001a 0000 0002 000a ................
004ddb0: 0044 0065 0073 006b 0074 006f 0070 0020 .D.e.s.k.t.o.p.
004ddc0: 0044 0046 0002 0002 0000 0000 0000 0011 .D.F............
004ddd0: b5ad 7314 b5ad 7314 0000 0000 0000 0000 ..s...s.........
004dde0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004ddf0: 0000 0000 4454 464c 444d 4752 4000 0000 ....DTFLDMGR@...
004de00: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004de10: 0000 0000 0000 0001 0000 0000 0000 0000 ................
# 0x00 : datafork, total size 0x0000000200000000 ???
# 0x0C : first block 0x623, length 0x80
-> Starts at 0xa600 + 0x623*0x200 = 0xCEC00
-> Ends at 0xa600 + 0x6A3*0x200 = 0xDEC00
004de20: 0000 0002 0000 0000 0000 0080 0000 0623 ...............#
004de30: 0000 0080 0000 0000 0000 0000 0000 0000 ................
004de40: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
004deb0: 0000 0000 0000 0000 0000 0000 0022 0000 ............."..
004dec0: 0002 000e 0044 0065 0073 006b 0074 006f .....D.e.s.k.t.o
004ded0: 0070 0020 0046 006f 006c 0064 0065 0072 .p. .F.o.l.d.e.r
004dee0: 0001 0000 0000 0000 0000 0014 b5ad 7314 ..............s.
004def0: b5ad 7314 0000 0000 0000 0000 0000 0000 ..s.............
004df00: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
004df30: 0000 0001 0000 0000 0034 0000 0002 0017 .........4......
004df40: 0054 0068 0065 0056 006f 006c 0075 006d .T.h.e.V.o.l.u.m
004df50: 0065 0053 0065 0074 0074 0069 006e 0067 .e.S.e.t.t.i.n.g
004df60: 0073 0046 006f 006c 0064 0065 0072 0001 .s.F.o.l.d.e.r..
004df70: 0000 0000 0001 0000 0010 b5ad 7314 b5ad ............s...
004df80: 7314 0000 0000 0000 0000 0000 0000 0000 s...............
004df90: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004dfa0: 0000 0000 0000 5000 0000 0000 0000 0000 ......P.........
004dfb0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004dfc0: 0001 0000 0000 0010 0000 0002 0005 0054 ...............T
004dfd0: 0072 0061 0073 0068 0001 0000 0000 0000 .r.a.s.h........
004dfe0: 0000 0015 b5ad 7314 b5ad 7314 0000 0000 ......s...s.....
004dff0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004e000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004e010: 4000 0000 0000 0000 0000 0000 0000 0000 @...............
004e020: 0000 0000 0000 0000 0000 0001 0000 0000 ................
004e030: 0006 0000 0010 0000 0003 0000 0000 0002 ................
004e040: 0017 0054 0068 0065 0056 006f 006c 0075 ...T.h.e.V.o.l.u
004e050: 006d 0065 0053 0065 0074 0074 0069 006e .m.e.S.e.t.t.i.n
004e060: 0067 0073 0046 006f 006c 0064 0065 0072 .g.s.F.o.l.d.e.r
004e070: 002a 0000 0010 0012 0044 0065 0073 006b .*.......D.e.s.k
004e080: 0074 006f 0070 0050 0072 0069 006e 0074 .t.o.p.P.r.i.n.t
004e090: 0065 0072 0073 0020 0044 0042 0002 0002 .e.r.s. .D.B....
004e0a0: 0000 0000 0000 0013 b5ad 7314 b5ad 7314 ..........s...s.
004e0b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
004e0c0: 0000 0000 0000 0000 0000 0000 6474 706c ............dtpl
004e0d0: 6463 6463 4000 0000 0000 0000 0000 0000 dcdc@...........
004e0e0: 0000 0000 8000 0000 0000 0000 0000 0001 ................
004e0f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
004e140: 0000 0000 0000 0000 0000 011e 0000 0000 ................
004e150: 0000 0001 0000 06a3 0000 0001 0000 0000 ................
004e160: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
004e190: 0000 0000 0006 0000 0011 0000 0004 0000 ................
004e1a0: 0000 0002 000a 0044 0065 0073 006b 0074 .......D.e.s.k.t
004e1b0: 006f 0070 0020 0044 0046 0006 0000 0012 .o.p. .D.F......
004e1c0: 0000 0004 0000 0000 0002 000a 0044 0065 .............D.e
004e1d0: 0073 006b 0074 006f 0070 0020 0044 0042 .s.k.t.o.p. .D.B
004e1e0: 0006 0000 0013 0000 0004 0000 0000 0010 ................
004e1f0: 0012 0044 0065 0073 006b 0074 006f 0070 ...D.e.s.k.t.o.p
004e200: 0050 0072 0069 006e 0074 0065 0072 0073 .P.r.i.n.t.e.r.s
004e210: 0020 0044 0042 0006 0000 0014 0000 0003 . .D.B..........
004e220: 0000 0000 0002 000e 0044 0065 0073 006b .........D.e.s.k
004e230: 0074 006f 0070 0020 0046 006f 006c 0064 .t.o.p. .F.o.l.d
004e240: 0065 0072 0006 0000 0015 0000 0003 0000 .e.r............
004e250: 0000 0002 0005 0054 0072 0061 0073 0068 .......T.r.a.s.h
004e260: 0073 0068 0044 0065 0073 006b 0074 006f .s.h.D.e.s.k.t.o
004e270: 0070 0050 0072 0069 006e 0074 0065 0072 .p.P.r.i.n.t.e.r
004e280: 0073 0020 0044 0042 0006 0000 0014 0000 .s. .D.B........
004e290: 0003 0000 0000 0002 000e 0044 0065 0073 ...........D.e.s
004e2a0: 006b 0074 006f 0070 0020 0046 006f 006c .k.t.o.p. .F.o.l
004e2b0: 0064 0065 0072 0006 0000 0015 0000 0003 .d.e.r..........
004e2c0: 0000 0000 0002 0005 0054 0072 0061 0073 .........T.r.a.s
004e2d0: 0068 0000 0000 0000 0000 0000 0000 0000 .h..............
004e2e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
# Backpointers in reverse order
004ebe0: 06d2 0660 0644 0616 05e0 05ba 0594 0470 ...`.D.........p
# Backpointers in reverse order
# 0xFE : 0x000E Pointer to '?????' at 0x4DC0E
# 0xFC : 0x0078 Pointer to '?????' at 0x4DC0E
# 0xFA : 0x000E Pointer to '?????' at 0x4DC0E
# 0xF8 : 0x000E Pointer to '?????' at 0x4DC0E
# 0xF6 : 0x000E Pointer to '?????' at 0x4DC0E
# 0xF4 : 0x0094 Pointer to '?????' at 0x4DC94
# 0xF2 : 0x0078 Pointer to '???' at 0x4DC78
# 0xF0 : 0x000E Pointer to 'disk1' at 0x4DC0E
004ebf0: 0430 03c6 0338 02bc 01a8 0094 0078 000e .0...8.......x..
# 0x03 : Begin of node 2 (does not exists)
004ec00: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
# End of catalog file
008cc00: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
# Begin of Desktop DB
00ccc00: 0000 0000 0000 0000 0100 0003 0000 0001 ................
00ccc10: 0000 0001 0000 0001 0000 0001 0000 0001 ................
00ccc20: 0200 0025 0000 0010 0000 000e 0000 0000 ...%............
00ccc30: 2000 ff00 0000 0000 0000 0000 0000 0000 ...............
00ccc40: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
00ccc70: 0000 0000 0000 0000 020a 0100 0000 0000 ................
00ccc80: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
00cccf0: 0000 0000 0000 0000 c000 0000 0000 0000 ................
00ccd00: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
00ccdf0: 0000 0000 0000 0000 01f8 00f8 0078 000e .............x..
00cce00: 0000 0000 0000 0000 ff01 0001 0000 0b01 ................
00cce10: 6174 636f 6174 636f fe00 0000 0000 0000 atcoatco........
00cce20: 0000 0002 0000 0000 0000 0000 0000 0000 ................
00cce30: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
00ccff0: 0000 0000 0000 0000 0000 0000 0024 000e .............$..
00cd000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
# End of Desktop DB - Begin of Desktop FD
00cec00: 0002 0100 0066 272e 0066 262e 0000 00dc .....f'..f&.....
00cec10: 0000 1df3 0c44 6963 7469 6f6e 6172 792e .....Dictionary.
00cec20: 6800 0200 0200 5445 5854 4357 4945 0100 h.....TEXTCWIE..
00cec30: 0e95 bd90 ac8a 7083 5383 5683 6283 4e83 ......p.S.V.b.N.
00cec40: 0200 0000 4646 494c 6d6f 7672 0100 01a2 ....FFILmovr....
00cec50: 0000 4646 494c 6d6f 7672 0100 01a2 0042 ..FFILmovr.....B
00cec60: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00cec70: 0000 b3ec 2e40 0000 0000 0066 280a 0000 .....@.....f(...
00cec80: 0000 0000 0000 0000 1800 0000 1df3 1244 ...............D
00cec90: 6963 7469 6f6e 6172 7944 6961 6c6f 672e ictionaryDialog.
00ceca0: 6300 0200 0200 5445 5854 4357 4945 0100 c.....TEXTCWIE..
00cecb0: ffff ffff 0000 0002 80bd 0000 0000 805c ...............\
00cecc0: 0000 9c00 0000 0000 01ac 0000 3400 b13e ............4..>
00cecd0: 2b63 b144 ab18 0000 0000 0000 0000 0000 +c.D............
00cece0: 0000 0000 0000 0000 0000 0000 2545 0003 ............%E..
00cecf0: 0000 0000 0000 0000 1f49 0001 0000 0000 .........I......
00ced00: 0000 001a d000 0000 00ff 000a 0000 ffff ................
00ced10: 000a 000a 0000 0009 0001 0003 0000 0000 ................
00ced20: 001a d000 0000 00ff 000c 0000 fffe 000c ................
00ced30: 000c 0000 000a 0002 0003 0000 0000 001a ................
00ced40: d000 0000 00ff 000e 0000 fffe 000e 000e ................
00ced50: 0000 000c 0002 0004 0000 0000 001a d000 ................
00ced60: 0000 00ff 0012 0000 fffd 0012 0012 0000 ................
00ced70: 000f 0003 0005 0000 0000 001a d000 0000 ................
00ced80: 00ff 0019 0000 fffd 0018 0018 0000 0015 ................
00ced90: 0003 0006 0000 0000 001a d000 0000 00ff ................
00ceda0: 0009 0000 ffff 0009 0009 0000 0008 0001 ................
00cedb0: 0002 0000 0000 02ec 1000 413d 0000 00ff ..........A=....
00cedc0: 0db7 fdb7 0400 1000 0000 0060 0000 0000 ...........`....
00cedd0: 0000 029c 0000 0155 0000 0000 0100 0155 .......U.......U
00cede0: feab 0155 0000 0000 0268 0004 0006 0000 ...U.....h......
00cedf0: 0000 413d 0009 0000 7ff6 000a 0000 7ff5 ..A=............
00cee00: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
# End of Desktop DF - Start of ...
00dec00: 0000 0100 0000 0100 0000 0000 0000 001e ................
00dec10: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
00ded00: 0000 0100 0000 0100 0000 0000 0000 001e ................
00ded10: 0000 0000 0000 0000 001c 001e ffff 0000 ................
00ded20: 001a d000 0000 00ff 000a 0000 ffff 000a ................
00ded30: 000a 0000 0009 0001 0003 0000 0000 001a ................
00ded40: d000 0000 00ff 000c 0000 fffe 000c 000c ................
00ded50: 0000 000a 0002 0003 0000 0000 001a d000 ................
00ded60: 0000 00ff 000e 0000 fffe 000e 000e 0000 ................
00ded70: 000c 0002 0004 0000 0000 001a d000 0000 ................
00ded80: 00ff 0012 0000 fffd 0012 0012 0000 000f ................
00ded90: 0003 0005 0000 0000 001a d000 0000 00ff ................
00deda0: 0018 0000 fffd 0018 0018 0000 0015 0003 ................
00dedb0: 0006 0000 0000 02e8 1000 413c 0000 00ff ..........A<....
00dedc0: 0db7 fdb7 0400 1000 0000 0060 0000 0000 ...........`....
00dedd0: 0000 029c 0000 0155 0000 0000 0100 0155 .......U.......U
00dede0: feab 0155 0000 0000 0268 0004 0006 0000 ...U.....h......
00dedf0: 0000 413c 0009 0000 7ff0 000a 0000 7fef ..A<............
# First free block as defined by allocation bitmap
00dee00: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
# Backup Master directory block for HFS+
# Second to last block in volume = 0x1FFF800 - 2*0x200 = 1FFF600<
1fff600: 482b 0004 0000 0100 382e 3130 0000 0000 H+......8.10....
1fff610: b5ad f194 b5ad 7304 0000 0000 b5ad 7304 ......s.......s.
1fff620: 0000 0000 0000 0000 0000 0200 0000 ffaa ................
1fff630: 0000 fb95 0000 0613 0000 2000 0000 2000 .......... ... .
1fff640: 0000 0010 0000 0000 0000 0000 0000 0002 ................
1fff650: 0000 0000 0000 0000 0000 0000 0000 0000 ................
1fff660: 0000 0000 0000 0000 0000 0000 0000 0000 ................
1fff670: 0000 0000 0000 2000 0000 2000 0000 0010 ...... ... .....
1fff680: 0000 0003 0000 0010 0000 0000 0000 0000 ................
1fff690: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
1fff6c0: 0000 0000 0004 0000 0004 0000 0000 0200 ................
1fff6d0: 0000 0013 0000 0200 0000 0000 0000 0000 ................
1fff6e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
1fff710: 0000 0000 0004 0000 0004 0000 0000 0200 ................
1fff720: 0000 0213 0000 0200 0000 0000 0000 0000 ................
1fff730: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
# Backup Master directory block for HFS-Wrapper
1fffc00: 4244 b5ad f194 b5ad f194 8300 0006 0003 BD..............
1fffc10: 000d 7ff9 0000 0400 0000 0400 000b 0000 ................
1fffc20: 0016 0000 0768 6673 706c 7573 0000 0000 .....hfsplus....
1fffc30: 0000 0000 0000 0000 0000 0000 0000 0000 ................
1fffc40: 0000 0000 0000 0000 000d 0000 1000 0000 ................
1fffc50: 1000 0000 0000 0006 0000 0000 0000 0002 ................
1fffc60: 0000 0000 0000 0000 0000 0000 0000 0000 ................
1fffc70: 0000 0000 0000 0000 0000 0000 482b 0024 ............H+.$
1fffc80: 7fd5 0000 1000 0000 0004 0000 0000 0000 ................
1fffc90: 0000 0000 1000 0004 0004 0000 0000 0000 ................
1fffca0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
*
1fffff0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
hfsplus-1.0.4/libhfsp/test/dump2.txt 0100644 0000000 0000000 00000075261 07441220605 016110 0 ustar root root
# This is a commented dump of an HFS+ volume
# Original By Brad Boyer
#
# $Id: dump2.txt,v 1.1.1.1 2002/03/05 19:50:29 klaus Exp $
000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
Signature: 42 44
Create Time: b47f394a
Mod Time: b5c1dc16
Attributes: 8300 (LOCKED | SPARED | CLEAN)
Num Files: 0005
Vol Bmp: 0003
000400: 42 44 b4 7f 39 4a b5 c1 dc 16 83 00 00 05 00 03 BD..9J..........
AllocPtr: 0009
AllocBlk Cnt: fee7 (65255)
AllocBlk Size: 00000600 (1.5k)
Clump Size: 00000600 (1.5k)
AllocBlk Start: 0013
Next CNID: 00000015
000410: 00 09 fe e7 00 00 06 00 00 00 06 00 00 13 00 00 ................
Free Blocks: 0000
Volume Label: ZIP-100
000420: 00 15 00 00 07 5a 49 50 2d 31 30 30 00 00 00 00 .....ZIP-100....
000430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Write Count: 0000000d
Extents ClmpSize: 00001200 (4.5k)
Catalog ClmpSize: 00001200 (4.5k)
000440: 00 00 00 00 00 00 00 00 00 0d 00 00 12 00 00 00 ................
NumDir in root: 0000
File Count: 00000005
Dir Count: 00000000
000450: 12 00 00 00 00 00 00 05 00 00 00 00 00 00 00 02 ................
000460: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Embedded Sig: 482b
Embedded Extent: 0018 fecf
000470: 00 00 00 00 00 00 00 00 00 00 00 00 48 2b 00 18 ............H+..
000480: fe cf 00 00 12 00 00 00 00 03 00 00 00 00 00 00 ................
000490: 00 00 00 00 12 00 00 03 00 03 00 00 00 00 00 00 ................
0004a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
[Snipped data from HFS wrapper, including System and "Where have..."]
Start of HFS+ Volume Header (Start of HFS+ filesystem = b600)
Signature: 482b
Version: 0004
Attributes: 00000100 (Unmounted)
Last Mounted: 8.10 (MacOS 8)
Reserved: 00000000
00ba00: 48 2b 00 04 00 00 01 00 38 2e 31 30 00 00 00 00 H+......8.10....
Create Date: b47f394a
Modify Date: b5c24c1a
Backup Date: 00000000
Checked Date: b47fa9cc
00ba10: b4 7f 39 4a b5 c2 4c 1a 00 00 00 00 b4 7f a9 cc ..9J..L.........
File Count: 00000004
Folder Count: 00000000
Block Size: 00000200 (512)
Total Blocks: 0002fc6d
00ba20: 00 00 00 04 00 00 00 00 00 00 02 00 00 02 fc 6d ...............m
Free Blocks: 0002efb4
Next Alloc: 000012ae
rsrc ClumpSz: 00002000
data ClumpSz: 00002000
00ba30: 00 02 ef b4 00 00 12 ae 00 00 20 00 00 00 20 00 .......... ... .
Next CNID: 00000014
Write Count: 00000020
Encodings Bitmap: 0000000000000001 (MacRoman)
00ba40: 00 00 00 14 00 00 00 20 00 00 00 00 00 00 00 01 ....... ........
Finderinfo
00ba50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
Allocation File
Logical Size: 0000000000006000 (24k)
Clump Size: 00006000
Total Blocks: 00000030
00ba70: 00 00 00 00 00 00 60 00 00 00 60 00 00 00 00 30 ......`...`....0
Extent 1
Start Block: 00000003
Block Count: 00000030
00ba80: 00 00 00 03 00 00 00 30 00 00 00 00 00 00 00 00 .......0........
00ba90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
Extents File
Logical Size: 00000000000bf000 (764k)
Clump Size: 000bf000
Total Blocks: 000005f8
00bac0: 00 00 00 00 00 0b f0 00 00 0b f0 00 00 00 05 f8 ................
Extent 1
Start Block: 00000033
Block Count: 000005f8
00bad0: 00 00 00 33 00 00 05 f8 00 00 00 00 00 00 00 00 ...3............
00bae0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
Catalog File:
Logical Size: 00000000000bf000 (764k)
Clump Size: 000bf000
Total Blocks: 000005f8
00bb10: 00 00 00 00 00 0b f0 00 00 0b f0 00 00 00 05 f8 ................
Extent 1
Start Block: 0000062b
Block Count: 000005f8
00bb20: 00 00 06 2b 00 00 05 f8 00 00 00 00 00 00 00 00 ...+............
00bb30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
Start of Allocation File
00bc00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
*
00bd80: ff ff ff ff e0 00 00 00 00 00 00 00 00 00 00 00 ................
00bd90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
00be40: 00 00 00 1f ff ff ff ff ff ff ff ff ff ff ff ff ................
00be50: ff ff ff ff ff fe 00 00 00 00 00 00 00 00 00 00 ................
00be60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
011b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 18 00 00 ................
011b90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
End of Allocation File
Start of Extents File
fLink: 00000000
bLink: 00000000
Kind: 01 (Header)
Height: 00
Num Recs: 0003
Reserved: 0000
Tree Depth: 0000
011c00: 00 00 00 00 00 00 00 00 01 00 00 03 00 00 00 00 ................
Root Node: 00000000
Leaf Recs: 00000000
First Leaf: 00000000
Last Leaf: 00000000
011c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Node Size: 0400
Max Keylen: 000a
Total Nodes: 000002fc
Free Nodes: 000002fb
Reserved: 0000
Clump Size: 000bf000
011c20: 04 00 00 0a 00 00 02 fc 00 00 02 fb 00 00 00 0b ................
Tree Type: 00 (unused in HFS+)
Reserved: 00
Attributes:00000002 (BigKeys)
011c30: f0 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 ................
011c40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
Map record (starts at 11cf8, node 0 in use)
011cf0: 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 ................
011d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
Record Offsets:
Rec 1: 000e (header record)
Rec 2: 0078 (reserved record)
Rec 3: 00f8 (map record)
Rec 4: 03f8 (free space)
011ff0: 00 00 00 00 00 00 00 00 03 f8 00 f8 00 78 00 0e .............x..
012000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
Start of Catalog File
fLink: 00000000
bLink: 00000000
Kind: 01 (Header)
Height: 00
Num Recs: 0003
Reserved: 0000
Tree Depth: 0001
0d0c00: 00 00 00 00 00 00 00 00 01 00 00 03 00 00 00 01 ................
Root Node: 00000001
Leaf Recs: 0000000a
First Leaf: 00000001
Last Leaf: 00000001
0d0c10: 00 00 00 01 00 00 00 0a 00 00 00 01 00 00 00 01 ................
Node Size: 1000
Max Keylen: 0204
Total Nodes: 000000bf
Free Nodes: 000000bd
Reserved: 0000
Clump Size: 000bf000
0d0c20: 10 00 02 04 00 00 00 bf 00 00 00 bd 00 00 00 0b ................
Tree Type: 00 (unused in HFS+)
Reserved: 00
Attributes:00000006 (BigKeys | VariableIndexKeys)
0d0c30: f0 00 00 00 00 00 00 06 00 00 00 00 00 00 00 00 ................
0d0c40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
Map record (starts at d0cf8, nodes 0 and 1 in use)
0d0cf0: 00 00 00 00 00 00 00 00 c0 00 00 00 00 00 00 00 ................
0d0d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
Record Offsets:
Rec 1: 000e (header record)
Rec 2: 0078 (reserved record)
Rec 3: 00f8 (map record)
Rec 4: 0ff8 (free space)
0d1bf0: 00 00 00 00 00 00 00 00 0f f8 00 f8 00 78 00 0e .............x..
Node 1 (Root and only leaf node)
fLink: 00000000
bLink: 00000000
Kind: ff (Leaf)
Height: 01
Num Recs: 000a
Reserved: 0000
Keylen: 0014 (Start of Record 1: 0d1c0e)
0d1c00: 00 00 00 00 00 00 00 00 ff 01 00 0a 00 00 00 14 ................
ParentId: 00000001 (Parent of Root)
NodeNameLen: 0007
NodeNameText: 005a00490050002d003100300030 (ZIP-100)
0d1c10: 00 00 00 01 00 07 00 5a 00 49 00 50 00 2d 00 31 .......Z.I.P.-.1
RecordType: 0001 (Folder)
Flags: 0000
Valence: 00000004
CNID: 00000002 (Root)
0d1c20: 00 30 00 30 00 01 00 00 00 00 00 04 00 00 00 02 .0.0............
CreateDate: b47fa9cd
ContentModDate: b47fa9e1
AttribModDate: 00000000
AccessDate: 00000000
0d1c30: b4 7f a9 cd b4 7f a9 e1 00 00 00 00 00 00 00 00 ................
BackupDate: 00000000
Owner: 00000000
Group: 00000000
Permissions: 00000000
0d1c40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Device: 00000000
Rect: 0000000000000000
Flags: 03e0
Location: 00dc03c0
0d1c50: 00 00 00 00 00 00 00 00 00 00 00 00 03 e0 00 dc ................
View: 0107
Scroll: 00000000
OpenChain: c3400000
Unused: 0000
Comment: 0000
0d1c60: 03 c0 01 07 00 00 00 00 c3 40 00 00 00 00 00 00 .........@......
PutAway: 00000000
Encoding: 00000000
Reserved: 00000000
Keylen: 0006 (Start of Record 2: 0d1c7c)
ParentId: 00000002 (Root)
0d1c70: 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 00 ................
NodeNameLen: 0000
RecordType: 0003 (Folder Thread)
Reserved: 0000
ParentId: 00000001 (Parent of Root)
NodeNameLen: 0007
NodeNameText: 005a00490050002d003100300030 (ZIP-100)
0d1c80: 00 02 00 00 00 03 00 00 00 00 00 01 00 07 00 5a ...............Z
Keylen: 001a (Start of Record 3: 0d1c9c)
ParentId: 00000002 (Root)
0d1c90: 00 49 00 50 00 2d 00 31 00 30 00 30 00 1a 00 00 .I.P.-.1.0.0....
NodeNameLen: 000a
NodeNameText: 004400650073006b0074006f0070002000440042 (Desktop DB)
0d1ca0: 00 02 00 0a 00 44 00 65 00 73 00 6b 00 74 00 6f .....D.e.s.k.t.o
RecordType: 0002 (File)
Flags: 0002
Reserved: 00000000
0d1cb0: 00 70 00 20 00 44 00 42 00 02 00 02 00 00 00 00 .p. .D.B........
CNID: 00000011
CreateDate: b47fa9cd
ContentModDate: b47fa9cd
AttribModDate: 00000000
0d1cc0: 00 00 00 11 b4 7f a9 cd b4 7f a9 cd 00 00 00 00 ................
AccessDate: 00000000
BackupDate: 00000000
Owner: 00000000
Group: 00000000
0d1cd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Permissions: 00000000
Device: 00000000
Type: 4254464c (BTFL)
Creator: 444d4752 (DMGR)
0d1ce0: 00 00 00 00 00 00 00 00 42 54 46 4c 44 4d 47 52 ........BTFLDMGR
Flags: 4000
Location: 00000000
Folder: 0000
Icon: 0000
Unused: 0000000000000000
0d1cf0: 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @...............
Comment: 0000
PutAway: 00000000
Encoding: 00000000
Reserved: 00000000
DataSize: 0000000000000000
0d1d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
ClumpSize: 24000000
Blocks: 00000000
0d1d10: 00 00 00 00 00 00 24 00 00 00 00 00 00 00 00 12 ......$.........
0d1d20: 00 00 12 1b 00 00 00 12 00 00 00 00 00 00 00 00 ................
0d1d30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
0d1db0: 00 1a 00 00 00 02 00 0a 00 44 00 65 00 73 00 6b .........D.e.s.k
0d1dc0: 00 74 00 6f 00 70 00 20 00 44 00 46 00 02 00 02 .t.o.p. .D.F....
0d1dd0: 00 00 00 00 00 00 00 10 b4 7f a9 cd b4 7f a9 cd ................
0d1de0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0d1df0: 00 00 00 00 00 00 00 00 00 00 00 00 44 54 46 4c ............DTFL
0d1e00: 44 4d 47 52 40 00 00 00 00 00 00 00 00 00 00 00 DMGR@...........
0d1e10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0d1e20: 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 ................
0d1e30: 00 00 00 80 00 00 12 2d 00 00 00 80 00 00 00 00 .......-........
0d1e40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
0d1ec0: 00 00 00 00 00 2a 00 00 00 02 00 12 00 44 00 65 .....*.......D.e
0d1ed0: 00 73 00 6b 00 74 00 6f 00 70 00 50 00 72 00 69 .s.k.t.o.p.P.r.i
0d1ee0: 00 6e 00 74 00 65 00 72 00 73 00 20 00 44 00 42 .n.t.e.r.s. .D.B
0d1ef0: 00 02 00 02 00 00 00 00 00 00 00 12 b4 7f a9 cd ................
0d1f00: b4 7f a9 cd 00 00 00 00 00 00 00 00 00 00 00 00 ................
0d1f10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0d1f20: 64 74 70 6c 64 63 64 63 40 00 00 00 00 00 00 00 dtpldcdc@.......
0d1f30: 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 ................
0d1f40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
0d1f90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 1e ................
0d1fa0: 00 00 00 00 00 00 00 01 00 00 12 ad 00 00 00 01 ................
0d1fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
0d1fe0: 00 00 00 00 00 00 00 00 00 28 00 00 00 02 00 11 .........(......
0d1ff0: 00 4f 00 70 00 65 00 6e 00 46 00 6f 00 6c 00 64 .O.p.e.n.F.o.l.d
0d2000: 00 65 00 72 00 4c 00 69 00 73 00 74 00 44 00 46 .e.r.L.i.s.t.D.F
0d2010: 00 0d 00 02 00 02 00 00 00 00 00 00 00 13 b4 7f ................
0d2020: a9 e1 b4 7f a9 e1 00 00 00 00 00 00 00 00 00 00 ................
0d2030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0d2040: 00 00 46 4f 4c 44 4d 41 43 53 40 00 00 00 00 00 ..FOLDMACS@.....
0d2050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
0d20c0: 01 1e 00 00 00 00 00 00 00 01 00 00 12 ae 00 00 ................
0d20d0: 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0d20e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
0d2100: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 10 ................
0d2110: 00 00 00 04 00 00 00 00 00 02 00 0a 00 44 00 65 .............D.e
0d2120: 00 73 00 6b 00 74 00 6f 00 70 00 20 00 44 00 46 .s.k.t.o.p. .D.F
0d2130: 00 06 00 00 00 11 00 00 00 04 00 00 00 00 00 02 ................
0d2140: 00 0a 00 44 00 65 00 73 00 6b 00 74 00 6f 00 70 ...D.e.s.k.t.o.p
0d2150: 00 20 00 44 00 42 00 06 00 00 00 12 00 00 00 04 . .D.B..........
0d2160: 00 00 00 00 00 02 00 12 00 44 00 65 00 73 00 6b .........D.e.s.k
0d2170: 00 74 00 6f 00 70 00 50 00 72 00 69 00 6e 00 74 .t.o.p.P.r.i.n.t
0d2180: 00 65 00 72 00 73 00 20 00 44 00 42 00 06 00 00 .e.r.s. .D.B....
0d2190: 00 13 00 00 00 04 00 00 00 00 00 02 00 11 00 4f ...............O
0d21a0: 00 70 00 65 00 6e 00 46 00 6f 00 6c 00 64 00 65 .p.e.n.F.o.l.d.e
0d21b0: 00 72 00 4c 00 69 00 73 00 74 00 44 00 46 00 0d .r.L.i.s.t.D.F..
0d21c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
Record Offsets:
Rec 9: 0556
Rec 10: 058c
Rec 11: 05c0 (Free space)
0d2be0: 00 00 00 00 00 00 00 00 00 00 05 c0 05 8c 05 56 ...............V
Record Offsets:
Rec 1: 000e
Rec 2: 007c
Rec 3: 009c
Rec 4: 01b0
Rec 5: 02c4
Rec 6: 03e8
Rec 7: 050a
Rec 8: 0530
0d2bf0: 05 30 05 0a 03 e8 02 c4 01 b0 00 9c 00 7c 00 0e .0...........|..
0d2c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
191c00: 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1e ................
191c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
191d00: 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1e ................
191d10: 00 00 00 00 00 00 00 00 00 1c 00 1e ff ff 00 00 ................
191d20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
192200: 00 00 01 00 00 00 08 0c 00 00 07 0c 00 00 00 5a ...............Z
192210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
192300: 00 00 01 00 07 ff ff e0 1e 08 00 b8 74 08 00 ae ............t...
192310: c4 0f ff a3 84 00 00 21 84 00 80 21 84 00 00 21 .......!...!...!
192320: 84 1e b8 21 84 04 a4 21 84 08 a4 21 84 1e b8 21 ...!...!...!...!
192330: 84 00 20 21 84 00 00 21 87 ff ff e1 84 2a aa a1 .. !...!.....*..
192340: 84 35 55 41 84 2a aa 99 87 ff ff 3d 84 00 00 3d .5UA.*.....=...=
192350: 84 00 00 19 84 4e 38 01 84 d1 45 ff 84 51 45 ff .....N8...E..QE.
192360: 84 51 45 c7 84 51 45 c7 84 4e 39 e7 84 00 01 e7 .QE..QE..N9.....
192370: 84 00 01 e7 87 ff ff e7 c4 00 01 e7 7c 00 01 ff ............|...
192380: 07 ff ff ff 07 ff ff e0 1f ff ff f8 7f ff ff fe ................
192390: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
*
1923f0: ff ff ff ff ff ff ff ff ff ff ff ff 7f ff ff ff ................
192400: 07 ff ff ff 00 00 02 00 00 00 0f ff ff ff ff ff ................
192410: ff ff ff ff ff f0 00 00 00 0f ff fd dd dd fc cc ................
192420: cc cc cc cc fd ff f0 00 0f ff cf dd dd dd fc cc ................
192430: cc cc cc cc fd fc ff f0 ff dd cf dd dd dd ff ff ................
192440: ff ff ff ff fd fc dd ff fd dd cf dd dd dd dd dd ................
192450: dd dd dd dd dd fc dd df fd dd cf dd dd dd dd dd ................
192460: fd dd dd dd dd fc dd df fd dd cf dd dd dd dd dd ................
192470: dd dd dd dd dd fc dd df fd dd cf dd dd df ff fd ................
192480: fd ff fd dd dd fc dd df fd dd cf dd dd dd df dd ................
192490: fd fd df dd dd fc dd df fd dd cf dd dd dd fd dd ................
1924a0: fd fd df dd dd fc dd df fd dd cf dd dd df ff fd ................
1924b0: fd ff fd dd dd fc dd df fd dd cf dd dd dd dd dd ................
1924c0: dd fd dd dd dd fc dd df fd dd cf dd dd dd dd dd ................
1924d0: dd dd dd dd dd fc dd df fd dd cf ff ff ff ff ff ................
1924e0: ff ff ff ff ff fc dd df fd dd cf 00 00 f3 33 33 ..............33
1924f0: 33 33 33 33 33 fc dd df fd dd cf 00 00 f3 33 33 33333.........33
*
192510: 33 33 33 33 33 05 5d df fd dd cf ff ff ff ff ff 33333.].........
192520: ff ff ff ff f0 55 55 df fd dd cf 00 00 00 00 00 .....UU.........
192530: 00 00 00 00 00 55 55 df fd dd cf 00 00 00 00 00 .....UU.........
192540: 00 00 00 00 00 05 5d df fd dd cf 00 0f 00 ff f0 ......].........
192550: 00 ff f0 00 00 0d dd df fd dd cf 00 ff 0f 00 0f ................
192560: 0f 00 0f 05 55 55 55 55 fd dd cf 00 0f 0f 00 0f ....UUUU........
192570: 0f 00 0f 05 33 33 33 35 fd dd cf 00 0f 0f 00 0f ....3335........
192580: 0f 00 0f 05 33 00 03 35 fd dd cf 00 0f 0f 00 0f ....3..5........
192590: 0f 00 0f 05 33 00 03 35 fd dd cf 00 0f 00 ff f0 ....3..5........
1925a0: 00 ff f0 05 33 30 03 35 fd dd cf 00 00 00 00 00 ....30.5........
1925b0: 00 00 00 05 33 30 03 35 fd dd cf 00 00 00 00 00 ....30.5........
1925c0: 00 00 00 05 33 30 03 35 fd dd cf ff ff ff ff ff ....30.5........
1925d0: ff ff ff f5 33 30 03 35 fd dd cf dd dd dd dd dd ....30.5........
1925e0: dd dd dd d5 33 30 03 35 0f ff ff dd dd dd dd dd ....30.5........
1925f0: dd dd dd d5 33 33 33 35 00 00 0f ff ff ff ff ff ....3335........
192600: ff ff ff f5 55 55 55 55 00 00 04 00 00 00 00 00 ....UUUU........
192610: 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
192620: ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 ff ................
192630: ff ff ff f8 f8 f8 f8 f8 ff f6 f6 f6 f6 f6 f6 f6 ................
192640: f6 f6 f6 f6 ff f8 ff ff ff 00 00 00 00 ff ff ff ................
192650: f6 ff f8 f8 f8 f8 f8 f8 ff f6 f6 f6 f6 f6 f6 f6 ................
192660: f6 f6 f6 f6 ff f8 ff f6 ff ff ff 00 ff ff f8 f8 ................
192670: f6 ff f8 f8 f8 f8 f8 f8 ff ff ff ff ff ff ff ff ................
192680: ff ff ff ff ff f8 ff f6 f8 f8 ff ff ff f8 f8 f8 ................
192690: f6 ff f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 ................
1926a0: f8 f8 f8 f8 f8 f8 ff f6 f8 f8 f8 ff ff f8 f8 f8 ................
1926b0: f6 ff f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 ff f8 f8 f8 ................
1926c0: f8 f8 f8 f8 f8 f8 ff f6 f8 f8 f8 ff ff f8 f8 f8 ................
1926d0: f6 ff f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 ................
1926e0: f8 f8 f8 f8 f8 f8 ff f6 f8 f8 f8 ff ff f8 f8 f8 ................
1926f0: f6 ff f8 f8 f8 f8 f8 ff ff ff ff f8 ff f8 ff ff ................
192700: ff f8 f8 f8 f8 f8 ff f6 f8 f8 f8 ff ff f8 f8 f8 ................
192710: f6 ff f8 f8 f8 f8 f8 f8 f8 ff f8 f8 ff f8 ff f8 ................
192720: f8 ff f8 f8 f8 f8 ff f6 f8 f8 f8 ff ff f8 f8 f8 ................
192730: f6 ff f8 f8 f8 f8 f8 f8 ff f8 f8 f8 ff f8 ff f8 ................
192740: f8 ff f8 f8 f8 f8 ff f6 f8 f8 f8 ff ff f8 f8 f8 ................
192750: f6 ff f8 f8 f8 f8 f8 ff ff ff ff f8 ff f8 ff ff ................
192760: ff f8 f8 f8 f8 f8 ff f6 f8 f8 f8 ff ff f8 f8 f8 ................
192770: f6 ff f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 ff f8 ................
192780: f8 f8 f8 f8 f8 f8 ff f6 f8 f8 f8 ff ff f8 f8 f8 ................
192790: f6 ff f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 ................
1927a0: f8 f8 f8 f8 f8 f8 ff f6 f8 f8 f8 ff ff f8 f8 f8 ................
1927b0: f6 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
1927c0: ff ff ff ff ff ff ff f6 f8 f8 f8 ff ff f8 f8 f8 ................
1927d0: f6 ff 00 00 00 00 ff d8 d8 d8 d8 d8 d8 d8 d8 d8 ................
1927e0: d8 d8 d8 d8 d8 d8 ff f6 f8 f8 f8 ff ff f8 f8 f8 ................
1927f0: f6 ff 00 00 00 00 ff d8 d8 d8 d8 d8 d8 d8 d8 d8 ................
192800: d8 d8 d8 d8 d8 d8 ff f6 f8 f8 f8 ff ff f8 f8 f8 ................
192810: f6 ff 00 00 00 00 ff d8 d8 d8 d8 d8 d8 d8 d8 d8 ................
192820: d8 d8 d8 d8 d8 d8 00 b0 b0 f8 f8 ff ff f8 f8 f8 ................
192830: f6 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
192840: ff ff ff ff ff 00 b0 b0 b0 b0 f8 ff ff f8 f8 f8 ................
192850: f6 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
192860: 00 00 00 00 00 00 b0 b0 b0 b0 f8 ff ff f8 f8 f8 ................
192870: f6 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
192880: 00 00 00 00 00 00 00 b0 b0 f8 f8 ff ff f8 f8 f8 ................
192890: f6 ff 00 00 00 ff 00 00 ff ff ff 00 00 00 ff ff ................
1928a0: ff 00 00 00 00 00 00 f8 f8 f8 f8 ff ff f8 f8 f8 ................
1928b0: f6 ff 00 00 ff ff 00 ff 00 00 00 ff 00 ff 00 00 ................
1928c0: 00 ff 00 b0 b0 b0 b0 b0 b0 b0 b0 b0 ff f8 f8 f8 ................
1928d0: f6 ff 00 00 00 ff 00 ff 00 00 00 ff 00 ff 00 00 ................
1928e0: 00 ff 00 b0 d8 d8 d8 d8 d8 d8 d8 b0 ff f8 f8 f8 ................
1928f0: f6 ff 00 00 00 ff 00 ff 00 00 00 ff 00 ff 00 00 ................
192900: 00 ff 00 b0 d8 d8 00 00 00 d8 d8 b0 ff f8 f8 f8 ................
192910: f6 ff 00 00 00 ff 00 ff 00 00 00 ff 00 ff 00 00 ................
192920: 00 ff 00 b0 d8 d8 00 00 00 d8 d8 b0 ff f8 f8 f8 ................
192930: f6 ff 00 00 00 ff 00 00 ff ff ff 00 00 00 ff ff ................
192940: ff 00 00 b0 d8 d8 d8 00 00 d8 d8 b0 ff f8 f8 f8 ................
192950: f6 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
192960: 00 00 00 b0 d8 d8 d8 00 00 d8 d8 b0 ff f8 f8 f8 ................
192970: f6 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
192980: 00 00 00 b0 d8 d8 d8 00 00 d8 d8 b0 ff f8 f8 f8 ................
192990: f6 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
1929a0: ff ff ff b0 d8 d8 d8 00 00 d8 d8 b0 ff f8 f8 f8 ................
1929b0: f6 ff f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 ................
1929c0: f8 f8 f8 b0 d8 d8 d8 00 00 d8 d8 b0 00 ff ff ff ................
1929d0: ff ff f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 ................
1929e0: f8 f8 f8 b0 d8 d8 d8 d8 d8 d8 d8 b0 00 00 00 00 ................
1929f0: 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................
192a00: ff ff ff b0 b0 b0 b0 b0 b0 b0 b0 b0 00 00 01 00 ................
192a10: 00 00 08 0c 00 00 07 0c 00 00 00 5a 05 a3 c5 a8 ...........Z....
192a20: 29 22 00 00 00 1c 00 5a 00 02 49 43 4e 23 00 00 )".....Z..ICN#..
192a30: 00 1a 69 63 6c 34 00 00 00 26 69 63 6c 38 00 00 ..icl4...&icl8..
192a40: 00 32 bf b9 ff ff 00 00 00 00 05 a3 c4 cc bf b9 .2..............
192a50: ff ff 00 00 01 04 05 a3 c4 d0 bf b9 ff ff 00 00 ................
192a60: 03 08 05 a3 c4 bc 00 00 00 00 00 00 00 00 00 00 ................
192a70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
24ec00: 00 00 00 00 00 00 00 00 01 00 00 03 00 00 00 01 ................
24ec10: 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 ................
24ec20: 02 00 00 25 00 00 00 12 00 00 00 10 00 00 00 00 ...%............
24ec30: 20 00 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 ...............
24ec40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
24ec70: 00 00 00 00 00 00 00 00 02 0a 01 00 00 00 00 00 ................
24ec80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
24ecf0: 00 00 00 00 00 00 00 00 c0 00 00 00 00 00 00 00 ................
24ed00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
24edf0: 00 00 00 00 00 00 00 00 01 f8 00 f8 00 78 00 0e .............x..
24ee00: 00 00 00 00 00 00 00 00 ff 01 00 01 00 00 0b 01 ................
24ee10: 61 74 63 6f 61 74 63 6f fe 00 00 00 00 00 00 00 atcoatco........
24ee20: 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 ................
24ee30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
24eff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 24 00 0e .............$..
24f000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
251000: 00 02 00 00 00 00 00 00 01 00 00 03 00 00 00 01 ................
251010: 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 ................
251020: 02 00 00 07 00 00 00 09 00 00 00 07 00 00 00 00 ................
251030: 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
251040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
2510f0: 00 00 00 00 00 00 00 00 c0 00 00 00 00 00 00 00 ................
251100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
2511f0: 00 00 00 00 00 00 00 00 01 f8 00 f8 00 78 00 0e .............x..
251200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
261000: 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1e ................
261010: 79 80 7f 79 7f 80 7f 79 7f 79 aa 79 7f 80 7f 79 y..y...y.y.y...y
261020: 7f 79 7f 7f 79 7f 79 7f 80 7f 79 80 7f 79 80 7f .y..y.y...y..y..
261030: 79 a4 7f 80 7f 79 80 73 7f a4 7f a4 7f 79 7f 79 y....y.s.....y.y
261040: 80 7f a4 7f 80 7f a4 7f 80 7f 79 7f 7f 79 7f a4 ..........y..y..
261050: 7f 79 7f a4 7f 79 7f a4 7f 79 7f 79 7f 7f a4 7f .y...y...y.y....
261060: 79 7f 7f 79 7f 7f a4 7f 79 7f 79 7f 7f a4 7f 79 y..y....y.y....y
261070: a4 7f 79 7f 7f 79 7f 79 7f 79 7f 79 7f 79 aa 79 ..y..y.y.y.y.y.y
261080: 7f 80 7f 79 80 7f 7f 80 7f 79 7f 79 7f a4 7f 79 ...y.....y.y...y
261090: 7f 79 7f 79 7f a4 80 7f 4f 4e 54 f6 55 4e 2a 4f .y.y....ONT.UN*O
2610a0: 4f 55 2a 00 00 4f 06 79 7f aa aa ea 01 f6 09 ff OU*..O.y........
2610b0: ea aa a4 5b 4f 06 2a 00 4e fe 00 61 06 4e 00 4e ...[O.*.N..a.N.N
2610c0: 00 4f 7f 5b a4 80 a3 a4 a4 86 a4 80 a4 80 aa a4 .O.[............
2610d0: a4 aa a4 a4 aa a3 aa a4 a4 80 aa a4 a4 86 a4 80 ................
2610e0: a3 80 a4 80 a4 7f a4 86 a4 a4 80 a3 80 a4 aa a4 ................
2610f0: a4 80 a3 80 a3 86 a4 a3 a4 aa a3 80 aa 80 a4 80 ................
261100: 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1e ................
261110: 00 00 00 00 00 00 00 00 00 1c 00 1e ff ff fe a4 ................
261120: 58 aa a4 a3 fb a9 a4 80 aa 7f a4 a3 fb a3 a4 80 X...............
261130: a4 7f a4 80 a4 86 aa a4 80 a4 80 aa a4 80 a4 a4 ................
261140: 80 aa 80 aa 80 a4 80 aa a4 a4 7f aa 80 a4 7f a4 ................
261150: 86 a4 80 a4 80 a3 80 aa 80 a4 86 a4 80 a3 fb 7f ................
261160: aa 80 aa a4 7f a4 86 a3 80 a4 80 a4 86 a4 80 a4 ................
261170: 86 a4 86 a4 80 a4 80 a4 a4 aa fe a4 7f aa a4 80 ................
261180: a4 80 aa 80 a3 80 aa 80 aa a4 a4 86 a4 7f aa 80 ................
261190: a4 a4 a3 aa aa a4 80 a4 7f a4 aa a4 a4 a3 fb a3 ................
2611a0: a4 aa 80 a3 fb a3 a4 a4 80 aa 80 a3 80 aa 80 aa ................
2611b0: a3 aa a4 a4 7f aa a4 a3 80 a4 80 a3 80 aa 80 a4 ................
2611c0: 80 a4 a4 aa aa a4 80 a4 aa a4 86 a4 86 a4 80 a3 ................
2611d0: 80 aa a4 a4 aa a3 aa a4 a4 80 aa a4 a4 86 a4 80 ................
2611e0: a3 80 a4 80 a4 7f a4 86 a4 a4 80 a3 80 a4 aa a4 ................
2611f0: a4 80 a3 80 a3 86 a4 a3 a4 aa a3 80 aa 20 80 a4 ............. ..
261200: 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1e ................
261210: aa a4 80 a4 86 a4 a3 fb a3 86 a4 80 aa 80 aa fe ................
261220: a4 58 aa a4 a3 fb a9 a4 80 aa 7f a4 a3 fb a3 a4 .X..............
261230: 80 a4 7f a4 80 a4 86 aa a4 80 a4 80 aa a4 80 a4 ................
261240: a4 80 aa 80 aa 80 a4 80 aa a4 a4 7f aa 80 a4 7f ................
261250: a4 86 a4 80 a4 80 a3 80 aa 80 a4 86 a4 80 a3 fb ................
261260: 7f aa 80 aa a4 7f a4 86 a3 80 a4 80 a4 86 a4 80 ................
261270: a4 86 a4 86 a4 80 a4 80 a4 a4 aa fe a4 25 aa a4 .............%..
261280: 80 a4 80 aa 80 a3 80 aa 80 a4 80 a4 80 a4 7f 55 ...............U
261290: 4e 4f 06 4f 54 f7 4f 55 30 4f 4f 55 4f 55 2a 79 NO.OT.OU0OOUOU*y
2612a0: a4 a4 ce ef 01 a5 06 ff ef aa a3 79 4e 4f fe 00 ...........yNO..
2612b0: 03 4f 4e 06 2a fe 00 05 06 00 79 4f 7f 79 fd 7f .ON.*.....yO.y..
2612c0: 00 79 f8 7f 02 79 7f 79 fb 7f 02 79 7f 79 fa 7f .y...y.y...y.y..
2612d0: 00 79 fb 7f 00 79 fb 7f 00 79 fe 7f 03 79 7f 7f .y...y...y...y..
2612e0: 79 fd 7f 00 79 fc 7f 00 79 fe 7f 00 79 fe 7f 0e y...y...y...y...
2612f0: 79 7f 7f 79 7f 7f 79 7f 7f 79 7f 7f 79 7f 79 fe y..y..y..y..y.y.
261300: 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 1e ................
261310: 00 00 00 00 00 00 00 00 00 1c 00 1e ff ff fe 7f ................
261320: 04 79 5b 7f 7f 79 fd 7f 00 79 fe 7f 13 79 7f 7f .y[..y...y...y..
261330: 79 7f 79 7f 9d 7f 7f 79 7f 79 7f 79 7f 7f 79 7f y.y....y.y.y..y.
261340: 79 fd 7f 00 79 fd 7f 01 a3 79 fc 7f 00 79 fe 7f y...y....y...y..
261350: 02 79 7f 79 fe 7f 00 79 fe 7f 08 79 7f 79 7f 7f .y.y...y...y.y..
261360: 79 7f 7f 79 fd 7f 01 79 79 fe 7f 02 a4 7f 79 fe y..y...yy.....y.
261370: 7f 00 79 fd 7f 00 79 fb 7f 07 79 7f 7f 79 7f 79 ..y...y...y..y.y
261380: 7f 79 fe 7f 00 79 fa 7f 07 79 7f 7f 79 7f 7f 79 .y...y...y..y..y
261390: 79 fe 7f 04 79 7f 79 7f 79 fa 7f 02 79 7f 79 fb y...y.y.y...y.y.
2613a0: 7f 02 79 7f 79 fa 7f 00 79 fb 7f 00 79 fb 7f 00 ..y.y...y...y...
2613b0: 79 fe 7f 03 79 7f 7f 79 fd 7f 00 79 fc 7f 00 79 y...y..y...y...y
2613c0: fe 7f 00 79 fe 7f 0e 79 7f 7f 79 7f 7f 79 7f 7f ...y...y..y..y..
2613d0: 79 7f 7f 79 7f 79 fe 7f 00 79 fe 7f 06 79 7f 7f y..y.y...y...y..
2613e0: 79 7f 7f 79 f8 7f 02 9d 7f 79 fd 7f 01 79 a3 fe y..y.....y...y..
2613f0: 7f 02 79 7f 79 fe 7f 04 79 5b 7f 7f 79 fd 7f 00 ..y.y...y[..y...
261400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
5f98c00: 48 2b 00 04 00 00 01 00 38 2e 31 30 00 00 00 00 H+......8.10....
5f98c10: b4 7f 39 4a b4 7f a9 cc 00 00 00 00 b4 7f a9 cc ..9J............
5f98c20: 00 00 00 00 00 00 00 00 00 00 02 00 00 02 fc 6d ...............m
5f98c30: 00 02 f0 48 00 00 12 1b 00 00 20 00 00 00 20 00 ...H...... ... .
5f98c40: 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 01 ................
5f98c50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
5f98c70: 00 00 00 00 00 00 60 00 00 00 60 00 00 00 00 30 ......`...`....0
5f98c80: 00 00 00 03 00 00 00 30 00 00 00 00 00 00 00 00 .......0........
5f98c90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
5f98cc0: 00 00 00 00 00 0b f0 00 00 0b f0 00 00 00 05 f8 ................
5f98cd0: 00 00 00 33 00 00 05 f8 00 00 00 00 00 00 00 00 ...3............
5f98ce0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
5f98d10: 00 00 00 00 00 0b f0 00 00 0b f0 00 00 00 05 f8 ................
5f98d20: 00 00 06 2b 00 00 05 f8 00 00 00 00 00 00 00 00 ...+............
5f98d30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
5f99200: 42 44 b4 7f 39 4a b4 7f 39 4b 83 00 00 05 00 03 BD..9J..9K......
5f99210: 00 09 fe e7 00 00 06 00 00 00 06 00 00 13 00 00 ................
5f99220: 00 15 00 00 07 5a 49 50 2d 31 30 30 00 00 00 00 .....ZIP-100....
5f99230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
5f99240: 00 00 00 00 00 00 00 00 00 0c 00 00 12 00 00 00 ................
5f99250: 12 00 00 00 00 00 00 05 00 00 00 00 00 00 00 02 ................
5f99260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
5f99270: 00 00 00 00 00 00 00 00 00 00 00 00 48 2b 00 18 ............H+..
5f99280: fe cf 00 00 12 00 00 00 00 03 00 00 00 00 00 00 ................
5f99290: 00 00 00 00 12 00 00 03 00 03 00 00 00 00 00 00 ................
5f992a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
hfsplus-1.0.4/libhfsp/test/dump3e.txt 0100644 0000000 0000000 00000125716 07441220605 016257 0 ustar root root # This is a commented dump of the end of my 2.5 GB HFS+ Partition
#
# $Id: dump3e.txt,v 1.1.1.1 2002/03/05 19:50:29 klaus Exp $
#
# This dump was created with
# dd bs=4096 skip=617720 if=/dev/hda13 | xxd
# I adjusted the offsets manually
#
96b04000: 3b81 0060 3bc1 0068 3ba1 006c 9001 005c ;..`;..h;..l...\
96b04010: 3b60 0000 8001 004c 9001 0060 8001 0050 ;`.....L...`...P
96b04020: 9001 0064 8001 0054 9001 0068 8001 0058 ...d...T...h...X
96b04030: 9001 006c 4800 0050 8061 0068 389f 0070 ...lH..P.a.h8..p
96b04040: 8063 0010 8183 0000 818c 0030 4801 6971 .c.........0H.iq
96b04050: 8041 0014 8001 0060 9001 005c 8001 005c .A.....`...\...\
96b04060: 2800 0000 4182 001c 8061 0064 389c 0000 (...A....a.d8...
96b04070: 38bd 0000 38de 0000 4800 32b5 6000 0000 8...8...H.2.`...
96b04080: 3b7b 0001 801f 002c 7c1b 0000 4180 ffac ;{.....,|...A...
96b04090: 807f 007c 3880 0000 8183 0000 818c 00a0 ...|8...........
96b040a0: 4801 691d 8041 0014 3800 0000 901f 0088 H.i..A..8.......
96b040b0: 807f 007c 8183 0000 818c 0014 4801 6901 ...|........H.i.
96b040c0: 8041 0014 3860 0000 8001 0098 3821 0090 .A..8`......8!..
96b040d0: 7c08 03a6 bb61 ffec 4e80 0020 80a3 0060 |....a..N.. ...`
96b040e0: 8003 0064 3860 0000 90a4 0000 9004 0004 ...d8`..........
96b040f0: 4e80 0020 80a3 0068 8003 006c 3860 0000 N.. ...h...l8`..
96b04100: 90a4 0000 9004 0004 4e80 0020 7c08 02a6 ........N.. |...
96b04110: 93e1 fffc 7c7f 1b78 9001 0008 9421 ffb0 ....|..x.....!..
96b04120: 80a4 0000 8004 0004 90a3 0050 9003 0054 ...........P...T
96b04130: 8003 0088 2c00 0000 4182 0040 801f 007c ....,...A..@...|
96b04140: 2800 0000 4182 0034 387f 0000 3881 0038 (...A..48...8..8
96b04150: 819f 0000 818c 004c 4801 6865 8041 0014 .......LH.he.A..
96b04160: 807f 007c 3881 0038 8183 0000 818c 003c ...|8..8.......<
96b04170: 4801 684d 8041 0014 801f 0090 2c00 0000 H.hM.A......,...
96b04180: 4082 0014 807f 0080 8063 0018 4801 60e1 @........c..H.`.
96b04190: 8041 0014 8001 0058 3821 0050 3860 0000 .A.....X8!.P8`..
96b041a0: 7c08 03a6 83e1 fffc 4e80 0020 80a3 0050 |.......N.. ...P
96b041b0: 8003 0054 3860 0000 90a4 0000 9004 0004 ...T8`..........
96b041c0: 4e80 0020 7c08 02a6 9001 0008 9421 ffc0 N.. |........!..
96b041d0: 8003 000c 3864 0000 7c04 0378 4801 5149 ....8d..|..xH.QI
96b041e0: 8041 0014 8001 0048 3860 0000 3821 0040 .A.....H8`..8!.@
96b041f0: 7c08 03a6 4e80 0020 7c08 02a6 9001 0008 |...N.. |.......
96b04200: 9421 ffc0 8003 0018 3864 0000 7c04 0378 .!......8d..|..x
96b04210: 4801 5115 8041 0014 8001 0048 3860 0000 H.Q..A.....H8`..
96b04220: 3821 0040 7c08 03a6 4e80 0020 8063 002c 8!.@|...N.. .c.,
96b04230: 4e80 0020 7c08 02a6 93e1 fffc 3be3 0000 N.. |.......;...
96b04240: 9001 0008 3800 0000 9421 ff90 9001 0060 ....8....!.....`
96b04250: 3881 0060 9001 0064 9001 0050 9001 0054 8..`...d...P...T
96b04260: 9001 0040 9001 0044 9001 0048 9001 004c ...@...D...H...L
96b04270: 8063 007c 8183 0000 818c 0058 4801 6741 .c.|.......XH.gA
96b04280: 8041 0014 387f 0000 3881 0050 819f 0000 .A..8...8..P....
96b04290: 818c 004c 4801 6729 8041 0014 3861 0060 ...LH.g).A..8a.`
96b042a0: 3881 0040 4801 5fe1 8041 0014 8061 0060 8..@H._..A...a.`
96b042b0: 8001 0040 7c03 0000 4080 0014 7c03 0050 ...@|...@...|..P
96b042c0: 7c03 0214 9001 0060 4800 0024 8001 0050 |......`H..$...P
96b042d0: 8081 0048 7c03 0214 7c00 2000 4081 0010 ...H|...|. .@...
96b042e0: 7c04 0050 7c00 1850 9001 0060 8061 0064 |..P|..P...`.a.d
96b042f0: 8001 0044 7c03 0000 4080 0014 7c03 0050 ...D|...@...|..P
96b04300: 7c03 0214 9001 0064 4800 0024 8001 0054 |......dH..$...T
96b04310: 8081 004c 7c03 0214 7c00 2000 4081 0010 ...L|...|. .@...
96b04320: 7c04 0050 7c00 1850 9001 0064 807f 007c |..P|..P...d...|
96b04330: 3881 0060 8183 0000 818c 004c 4801 6681 8..`.......LH.f.
96b04340: 8041 0014 8001 0078 3821 0070 7c08 03a6 .A.....x8!.p|...
96b04350: 83e1 fffc 4e80 0020 7c08 02a6 bfc1 fff8 ....N.. |.......
96b04360: 3be4 0000 3bc3 0000 9001 0008 9421 ffc0 ;...;........!..
96b04370: 93e3 004c 8003 0088 2c00 0000 4182 0080 ...L....,...A...
96b04380: 807e 007c 2803 0000 4182 0074 2c1f 0000 .~.|(...A..t,...
96b04390: 4182 0044 801e 0098 2c00 0000 4182 000c A..D....,...A...
96b043a0: 7fc3 f378 4bff fe91 807e 0080 7fe4 fb78 ...xK....~.....x
96b043b0: 4800 2149 6000 0000 807e 007c 7fe4 fb78 H.!I`....~.|...x
96b043c0: 8183 0000 818c 00a0 4801 65f5 8041 0014 ........H.e..A..
96b043d0: 4800 003c 8183 0000 7fe4 fb78 818c 00a0 H..<.......x....
96b043e0: 4801 65dd 8041 0014 807e 0080 7fe4 fb78 H.e..A...~.....x
96b043f0: 4800 2109 6000 0000 4800 0014 807e 0080 H.!.`...H....~..
96b04400: 7fe4 fb78 4800 20f5 6000 0000 8001 0048 ...xH. .`......H
96b04410: 3821 0040 3860 0000 7c08 03a6 bbc1 fff8 8!.@8`..|.......
96b04420: 4e80 0020 7c08 02a6 9001 0008 9421 ffc0 N.. |........!..
96b04430: 8003 0088 2c00 0000 4182 0028 8003 007c ....,...A..(...|
96b04440: 2800 0000 4182 001c 7c03 0378 8183 0000 (...A...|..x....
96b04450: 818c 00a4 4801 6569 8041 0014 4800 0008 ....H.ei.A..H...
96b04460: 8063 004c 8001 0048 3821 0040 7c08 03a6 .c.L...H8!.@|...
96b04470: 4e80 0020 3860 0000 4e80 0020 3860 0000 N.. 8`..N.. 8`..
96b04480: 4e80 0020 3860 ffff 4e80 0020 3860 0000 N.. 8`..N.. 8`..
96b04490: 4e80 0020 3860 ffff 4e80 0020 3860 0001 N.. 8`..N.. 8`..
96b044a0: 4e80 0020 7c08 02a6 bfc1 fff8 3bc3 0000 N.. |.......;...
96b044b0: 3be4 0000 9001 0008 9421 ffc0 8003 0088 ;........!......
96b044c0: 2c00 0000 4182 002c 807e 007c 2803 0000 ,...A..,.~.|(...
96b044d0: 4182 0020 8183 0000 7fe4 fb78 818c 004c A.. .......x...L
96b044e0: 4801 64dd 8041 0014 3860 0000 4800 0030 H.d..A..8`..H..0
96b044f0: 807e 0080 7fe4 fb78 80be 0058 80de 005c .~.....x...X...\
96b04500: 4800 1e99 6000 0000 809f 0000 3860 0000 H...`.......8`..
96b04510: 801f 0004 909e 0058 901e 005c 8001 0048 .......X...\...H
96b04520: 3821 0040 7c08 03a6 bbc1 fff8 4e80 0020 8!.@|.......N..
96b04530: 8003 0088 2c00 0000 4082 0010 8003 0098 ....,...@.......
96b04540: 2c00 0000 4182 0024 80a3 007c 2805 0000 ,...A..$...|(...
96b04550: 4182 0018 8005 0020 9004 0000 8005 0024 A...... .......$
96b04560: 9004 0004 4800 0014 80a3 0058 8003 005c ....H......X...\
96b04570: 90a4 0000 9004 0004 3860 0000 4e80 0020 ........8`..N..
96b04580: 3860 0000 4e80 0020 7c08 02a6 bf61 ffec 8`..N.. |....a..
96b04590: 7c7f 1b78 9001 0008 9421 ff70 8003 002c |..x.....!.p...,
96b045a0: 2c00 0000 4082 000c 38a0 0000 4800 0008 ,...@...8...H...
96b045b0: 38a0 ffff 90a1 0048 387f 0024 3800 0000 8......H8..$8...
96b045c0: 3881 004c 90a1 004c 38c1 0054 38a1 0058 8..L...L8..T8..X
96b045d0: 9061 0050 9001 0054 9001 0058 8001 0048 .a.P...T...X...H
96b045e0: 2800 0000 4182 0010 8061 0050 4800 2d41 (...A....a.PH.-A
96b045f0: 6000 0000 8001 0048 3b81 0060 3bc1 0068 `......H;..`;..h
96b04600: 3ba1 006c 9001 005c 3b60 0000 8001 004c ;..l...\;`.....L
96b04610: 9001 0060 8001 0050 9001 0064 8001 0054 ...`...P...d...T
96b04620: 9001 0068 8001 0058 9001 006c 4800 004c ...h...X...lH..L
96b04630: 8061 0068 8063 0010 8183 0000 818c 0040 .a.h.c.........@
96b04640: 4801 637d 8041 0014 8001 0060 9001 005c H.c}.A.....`...\
96b04650: 8001 005c 2800 0000 4182 001c 8061 0064 ...\(...A....a.d
96b04660: 389c 0000 38bd 0000 38de 0000 4800 2cc1 8...8...8...H.,.
96b04670: 6000 0000 3b7b 0001 801f 002c 7c1b 0000 `...;{.....,|...
96b04680: 4180 ffb0 8001 0098 3821 0090 3860 0000 A.......8!..8`..
96b04690: 7c08 03a6 bb61 ffec 4e80 0020 3860 0001 |....a..N.. 8`..
96b046a0: 4e80 0020 7c08 02a6 bf41 ffe8 7c9a 2379 N.. |....A..|.#y
96b046b0: 3be3 0000 9001 0008 9421 ff80 4082 0010 ;........!..@...
96b046c0: 3c60 8000 3863 4005 4800 01b8 90bf 0078 <`..8c@.H......x
96b046d0: 3860 0020 4801 4b01 8041 0014 7c7b 1b79 8`. H.K..A..|{.y
96b046e0: 4182 0020 281f 0000 389f 0000 4182 0008 A.. (...8...A...
96b046f0: 3884 0004 7f63 db78 4800 17c5 6000 0000 8....c.xH...`...
96b04700: 281a 0000 937f 0080 4182 0050 7f43 d378 (.......A..P.C.x
96b04710: 3882 0f84 819a 0000 38bf 0074 818c 0008 8.......8..t....
96b04720: 4801 629d 8041 0014 2c03 0000 4082 0020 H.b..A..,...@..
96b04730: 807f 0074 389f 0070 8183 0000 818c 0018 ...t8..p........
96b04740: 4801 627d 8041 0014 4800 0010 3c60 8000 H.b}.A..H...<`..
96b04750: 3863 4005 4800 012c 7fe3 fb78 819f 0000 8c@.H..,...x....
96b04760: 818c 0100 4801 6259 8041 0014 2c03 0000 ....H.bY.A..,...
96b04770: 4182 0108 7fe3 fb78 837f 0040 819f 0000 A......x...@....
96b04780: 818c 0104 4801 6239 8041 0014 2c03 0000 ....H.b9.A..,...
96b04790: 4182 00c8 3ba1 0054 3b40 0000 3bc0 0000 A...;..T;@..;...
96b047a0: 4800 009c 807f 003c 7f83 f02e 807c 0010 H......<.....|..
96b047b0: 8183 0000 818c 0014 4801 6205 8041 0014 ........H.b..A..
96b047c0: 387f 0000 389c 0000 819f 0000 818c 010c 8...8...........
96b047d0: 4801 61ed 8041 0014 2c03 0000 4182 0058 H.a..A..,...A..X
96b047e0: 815c 0020 3800 0000 813c 001c 391c 0014 .\. 8....<..9...
96b047f0: 38fd 0000 389f 0070 9001 0054 9001 0058 8...8..p...T...X
96b04800: 807c 0010 80dc 0004 8183 0000 80bc 0000 .|..............
96b04810: 818c 001c 4801 61a9 8041 0014 387f 0000 ....H.a..A..8...
96b04820: 389c 0000 819f 0000 818c 0110 4801 6191 8...........H.a.
96b04830: 8041 0014 3b5a 0001 3bde 0004 7c1a d800 .A..;Z..;...|...
96b04840: 4180 ff64 7fe3 fb78 819f 0000 818c 0108 A..d...x........
96b04850: 4801 616d 8041 0014 7fe3 fb78 809f 0080 H.am.A.....x....
96b04860: 819f 0000 818c 00f0 4801 6155 8041 0014 ........H.aU.A..
96b04870: 3860 0000 4800 000c 3c60 8000 3863 4005 8`..H...<`..8c@.
96b04880: 8001 0088 3821 0080 7c08 03a6 bb41 ffe8 ....8!..|....A..
96b04890: 4e80 0020 4e80 0020 7c08 02a6 bf41 ffe8 N.. N.. |....A..
96b048a0: 7c7e 1b78 9001 0008 9421 ff70 8003 002c |~.x.....!.p...,
96b048b0: 2c00 0000 4082 000c 38a0 0000 4800 0008 ,...@...8...H...
96b048c0: 38a0 ffff 90a1 0048 387e 0024 3800 0000 8......H8~.$8...
96b048d0: 3881 004c 90a1 004c 38c1 0054 38a1 0058 8..L...L8..T8..X
96b048e0: 9061 0050 9001 0054 9001 0058 8001 0048 .a.P...T...X...H
96b048f0: 2800 0000 4182 0010 8061 0050 4800 2a31 (...A....a.PH.*1
96b04900: 6000 0000 8001 0048 3be1 0060 3ba1 0068 `......H;..`;..h
96b04910: 3b81 006c 9001 005c 8001 004c 9001 0060 ;..l...\...L...`
96b04920: 8001 0050 9001 0064 8001 0054 9001 0068 ...P...d...T...h
96b04930: 8001 0058 9001 006c 807e 0080 2803 0000 ...X...l.~..(...
96b04940: 4182 0018 3880 0001 4800 15f1 6000 0000 A...8...H...`...
96b04950: 3800 0000 901e 0080 3b40 0000 4800 00a0 8.......;@..H...
96b04960: 8361 0068 807b 0010 8183 0000 818c 0020 .a.h.{.........
96b04970: 4801 604d 8041 0014 807b 0010 8183 0000 H.`M.A...{......
96b04980: 818c 0018 4801 6039 8041 0014 281b 0000 ....H.`9.A..(...
96b04990: 4182 003c 807b 0010 2803 0000 4182 0014 A..<.{..(...A...
96b049a0: 8183 0000 818c 0010 4801 6015 8041 0014 ........H.`..A..
96b049b0: 387b 0004 3880 ffff 4800 4855 6000 0000 8{..8...H.HU`...
96b049c0: 7f63 db78 4801 47e1 8041 0014 8001 0060 .c.xH.G..A.....`
96b049d0: 9001 005c 8001 005c 2800 0000 4182 001c ...\...\(...A...
96b049e0: 8061 0064 389f 0000 38bc 0000 38dd 0000 .a.d8...8...8...
96b049f0: 4800 293d 6000 0000 3b5a 0001 801e 002c H.)=`...;Z.....,
96b04a00: 7c1a 0000 4180 ff5c 387e 0024 4800 2665 |...A..\8~.$H.&e
96b04a10: 6000 0000 387e 003c 3880 0000 38a0 ffff `...8~.<8...8...
96b04a20: 4800 2295 6000 0000 807e 0074 2803 0000 H.".`....~.t(...
96b04a30: 4182 001c 8183 0000 818c 0010 4801 5f81 A...........H._.
96b04a40: 8041 0014 3800 0000 901e 0074 8001 0098 .A..8......t....
96b04a50: 3821 0090 3860 0000 7c08 03a6 bb41 ffe8 8!..8`..|....A..
96b04a60: 4e80 0020 7c08 02a6 93e1 fffc 3be4 0000 N.. |.......;...
96b04a70: 9001 0008 3800 0000 9421 ffb0 9001 0038 ....8....!.....8
96b04a80: 8063 0074 2803 0000 4182 0030 8183 0000 .c.t(...A..0....
96b04a90: 38a1 0038 3882 0f84 818c 0008 4801 5f21 8..88.......H._!
96b04aa0: 8041 0014 2c03 0000 4182 0010 3c60 8000 .A..,...A...<`..
96b04ab0: 3863 4005 4800 0034 8061 0038 7fe4 fb78 8c@.H..4.a.8...x
96b04ac0: 8183 0000 818c 001c 4801 5ef5 8041 0014 ........H.^..A..
96b04ad0: 8061 0038 8183 0000 818c 0010 4801 5ee1 .a.8........H.^.
96b04ae0: 8041 0014 3860 0000 8001 0058 3821 0050 .A..8`.....X8!.P
96b04af0: 7c08 03a6 83e1 fffc 4e80 0020 8063 0084 |.......N.. .c..
96b04b00: 4e80 0020 8003 0058 9004 0000 8003 005c N.. ...X.......\
96b04b10: 9004 0004 80a4 0000 8003 0050 7c05 0214 ...........P|...
96b04b20: 9004 0008 8003 0054 3860 0000 80a4 0004 .......T8`......
96b04b30: 7c05 0214 9004 000c 4e80 0020 3c60 8000 |.......N.. <`..
96b04b40: 3863 4005 4e80 0020 7c08 02a6 3880 0000 8c@.N.. |...8...
96b04b50: 9001 0008 9421 ffc0 8183 0000 818c 0048 .....!.........H
96b04b60: 4801 5e5d 8041 0014 8001 0048 3860 0000 H.^].A.....H8`..
96b04b70: 3821 0040 7c08 03a6 4e80 0020 7c08 02a6 8!.@|...N.. |...
96b04b80: 3880 0000 9001 0008 9421 ffc0 8183 0000 8........!......
96b04b90: 818c 0048 4801 5e29 8041 0014 8001 0048 ...HH.^).A.....H
96b04ba0: 3860 0000 3821 0040 7c08 03a6 4e80 0020 8`..8!.@|...N..
96b04bb0: 7c08 02a6 3880 0000 9001 0008 9421 ffc0 |...8........!..
96b04bc0: 8183 0000 818c 0048 4801 5df5 8041 0014 .......HH.]..A..
96b04bd0: 8001 0048 3860 0000 3821 0040 7c08 03a6 ...H8`..8!.@|...
96b04be0: 4e80 0020 7c08 02a6 bfc1 fff8 3bc3 0000 N.. |.......;...
96b04bf0: 3860 0020 9001 0008 9421 ff90 4801 45d9 8`. .....!..H.E.
96b04c00: 8041 0014 7c7f 1b79 4182 0020 281e 0000 .A..|..yA.. (...
96b04c10: 389e 0000 4182 0008 3884 0004 7fe3 fb78 8...A...8......x
96b04c20: 4800 129d 6000 0000 807e 0080 3880 0000 H...`....~..8...
96b04c30: 4800 18c9 6000 0000 807e 0080 8003 001c H...`....~......
96b04c40: 2c00 0002 4182 000c 4080 0024 4800 0020 ,...A...@..$H..
96b04c50: 387e 0000 389f 0000 819e 0000 818c 00f4 8~..8...........
96b04c60: 4801 5d5d 8041 0014 4800 001c 387e 0000 H.]].A..H...8~..
96b04c70: 389f 0000 819e 0000 818c 00f0 4801 5d41 8...........H.]A
96b04c80: 8041 0014 807e 0080 3880 0001 8003 001c .A...~..8.......
96b04c90: 901f 001c 807e 0080 4800 12a1 6000 0000 .....~..H...`...
96b04ca0: 3800 0000 3881 0054 901e 0080 93fe 0080 8...8..T........
96b04cb0: 9001 005c 9001 0060 807e 0058 801e 005c ...\...`.~.X...\
96b04cc0: 80a1 005c 9061 0054 80c1 0060 9001 0058 ...\.a.T...`...X
96b04cd0: 807e 0080 4800 16c5 6000 0000 807e 0060 .~..H...`....~.`
96b04ce0: 38a1 004c 801e 0064 9061 004c 9001 0050 8..L...d.a.L...P
96b04cf0: 807e 0074 809e 0078 8183 0000 818c 0048 .~.t...x.......H
96b04d00: 4801 5cbd 8041 0014 807e 0080 3880 0001 H.\..A...~..8...
96b04d10: 4800 17e9 6000 0000 8001 0078 3821 0070 H...`......x8!.p
96b04d20: 3860 0001 7c08 03a6 bbc1 fff8 4e80 0020 8`..|.......N..
96b04d30: 3860 0001 4e80 0020 7c08 02a6 93e1 fffc 8`..N.. |.......
96b04d40: 3be3 0000 9001 0008 3800 0064 9421 ff70 ;.......8..d.!.p
96b04d50: 9081 00ac 3861 004c 3881 0048 90a1 00b0 ....8a.L8..H....
96b04d60: 9001 004c 9001 0048 4801 56b5 8041 0014 ...L...HH.V..A..
96b04d70: 8001 004c 3c80 4330 8061 00ac 6c00 8000 ...L<.C0.a..l...
96b04d80: c862 8bf8 9001 0074 6c60 8000 c822 8c00 .b.....tl`..."..
96b04d90: 9081 0070 c801 0070 9001 007c ec00 1828 ...p...p...|...(
96b04da0: 9081 0078 fc00 0824 c841 0078 ec42 1828 ...x...$.A.x.B.(
96b04db0: fc02 0032 fc00 001e d801 0068 8001 006c ...2.......h...l
96b04dc0: 901f 0060 8001 0048 8061 00b0 6c00 8000 ...`...H.a..l...
96b04dd0: 9001 005c 6c60 8000 9081 0058 c801 0058 ...\l`.....X...X
96b04de0: 9001 0064 ec00 1828 9081 0060 fc00 0824 ...d...(...`...$
96b04df0: c821 0060 ec21 1828 fc01 0032 fc00 001e .!.`.!.(...2....
96b04e00: d801 0050 8001 0054 901f 0064 8001 0098 ...P...T...d....
96b04e10: 3821 0090 7c08 03a6 83e1 fffc 4e80 0020 8!..|.......N..
96b04e20: 3860 0001 4e80 0020 3c60 8000 3863 4001 8`..N.. <`..8c@.
96b04e30: 4e80 0020 3860 0001 4e80 0020 3860 0000 N.. 8`..N.. 8`..
96b04e40: 4e80 0020 3860 0000 4e80 0020 3860 0000 N.. 8`..N.. 8`..
96b04e50: 4e80 0020 3863 fffc 4bff e8f4 3863 fffc N.. 8c..K...8c..
96b04e60: 4bff e8d8 3863 fffc 4bff e6a0 7c08 02a6 K...8c..K...|...
96b04e70: 93e1 fffc 3922 3718 7c7f 1b78 9001 0008 ....9"7.|..x....
96b04e80: 3800 0000 3902 d944 38a9 0044 9421 ffc0 8...9..D8..D.!..
96b04e90: 2804 0000 38c2 382c 9103 0000 3869 0070 (...8.8,....8i.p
96b04ea0: 38e2 3800 90df 0000 38c2 37dc 911f 0004 8.8.....8.7.....
96b04eb0: 90ff 0004 911f 0008 90df 0008 913f 0000 .............?..
96b04ec0: 90bf 0004 907f 0008 901f 000c 901f 0010 ................
96b04ed0: 901f 0014 901f 0018 901f 001c 901f 0020 ...............
96b04ee0: 901f 0024 4182 0020 7c83 2378 3882 0f94 ...$A.. |.#x8...
96b04ef0: 8183 0000 38bf 0010 818c 0008 4801 5ac1 ....8.......H.Z.
96b04f00: 8041 0014 8001 0048 3821 0040 7fe3 fb78 .A.....H8!.@...x
96b04f10: 7c08 03a6 83e1 fffc 4e80 0020 7c08 02a6 |.......N.. |...
96b04f20: 93e1 fffc 7c7f 1b79 3862 3718 9001 0008 ....|..y8b7.....
96b04f30: 9421 ffc0 4182 002c 907f 0000 38a3 0044 .!..A..,....8..D
96b04f40: 3863 0070 7c80 0735 90bf 0004 907f 0008 8c.p|..5........
96b04f50: 4081 0010 7fe3 fb78 4801 424d 8041 0014 @......xH.BM.A..
96b04f60: 8001 0048 3821 0040 7fe3 fb78 7c08 03a6 ...H8!.@...x|...
96b04f70: 83e1 fffc 4e80 0020 8083 000c 3804 0001 ....N.. ....8...
96b04f80: 9003 000c 7c03 0378 4e80 0020 7c08 02a6 ....|..xN.. |...
96b04f90: 9001 0008 9421 ffc0 8083 000c 3404 ffff .....!......4...
96b04fa0: 9003 000c 4081 000c 8063 000c 4800 0024 ....@....c..H..$
96b04fb0: 2803 0000 4182 0018 8183 0000 3880 0001 (...A.......8...
96b04fc0: 818c 00c0 4801 59f9 8041 0014 3860 0000 ....H.Y..A..8`..
96b04fd0: 8001 0048 3821 0040 7c08 03a6 4e80 0020 ...H8!.@|...N..
96b04fe0: 7c08 02a6 bfc1 fff8 3940 0000 7cbf 2b78 |.......9@..|.+x
96b04ff0: 3902 0e84 7c7e 1b78 38a2 0fd4 396a 0000 9...|~.x8...9j..
96b05000: 9001 0008 7d4c 5378 3922 0fc4 9421 ffc0 ....}LSx9"...!..
96b05010: 8004 0000 8068 0000 7c00 1840 3862 0ff4 .....h..|..@8b..
96b05020: 4082 0018 80e4 0004 80c8 0004 7c07 3040 @...........|.0@
96b05030: 4082 0008 3980 0001 5586 063f 4182 0018 @...9...U..?A...
96b05040: 80e4 0008 80c8 0008 7c07 3040 4082 0008 ........|.0@@...
96b05050: 3960 0001 5566 063f 4182 0018 80e4 000c 9`..Uf.?A.......
96b05060: 80c8 000c 7c07 3040 4082 0008 3940 0001 ....|.0@@...9@..
96b05070: 5546 063f 4182 0024 7fc3 f378 819e 0000 UF.?A..$...x....
96b05080: 818c 000c 4801 5939 8041 0014 93df 0000 ....H.Y9.A......
96b05090: 3860 0000 4800 01d8 80c9 0000 3900 0000 8`..H.......9...
96b050a0: 3948 0000 3968 0000 7c00 3040 4082 0018 9H..9h..|.0@@...
96b050b0: 80e4 0004 80c9 0004 7c07 3040 4082 0008 ........|.0@@...
96b050c0: 3960 0001 5566 063f 4182 0018 80e4 0008 9`..Uf.?A.......
96b050d0: 80c9 0008 7c07 3040 4082 0008 3940 0001 ....|.0@@...9@..
96b050e0: 5546 063f 4182 0018 80e4 000c 80c9 000c UF.?A...........
96b050f0: 7c07 3040 4082 0008 3900 0001 5506 063f |.0@@...9...U..?
96b05100: 4182 0024 7fc3 f378 819e 0000 818c 000c A..$...x........
96b05110: 4801 58ad 8041 0014 93df 0000 3860 0000 H.X..A......8`..
96b05120: 4800 014c 80c3 0000 3900 0000 3928 0000 H..L....9...9(..
96b05130: 3948 0000 7c00 3040 4082 0018 80e4 0004 9H..|.0@@.......
96b05140: 80c3 0004 7c07 3040 4082 0008 3940 0001 ....|.0@@...9@..
96b05150: 5546 063f 4182 0018 80e4 0008 80c3 0008 UF.?A...........
96b05160: 7c07 3040 4082 0008 3920 0001 5526 063f |.0@@...9 ..U&.?
96b05170: 4182 0018 80c4 000c 8063 000c 7c06 1840 A........c..|..@
96b05180: 4082 0008 3900 0001 5503 063f 4182 0034 @...9...U..?A..4
96b05190: 7fc3 f378 819e 0000 818c 000c 4801 5821 ...x........H.X!
96b051a0: 8041 0014 281e 0000 387e 0000 4182 0008 .A..(...8~..A...
96b051b0: 3863 0004 907f 0000 3860 0000 4800 00b0 8c......8`..H...
96b051c0: 8065 0000 38c0 0000 38e6 0000 3906 0000 .e..8...8...9...
96b051d0: 7c00 1840 4082 0018 8064 0004 8005 0004 |..@@....d......
96b051e0: 7c03 0040 4082 0008 3900 0001 5500 063f |..@@...9...U..?
96b051f0: 4182 0018 8064 0008 8005 0008 7c03 0040 A....d......|..@
96b05200: 4082 0008 38e0 0001 54e0 063f 4182 0018 @...8...T..?A...
96b05210: 8064 000c 8005 000c 7c03 0040 4082 0008 .d......|..@@...
96b05220: 38c0 0001 54c0 063f 4182 0034 7fc3 f378 8...T..?A..4...x
96b05230: 819e 0000 818c 000c 4801 5785 8041 0014 ........H.W..A..
96b05240: 281e 0000 387e 0000 4182 0008 3863 0008 (...8~..A...8c..
96b05250: 907f 0000 3860 0000 4800 0014 3800 0000 ....8`..H...8...
96b05260: 3c60 8000 901f 0000 3863 4002 8001 0048 <`......8c@....H
96b05270: 3821 0040 7c08 03a6 bbc1 fff8 4e80 0020 8!.@|.......N..
96b05280: 7c08 02a6 93e1 fffc 7c7f 1b78 9001 0008 |.......|..x....
96b05290: 9421 ffc0 8063 0010 2803 0000 4182 0070 .!...c..(...A..p
96b052a0: 8183 0000 38bf 0014 3882 1024 818c 0008 ....8...8..$....
96b052b0: 4801 570d 8041 0014 807f 0010 38bf 0018 H.W..A......8...
96b052c0: 3882 1004 8183 0000 818c 0008 4801 56f1 8...........H.V.
96b052d0: 8041 0014 807f 0010 38bf 001c 3882 0fb4 .A......8...8...
96b052e0: 8183 0000 818c 0008 4801 56d5 8041 0014 ........H.V..A..
96b052f0: 807f 0010 38bf 0024 3882 0fa4 8183 0000 ....8..$8.......
96b05300: 818c 0008 4801 56b9 8041 0014 8001 0048 ....H.V..A.....H
96b05310: 3821 0040 3860 0000 7c08 03a6 83e1 fffc 8!.@8`..|.......
96b05320: 4e80 0020 7c08 02a6 bfc1 fff8 3bc3 0000 N.. |.......;...
96b05330: 3be4 0000 9001 0008 9421 ffc0 8063 0014 ;........!...c..
96b05340: 2803 0000 4182 0034 8183 0000 7fc4 f378 (...A..4.......x
96b05350: 818c 0018 4801 5669 8041 0014 807e 0014 ....H.Vi.A...~..
96b05360: 8183 0000 818c 0010 4801 5655 8041 0014 ........H.VU.A..
96b05370: 3800 0000 901e 0014 7fe3 fb78 3882 1024 8..........x8..$
96b05380: 819f 0000 38be 0014 818c 0008 4801 5631 ....8.......H.V1
96b05390: 8041 0014 2c03 0000 4182 0010 3c60 8004 .A..,...A...<`..
96b053a0: 3863 0009 4800 0028 807e 0014 2803 0000 8c..H..(.~..(...
96b053b0: 4182 0018 8183 0000 7fc4 f378 818c 0014 A..........x....
96b053c0: 4801 55fd 8041 0014 3860 0000 8001 0048 H.U..A..8`.....H
96b053d0: 3821 0040 7c08 03a6 bbc1 fff8 4e80 0020 8!.@|.......N..
96b053e0: 7c08 02a6 93e1 fffc 7c7f 1b78 9001 0008 |.......|..x....
96b053f0: 9421 ffc0 8063 0018 2803 0000 4182 001c .!...c..(...A...
96b05400: 8183 0000 818c 0010 4801 55b5 8041 0014 ........H.U..A..
96b05410: 3800 0000 901f 0018 807f 0014 2803 0000 8...........(...
96b05420: 4182 001c 8183 0000 818c 0010 4801 5591 A...........H.U.
96b05430: 8041 0014 3800 0000 901f 0014 807f 0010 .A..8...........
96b05440: 2803 0000 4182 001c 8183 0000 818c 0010 (...A...........
96b05450: 4801 556d 8041 0014 3800 0000 901f 0010 H.Um.A..8.......
96b05460: 807f 001c 2803 0000 4182 001c 8183 0000 ....(...A.......
96b05470: 818c 0010 4801 5549 8041 0014 3800 0000 ....H.UI.A..8...
96b05480: 901f 001c 8001 0048 3821 0040 3860 0000 .......H8!.@8`..
96b05490: 7c08 03a6 83e1 fffc 4e80 0020 7c08 02a6 |.......N.. |...
96b054a0: 9001 0008 9421 ffc0 8183 0000 818c 00bc .....!..........
96b054b0: 4801 550d 8041 0014 2803 0000 4182 001c H.U..A..(...A...
96b054c0: 8183 0000 818c 0014 4801 54f5 8041 0014 ........H.T..A..
96b054d0: 3860 0000 4800 000c 3c60 8000 3863 4005 8`..H...<`..8c@.
96b054e0: 8001 0048 3821 0040 7c08 03a6 4e80 0020 ...H8!.@|...N..
96b054f0: 3860 0000 4e80 0020 7c08 02a6 93e1 fffc 8`..N.. |.......
96b05500: 7c9f 2378 9001 0008 9421 ffc0 8183 0000 |.#x.....!......
96b05510: 818c 00bc 4801 54a9 8041 0014 2803 0000 ....H.T..A..(...
96b05520: 4182 0020 8183 0000 7fe4 fb78 818c 00a0 A.. .......x....
96b05530: 4801 548d 8041 0014 3860 0000 4800 000c H.T..A..8`..H...
96b05540: 3c60 8000 3863 4005 8001 0048 3821 0040 <`..8c@....H8!.@
96b05550: 7c08 03a6 83e1 fffc 4e80 0020 7c08 02a6 |.......N.. |...
96b05560: 93e1 fffc 7c9f 2378 9001 0008 9421 ffc0 ....|.#x.....!..
96b05570: 8183 0000 818c 00bc 4801 5445 8041 0014 ........H.TE.A..
96b05580: 2803 0000 4182 0020 8183 0000 7fe4 fb78 (...A.. .......x
96b05590: 818c 00b4 4801 5429 8041 0014 3860 0000 ....H.T).A..8`..
96b055a0: 4800 000c 3c60 8000 3863 4005 8001 0048 H...<`..8c@....H
96b055b0: 3821 0040 7c08 03a6 83e1 fffc 4e80 0020 8!.@|.......N..
96b055c0: 7c08 02a6 9001 0008 9421 ffc0 8183 0000 |........!......
96b055d0: 818c 00bc 4801 53e9 8041 0014 2803 0000 ....H.S..A..(...
96b055e0: 4182 001c 8183 0000 818c 0098 4801 53d1 A...........H.S.
96b055f0: 8041 0014 3860 0000 4800 000c 3c60 8000 .A..8`..H...<`..
96b05600: 3863 4005 8001 0048 3821 0040 7c08 03a6 8c@....H8!.@|...
96b05610: 4e80 0020 7c08 02a6 9001 0008 9421 ffc0 N.. |........!..
96b05620: 8183 0000 818c 00bc 4801 5395 8041 0014 ........H.S..A..
96b05630: 2803 0000 4182 0018 8183 0000 818c 0144 (...A..........D
96b05640: 4801 537d 8041 0014 4800 0008 3860 0000 H.S}.A..H...8`..
96b05650: 8001 0048 3821 0040 7c08 03a6 4e80 0020 ...H8!.@|...N..
96b05660: 8063 0020 4e80 0020 7c08 02a6 bfc1 fff8 .c. N.. |.......
96b05670: 7c9e 2378 9001 0008 9421 ffc0 8183 0000 |.#x.....!......
96b05680: 818c 00bc 4801 5339 8041 0014 7c7f 1b79 ....H.S9.A..|..y
96b05690: 4182 0030 807e 0000 4801 4965 8041 0014 A..0.~..H.Ie.A..
96b056a0: 819f 0000 3883 0000 387f 0000 818c 0020 ....8...8......
96b056b0: 4801 530d 8041 0014 3860 0000 4800 000c H.S..A..8`..H...
96b056c0: 3c60 8000 3863 4005 8001 0048 3821 0040 <`..8c@....H8!.@
96b056d0: 7c08 03a6 bbc1 fff8 4e80 0020 7c08 02a6 |.......N.. |...
96b056e0: bfa1 fff4 3ba3 0000 3bc4 0000 9001 0008 ....;...;.......
96b056f0: 9421 ffb0 819d 0000 818c 00bc 4801 52c1 .!..........H.R.
96b05700: 8041 0014 7c7f 1b79 4182 0078 801d 001c .A..|..yA..x....
96b05710: 2800 0000 4182 003c 7fe3 fb78 819f 0000 (...A..<...x....
96b05720: 818c 00d8 4801 5299 8041 0014 7c64 1b78 ....H.R..A..|d.x
96b05730: 807d 001c 38a1 0038 8183 0000 818c 0028 .}..8..8.......(
96b05740: 4801 527d 8041 0014 2c03 0000 4082 001c H.R}.A..,...@...
96b05750: 387f 0000 3881 0038 819f 0000 818c 0058 8...8..8.......X
96b05760: 4801 525d 8041 0014 8001 0038 3860 0000 H.R].A.....88`..
96b05770: 901e 0000 8001 003c 901e 0004 4800 000c .......<....H...
96b05780: 3c60 8000 3863 4005 8001 0058 3821 0050 <`..8c@....X8!.P
96b05790: 7c08 03a6 bba1 fff4 4e80 0020 7c08 02a6 |.......N.. |...
96b057a0: bfa1 fff4 3ba3 0000 3bc4 0000 9001 0008 ....;...;.......
96b057b0: 9421 ffb0 819d 0000 818c 00bc 4801 5201 .!..........H.R.
96b057c0: 8041 0014 7c7f 1b79 4182 0078 801d 001c .A..|..yA..x....
96b057d0: 2800 0000 4182 003c 7fe3 fb78 819f 0000 (...A..<...x....
96b057e0: 818c 00d8 4801 51d9 8041 0014 7c64 1b78 ....H.Q..A..|d.x
96b057f0: 807d 001c 38a1 0038 8183 0000 818c 0030 .}..8..8.......0
96b05800: 4801 51bd 8041 0014 2c03 0000 4082 001c H.Q..A..,...@...
96b05810: 387f 0000 3881 0038 819f 0000 818c 0040 8...8..8.......@
96b05820: 4801 519d 8041 0014 8001 0038 3860 0000 H.Q..A.....88`..
96b05830: 901e 0000 8001 003c 901e 0004 4800 000c .......<....H...
96b05840: 3c60 8000 3863 4005 8001 0058 3821 0050 <`..8c@....X8!.P
96b05850: 7c08 03a6 bba1 fff4 4e80 0020 7c08 02a6 |.......N.. |...
96b05860: bfc1 fff8 3bc3 0000 3be4 0000 9001 0008 ....;...;.......
96b05870: 9421 ffb0 819e 0000 818c 00bc 4801 5141 .!..........H.QA
96b05880: 8041 0014 2803 0000 4182 006c 387e 0000 .A..(...A..l8~..
96b05890: 3881 0040 819e 0000 818c 0098 4801 5121 8..@........H.Q!
96b058a0: 8041 0014 387e 0000 3881 0038 819e 0000 .A..8~..8..8....
96b058b0: 818c 0094 4801 5109 8041 0014 8001 0038 ....H.Q..A.....8
96b058c0: 3860 0000 901f 0000 8001 003c 901f 0004 8`.........<....
96b058d0: 809f 0000 8001 0040 7c04 0214 901f 0008 .......@|.......
96b058e0: 809f 0004 8001 0044 7c04 0214 901f 000c .......D|.......
96b058f0: 4800 000c 3c60 8000 3863 4005 8001 0058 H...<`..8c@....X
96b05900: 3821 0050 7c08 03a6 bbc1 fff8 4e80 0020 8!.P|.......N..
96b05910: 7c08 02a6 bfa1 fff4 3ba3 0000 3bc4 0000 |.......;...;...
96b05920: 9001 0008 9421 ffb0 819d 0000 818c 00bc .....!..........
96b05930: 4801 508d 8041 0014 7c7f 1b79 4182 0078 H.P..A..|..yA..x
96b05940: 801d 001c 2800 0000 4182 003c 7fe3 fb78 ....(...A..<...x
96b05950: 819f 0000 818c 00d8 4801 5065 8041 0014 ........H.Pe.A..
96b05960: 7c64 1b78 807d 001c 7fc5 f378 8183 0000 |d.x.}.....x....
96b05970: 818c 0018 4801 5049 8041 0014 2c03 0000 ....H.PI.A..,...
96b05980: 4082 002c 801e 0000 3881 0038 387f 0000 @..,....8..88...
96b05990: 9001 0038 801e 0004 9001 003c 819f 0000 ...8.......<....
96b059a0: 818c 004c 4801 5019 8041 0014 3860 0000 ...LH.P..A..8`..
96b059b0: 4800 000c 3c60 8000 3863 4005 8001 0058 H...<`..8c@....X
96b059c0: 3821 0050 7c08 03a6 bba1 fff4 4e80 0020 8!.P|.......N..
96b059d0: 3860 0000 4e80 0020 7c08 02a6 bfa1 fff4 8`..N.. |.......
96b059e0: 3ba3 0000 3bc4 0000 9001 0008 9421 ffb0 ;...;........!..
96b059f0: 819d 0000 818c 00bc 4801 4fc5 8041 0014 ........H.O..A..
96b05a00: 7c7f 1b79 4182 0078 801d 001c 2800 0000 |..yA..x....(...
96b05a10: 4182 003c 7fe3 fb78 819f 0000 818c 00d8 A..<...x........
96b05a20: 4801 4f9d 8041 0014 7c64 1b78 807d 001c H.O..A..|d.x.}..
96b05a30: 7fc5 f378 8183 0000 818c 0020 4801 4f81 ...x....... H.O.
96b05a40: 8041 0014 2c03 0000 4082 002c 801e 0000 .A..,...@..,....
96b05a50: 3881 0038 387f 0000 9001 0038 801e 0004 8..88......8....
96b05a60: 9001 003c 819f 0000 818c 003c 4801 4f51 ...<.......