Signed-off-by: Pablo Lezaeta Reyes <prflr88@gmail.com>
This commit is contained in:
Pablo Lezaeta Reyes 2017-09-27 00:10:03 -03:00
commit 60d1b2c293
No known key found for this signature in database
GPG Key ID: 9C928FDB51F562A7
199 changed files with 34649 additions and 0 deletions

47
BLURB Normal file
View File

@ -0,0 +1,47 @@
hfsutils - tools for reading and writing Macintosh HFS volumes
Copyright (C) 1996-1998 Robert Leslie
$Id: BLURB,v 1.1 1998/04/11 08:26:52 rob Exp $
===============================================================================
What is this?
HFS is the "Hierarchical File System" used on modern Macintosh computers.
With this package, you can read and write Macintosh-formatted media such as
floppy disks, CD-ROMs, and SCSI hard disks on most UNIX platforms. You can
also format raw media into an HFS volume.
This package contains a number of different tools:
* Several command-line programs (hmount, hls, hcopy, et al.)
* A Tk-based front-end for browsing and copying files through a
variety of transfer modes (MacBinary, BinHex, text, etc.)
* A Tcl package and interface for scriptable access to volumes
* A C library for low-level access to volumes
How is this different from other HFS packages?
This package attempts to provide a portable, free implementation of
routines for accessing HFS volumes. It is implemented as a set of user-level
tools to provide maximum portability.
The command-line programs are intended to be used in the same vein as the
Mtools command-line programs used to access MS-DOS filesystems.
The graphical front-end provides point-and-click access to Macintosh
volumes, which is often more convenient than the command line.
The Tcl interface offers a scriptable HFS "shell" that is more efficient
than the external command-line programs and allows for greater
extensibility.
The C library can be linked with other programs wanting to manipulate
Macintosh files in their native format. For example, an implementation of
the Macintosh Resource Manager could be built on top of this library to
provide seamless access to data objects contained within the resource forks
of Macintosh files.
===============================================================================

482
CHANGES Normal file
View File

@ -0,0 +1,482 @@
hfsutils - tools for reading and writing Macintosh HFS volumes
Copyright (C) 1996-1998 Robert Leslie
$Id: CHANGES,v 1.14 1998/11/02 22:08:20 rob Exp $
===============================================================================
Version 3.2.6
* Added casts and made other changes to satisfy fussy signed/unsigned
compilers.
* Fixed a problem in which volumes were not marked as "cleanly unmounted,"
causing unnecessary scavenging to occur when the volume is mounted again.
* Fixed a problem where scavenging failed to mark all extents from the final
B*-tree node.
* Added a simple next-CNID verification to scavenging.
* Introduced a flags parameter to hfs_format(); new HFS_OPT_2048 format
option ensures 2048-byte physical-block file boundaries, compatible with
hybrid ISO 9660 schemes.
* New HFS_OPT_NOCACHE mount option inhibits use of libhfs' internal block
cache, useful for RAM file systems or systems/circumstances where the
cache may decrease performance.
* New HFS_OPT_ZERO format/mount option forces all allocated blocks to be
zero-initialized before use, for systems/circumstances in which blocks
may otherwise contain random data. (This is primarily a security feature
with a performance cost.)
Version 3.2.5
* Miscellaneous internal `const' and other minor changes.
Version 3.2.4
* Fixed a problem with the handling of catalog and extents clump sizes
(again; first fixed in 1.15b but re-introduced in 3.0b1, alas.)
* Modified `configure' once again to search for tcl.h/tk.h header files.
* Changed the OS interface to operate on full block rather than byte
offsets.
* Moved the 800K size check from hfs_format() into v_geometry().
Version 3.2.3
* Fixed a problem with the B*-tree node splitting code. This could have
caused the libhfs routines to crash under some rare circumstances.
Version 3.2.2
* Added support for "blessing" the MacOS System Folder by means of a new
field in the hfsvolent struct. A new option to `hattrib' can be used to
set this field, as can a new "bless" Tcl volume command.
* Modified `configure' to use existing Tcl/Tk configuration information
rather than reconstruct it.
Version 3.2.1
* Fixed a minor potential problem where BinHex translation might fail to
recognize the hqx header.
Version 3.2
* Fixed a problem determining medium sizes under unusual conditions.
* Modified MDB `drVCSize', `drVBMCSize', and `drCtlCSize' to new
Sequoia-supporting `drEmbedSigWord' and `drEmbedExtent'.
Version 3.1.1
* Fixed a problem related to partition locations on large media.
* Fixed a problem with suid.c on some systems.
* Fixed a problem with font selection in `xhfs'.
* Changed copyouts not to append `.txt' to text files if the filename
already contains a period.
* Fixed a few other minor problems.
Version 3.1
* `hmount' and friends now properly handle relative pathnames, even if
the current directory changes.
* Enhanced API for managing partitions: hfs_zero() will create a new,
empty partition map on any medium. hfs_mkpart() will create a new HFS
partition (if space allows) in the map. hfs_nparts() will return the
number of HFS partitions currently existing on the medium.
* hfs_mount() and hfs_format() are now more strict with the partition
number passed to them; previously this number was ignored if the medium
was not partitioned. Now the partition _must_ exist, or else 0 can be
passed to ignore any partitions and select the entire medium.
* Changed the API for hfs_create(); this routine now returns an open file
reference upon successful creation.
* Added bad block sparing to hfs_format(). This routine now requires two
additional arguments specifying a list of block numbers which are
defective on the physical medium and should be mapped out of use.
* Character set translation is now performed as well as end-of-line
translation in the "text" transfer mode. The routines convert MacOS
Standard Roman to equivalent (or near-equivalent) Latin-1 (ISO 8859-1)
sequences and vice versa. It should be noted however that these
translations are NOT reversible for all characters.
* Fixed a bug in xhfs.tcl which failed to include the helper `ctime'
procedure (fixed in hfs.tcl) after it was removed from tclhfs.c.
* Further librsrc development.
Version 3.0b2
* Changed the block cache mechanism so that consecutive blocks are read
and written in single chunks, significantly improving performance.
* Improved the efficiency of the internal routines for searching B*-trees
by reducing the number of times the record keys are unpacked from their
external format.
Version 3.0b1
* Package is now configured automatically via GNU `configure' script.
* Numerous internal changes to support automatic configuration and improve
portability, as well as reduce code size.
* Bug fix: the alternate MDB was sometimes written to the wrong location
on non-partitioned media.
* Bug fix: the Extents Overflow file could become corrupted under some
circumstances in which a heavily fragmented file is removed.
* Bug fix: it was possible for the volume allocation routine to become
caught in an infinite loop.
* Significant librsrc development. The library can now read and return
resources to an application, but cannot create or modify them. The
library can be used with or without libhfs.
* hfs_mount() now honors the software volume lock bit and makes the volume
read-only accordingly.
* Added a new hfs_vsetattr() routine to allow some volume attributes to
be modified.
* Added support for partition data blocks that do not start at the
beginning of a partition.
Version 2.1
* Further hfsck development.
* Physical blocks from the volume are now cached by the library. This
should dramatically improve performance of the programs on some systems.
* Modified the hfsvolent and hfsdirent structures to include several new
fields. The hfs_vstat(), hfs_stat(), and hfs_setattr() functions now
manipulate the new fields. Note that hfsdirent now includes a separate
union structure for files and directories.
* Fixed a problem on some systems with `xhfs' that caused it to terminate
with the message `Error: can't read "data": no such variable'. The
problem was caused by the inability to parse the system's `df' command
output.
Version 2.0
* Renamed hfs_fork() to hfs_setfork(), and added hfs_getfork().
* Modified all programs to be setuid-aware. Setuid privileges are only
engaged when opening devices as HFS volumes; this can be useful to limit
access to and/or help protect the structural integrity of HFS volumes,
for example by installing the hfsutils programs setgid. N.B. This
implementation may not be completely portable, and is isolated to the
new source file `./suid.c'.
* First non-beta release.
Version 1.19b
* Fixed a problem which prevented large volumes from being properly
formatted by hfs_format(). This should also allow the library to
correctly manipulate large volumes in certain other cases.
* Adapted the code to work with Tcl 7.6 and Tk 4.2.
* Added an HFS globbing interface to Tcl, and extended the `hfs' shell
to use it.
* Modified globbing routine to ignore Finder-invisible files.
* Rewrote `hls' and `hdir'; many UNIX-like options are now available.
* Updated the general documentation.
* Continued development of `hfsck'.
Version 1.18b
* Resolved many signed/unsigned argument passing conflicts throughout the
code. It should now compile cleanly even on very strict systems.
* Changed the interface for hfs_read() and hfs_write() to accept a void *
buffer pointer rather than demanding char *.
* Made volume file locking optional for systems that don't support it.
* Included a few other portability fixes for AIX and BeOS.
Version 1.17b
* Completed the implementation for `hattrib'; HFS file attributes (type,
creator, invisible/locked) can now be changed from the command line.
* Fixed an off-by-one error in computing catalog record key lengths.
* Fixed a problem with backslash-quoted braces during globbing.
* Improved Makefile handling.
* Regularized the handling of the volume-unmounted flag.
* Streamlined the internal and external interface header files.
* Added a `parid' field to the hfsdirent structure.
* Updated libhfs documentation.
* Implemented a better error message reporting format involving pathnames.
Version 1.16b
* Improved the robustness of the HFS path resolution routine.
* Fixed hfs_rename() to better detect the validity of destination paths.
* Changed mount-time scavenging only to mark bits in the volume bitmap,
not clear them. This reduces the risk of causing further damage to a
corrupt disk, leaving serious recovery to more advanced tools.
* Added file locking to hfs_mount() to prevent concurrent processes from
potentially creating inconsistencies in a volume.
* Added a new argument to hfs_mount() for specifying mount flags. This now
allows a volume to be explicitly mounted read-only, read-write, or don't
care (whichever is available).
* Improved detection and handling of multiple same-device mounts by a single
process.
* Improved error message reporting for all programs.
* Fixed a problem where hrenaming a volume caused it to become inaccessible
until it was hmounted again.
Version 1.15b
* Increased buffer size for native HFS-to-HFS copies to increase
performance.
* Fixed a problem verifying the existence of directory threads.
* Fixed a problem with the handling of catalog and extents clump sizes.
Version 1.14b
* The command-line programs now support filename globbing; see hfsutils(1)
for syntax details.
* File threads are now managed properly when the associated file is deleted,
moved, or renamed. However, there is no mechanism yet to explicitly create
or remove threads, or to use them in catalog searches.
* The volume bitmap is now reconstructed from the catalog and extents files
when a volume is mounted that was not previously cleanly unmounted.
* Directories may now be deleted recursively using `xhfs'.
* BinHex and MacBinary header fork size validation limitations have been
relaxed. (MacBinary spec suggested 0x007fffff ~= 8MB as maximum length?)
* Volumes are now flushed automatically by `xhfs' every 30 seconds to
reduce risk of accidental data loss.
* Begun work on `hfsck', a program to verify and correct HFS volume
consistency.
* Begun work on `librsrc', a library for manipulating the resource forks
of HFS files.
Version 1.13b
* Fixed two bad extent record key sorting bugs; these could have caused
serious problems on certain fragmented volumes.
* Fixed a problem related to MacOS default file clump size semantics.
* Implemented recursive directory copies in `xhfs'.
* Files and directories may now be renamed with a mere change of case.
* Multiple files may now be moved with `hrename'.
* A UNIX pathname of "-" in `hcopy' may now be used to mean stdin or stdout
when used as the source or destination target, respectively.
Version 1.12b
* Fix to allow mounting of some miscreant partitioned media.
* Increased copyin/copyout buffer sizes for better performance.
* Implemented -a for `hcopy' (automatic transfer mode selection.)
* HFS timestamps are now relative to the current time zone.
Version 1.11b
* UNIX-to-HFS BinHex transfers have been implemented. All transfer modes
are now fully implemented.
* The overall BinHex implementation now uses the stdio library for
somewhat better performance.
* New libhfs routines: hfs_setattr(), hfs_fsetattr() for changing file
and directory attributes (timestamps, type/creator, flags).
* The copyin routines now update the relevant file information (timestamps,
flags) for MacBinary and BinHex transfers.
* The `hvol' command now provides better output.
* Modified the installation procedure; separate targets now build and
install the separate components of the package.
* Fixed a bug in HFS filename sorting which affects the search routines;
filenames are now sorted precisely according to MacOS idiosyncrasies.
* Begun work on (but still unimplemented): hattrib, filename globbing.
Version 1.10b
* Fixed a serious bug in directory record updates; directories with names
longer than 21 characters could get corrupted.
* Implemented hfs_rename() and eliminated hfs_move(); functionality for
the latter has been included in the former.
* Added an `hrename' command. Minor changes to hcwd.c to cope with
volume name or cwd path changes.
* Minor changes to `xhfs'. Files can now be renamed with the interface.
Version 1.9b
* Modularized the libhfs code.
* Resolved more portability issues. The code should now work regardless of
the size or endianness of the host's datatypes.
Version 1.8.1b
* Fixed some portability bugs.
Version 1.8b
* More UI enhancements to `xhfs'.
* UNIX-to-HFS MacBinary II transfers have been implemented; HFS-to-HFS
copies have been implemented. Only one transfer mode (UNIX-to-HFS BinHex)
remains unimplemented.
* Replaced `hcat' with a generic `hcopy'. All transfer modes are supported.
(But note: The -a option is not yet supported.)
* Fixed a bug in the MacBinary II encoding CRC algorithm.
* Tcl hash tables are now used to maintain open files and volumes.
* Cleaned up some of the Tcl/Tk interface to aid compatibility with
various versions.
Version 1.7b
* Many more UI enhancements to `xhfs'.
* Files can now be copied from UNIX to HFS volumes with `xhfs' using either
Text or Raw mode translation.
Version 1.6b
* Fixed a bug in the catalog manipulation routines which would allow files
and directories to be created at the same level as the root folder.
* Many UI enhancements to `xhfs'. Some minor enhancements to `hfs'.
* hfs_islocked() now returns 1 if a volume is locked (read-only).
* Extended file attributes to recognize invisible files.
Version 1.5b
* All cases of B*-tree record insertion have been completed.
* B*-tree record deletion has been implemented. Files and folders may now
be created and deleted with no limitations (other than the size of the
volume.)
* New commands: hrmdir, hdel
* File writing and truncation have been implemented.
* The library now maintains its own concept of "current volume". The last
volume to be mounted is by default current; the new functions
hfs_getvol() and hfs_setvol() can be used to get and set the current
volume, respectively. All other functions will now accept a null volume
pointer to represent the current volume.
* Absolute pathnames may now refer to (mounted) volumes other than the one
specified in the call; in this event the specified volume is ignored.
Version 1.4b
* Updated the installation procedure. The Tcl and Tk programs can now be
built and installed optionally.
* Fixed a minor bug which would cause the header node to be read just
before completing a directory read.
* Mounting the same volume more than once now returns a reference to the
same volume, and does the right thing when each reference is
independently unmounted.
* Cleaned up some of the Tcl interface to deal with multiply-referenced
volumes. `xhfs' can now deal with the same volume on both sides.
* Renamed hfs_cwdid() to hfs_getcwd(), and added hfs_setcwd().
* hfs_umount() now closes all open files and directories on the volume
before unmounting it. All external references to the volume and any
open files/directories will become invalid.
* Enabled hfs_umountall() which will effectively unmount all volumes,
invalidating all external volume and file references. This is a
catch-all that should be called before a program exits. N.B.: Errors
during volume flushing and unmounting are not reported.
Version 1.3b
* Enhanced writability: B*-tree file growth has been implemented. New
directories can be created until the disk gets full.
* Added an option to `xhfs' for creating new directories.
Version 1.2b
* Enhanced writability: B*-tree node splitting has been implemented. New
directories can be created until the catalog file gets full.
* Fixed some minor bugs in version 1.1b.
Version 1.1b
* Full read-only capability.
* Limited write capability: new directories can be created only until
a catalog node gets full.
* New volumes can be created with hfs_format().

339
COPYING Normal file
View File

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

21
COPYRIGHT Normal file
View File

@ -0,0 +1,21 @@
hfsutils - tools 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.
If you would like to negotiate alternate licensing terms, you may do
so by contacting the author: Robert Leslie <rob@mars.org>

49
CREDITS Normal file
View File

@ -0,0 +1,49 @@
hfsutils - tools for reading and writing Macintosh HFS volumes
Copyright (C) 1996-1998 Robert Leslie
$Id: CREDITS,v 1.11 1998/09/17 00:11:44 rob Exp $
===============================================================================
Author: Robert Leslie <rob@mars.org>
The HFS globbing code was inspired by similar code to perform filename
globbing in Tcl by John Ousterhout.
The code to perform BinHex encoding/decoding is based on the definition of
BinHex 4.0 as written by Peter N Lewis.
The code for `hls' is loosely based on the GNU implementation of `ls'.
Many thanks to the following people for their support and various
contributions to this project:
Howard Bergstrom <bergy@vnet.ibm.com>
Marcus Better <f96-bet@nada.kth.se>
Cees de Groot <C.deGroot@inter.nl.net>
Pat Dirks <pwd@apple.com>
Andy Fyfe <andy@hyperparallel.com>
Paul H. Hargrove <hargrove@sccm.Stanford.EDU>
George Hoffman <geh@be.com>
Jack Howarth <howarth@nitro.med.uc.edu>
Geoff Hulten <ghulten@ccs.neu.edu>
Richard C.S. Kinne <kinnerc@snymorva.cs.snymor.edu>
Marc Lebas <marc-lebas@calvanet.calvacom.fr>
Zach Leber <zach@radionics.com>
Clifford T. Matthews <ctm@ardi.com>
Markus Mayer <may@inflab.tuwien.ac.at>
Allen Pouratian <allenp@CSUA.Berkeley.EDU>
Steve Revilak <revilak@umbsky.cc.umb.edu>
Andrew Ross <andrew.ross@acm.org>
Nick Stephen <stephen@gr.osf.org>
Ray Van Tassle <rayvt@comm.mot.com>
Thomas B. White <tbwhite@hookup.net>
John Witford <jwitford@hutch.com.au>
And thanks of course to the engineers of the truly fascinating HFS filesystem
for giving me a challenge. May your extents overflow file never become so
fragmented that you cannot locate its own extents.
===============================================================================

183
INSTALL Normal file
View File

@ -0,0 +1,183 @@
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.

317
Makefile.in Normal file
View File

@ -0,0 +1,317 @@
#
# hfsutils - tools 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.in,v 1.12 1998/08/31 18:40:14 rob Exp $
#
@SET_MAKE@
src = @srcdir@
VPATH = @srcdir@
### USER CUSTOMIZATIONS FOLLOW ################################################
prefix = @prefix@
exec_prefix = @exec_prefix@
BINDEST = @bindir@
MANDEST = @mandir@
LIBDEST = @libdir@
INCDEST = @includedir@
MANEXT = 1
INSTALL = @INSTALL@
BININSTALL = @INSTALL_PROGRAM@ -m 755
LIBINSTALL = @INSTALL_DATA@
HARDLINK = ln -f
CC = @CC@
INCLUDES = @CPPFLAGS@ -Ilibhfs @TCL_INCLUDES@ @TK_INCLUDES@
DEFINES = @DEFS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
TCLLIBS = @TCL_LIB_SPEC@ @TCL_LIBS@
TKLIBS = @TK_LIB_SPEC@ @TCL_LIB_SPEC@ @TK_LIBS@
COPTS = @CFLAGS@
LDOPTS = @LDFLAGS@ -Llibhfs
### END OF USER CUSTOMIZATION #################################################
CFLAGS = $(COPTS) $(INCLUDES) $(DEFINES)
LDFLAGS = $(LDOPTS)
###############################################################################
TARGETS = $(CLITARGETS) $(TCLTARGETS) $(TKTARGETS)
CLITARGETS = hattrib hcd hcopy hdel hdir hformat hls hmkdir hmount hpwd \
hrename hrmdir humount hvol
TCLTARGETS = hfssh hfs
TKTARGETS = xhfs
LIBHFS = libhfs/libhfs.a
INCHFS = libhfs/hfs.h
LIBRSRC = librsrc/librsrc.a
INCRSRC = librsrc/rsrc.h
HFSUTIL = hfsutil
HFSCK = hfsck/hfsck
LINUX = linux/mkfs.hfs linux/fsck.hfs linux/kernel/hfs.o
SUBDIRS = hfsck linux test
ACSUBDIRS = @subdirs@
GENERALDOCS = hfsutils.1
CLIDOCS = hattrib.1 hcd.1 hcopy.1 hdel.1 hdir.1 hformat.1 hls.1 \
hmkdir.1 hmount.1 hpwd.1 hrename.1 hrmdir.1 humount.1 hvol.1
TCLDOCS = hfssh.1 hfs.1
TKDOCS = xhfs.1
CLIOBJS = hattrib.o hcd.o hcopy.o hdel.o hformat.o hls.o hmkdir.o \
hmount.o hpwd.o hrename.o hrmdir.o humount.o hvol.o
UTILOBJS = crc.o binhex.o copyin.o copyout.o charset.o \
darray.o dlist.o dstring.o glob.o suid.o version.o
###############################################################################
all :: @MAKE_TARGETS@
all_cli :: $(CLITARGETS)
all_tcl :: $(TCLTARGETS)
all_tk :: $(TKTARGETS)
all_lib :: $(LIBHFS) $(LIBRSRC)
check :: all
@if [ -f hfs ]; then \
cd test && $(MAKE) && \
echo "Self-tests passed."; \
else \
echo "Self-tests only available if configured --with-tcl."; \
fi
install :: @INSTALL_TARGETS@
install_cli :: all_cli
$(BININSTALL) $(HFSUTIL) "$(BINDEST)/."
for file in $(CLITARGETS); do \
$(HARDLINK) "$(BINDEST)/$(HFSUTIL)" "$(BINDEST)/$$file"; \
done
rm -f "$(BINDEST)/$(HFSUTIL)"
for file in $(GENERALDOCS) $(CLIDOCS); do \
$(LIBINSTALL) doc/man/$$file \
"$(MANDEST)/man$(MANEXT)/`basename $$file .1`.$(MANEXT)"; \
done
install_tcl :: all_tcl
for file in $(TCLTARGETS); do \
$(BININSTALL) $$file "$(BINDEST)/."; \
done
if [ -f "$(BINDEST)/hfs" ]; then \
sed -e '1d' "$(BINDEST)/hfs" > "$(BINDEST)/hfs.new"; \
$(BININSTALL) "$(BINDEST)/hfs.new" "$(BINDEST)/hfs"; \
rm -f "$(BINDEST)/hfs.new"; \
fi
for file in $(TCLDOCS); do \
$(LIBINSTALL) doc/man/$$file \
"$(MANDEST)/man$(MANEXT)/`basename $$file .1`.$(MANEXT)"; \
done
install_tk :: all_tk
for file in $(TKTARGETS); do \
$(BININSTALL) $$file "$(BINDEST)/."; \
done
for file in $(TKDOCS); do \
$(LIBINSTALL) doc/man/$$file \
"$(MANDEST)/man$(MANEXT)/`basename $$file .1`.$(MANEXT)"; \
done
install_lib :: all_lib
cd libhfs && $(MAKE) install
cd librsrc && $(MAKE) install
again :: clean all
depend ::
for dir in $(ACSUBDIRS) $(SUBDIRS); do \
(cd $$dir && $(MAKE) depend); \
done
( sed -n '1,/^### DEPEND/p' Makefile.in; \
echo; \
$(CC) -MM $(INCLUDES) $(DEFINES) *.c; \
) > Makefile.in.new
mv -f Makefile.in.new Makefile.in
clean ::
for dir in $(ACSUBDIRS) $(SUBDIRS); do \
(cd $$dir && $(MAKE) clean); \
done
rm -f $(TARGETS) *.o gmon.* core
rm -f $(HFSUTIL) xhfs.c
distclean :: clean
for dir in $(ACSUBDIRS); do \
(cd $$dir && $(MAKE) distclean); \
done
rm -f config.status config.cache config.log config.h
rm -f hfsck/Makefile linux/Makefile Makefile
maintainer-clean :: distclean
for dir in . $(ACSUBDIRS); do \
rm -f $$dir/config.h.in $$dir/configure; \
done
dist ::
for dir in . $(ACSUBDIRS); do \
(cd $$dir && $(MAKE) config.h.in configure); \
done
$(MAKE) distclean
###############################################################################
Makefile: config.status
./config.status && touch .stamp/config.h
.stamp/config.h: config.status
./config.status && touch .stamp/config.h
config.status: .stamp/configure .stamp/config.h.in Makefile.in
./config.status --recheck
.stamp/configure: configure.in
autoconf && touch .stamp/configure
.stamp/config.h.in: configure.in acconfig.h
autoheader && touch .stamp/config.h.in
###############################################################################
$(LIBHFS) ::
cd libhfs && $(MAKE)
$(LIBRSRC) ::
cd librsrc && $(MAKE)
$(HFSCK) :: $(LIBHFS)
cd hfsck && $(MAKE)
$(LINUX) :: $(LIBHFS)
cd linux && $(MAKE)
$(HFSUTIL): $(LIBHFS) hfsutil.o hcwd.o $(CLIOBJS) $(UTILOBJS) $(LIBOBJS)
$(CC) $(LDFLAGS) hfsutil.o hcwd.o \
$(CLIOBJS) $(UTILOBJS) \
-lhfs $(LIBS) $(LIBOBJS) -o $@
$(CLITARGETS): $(HFSUTIL)
-$(HARDLINK) $(HFSUTIL) $@
hfssh: $(LIBHFS) hfssh.o tclhfs.o $(UTILOBJS) $(LIBOBJS)
$(CC) $(LDFLAGS) hfssh.o tclhfs.o $(UTILOBJS) \
-lhfs $(LIBS) $(TCLLIBS) $(LIBOBJS) -o $@
hfs: hfs.tcl hfssh
( echo "#!./hfssh"; \
echo "#! /bin/sh"; \
echo "# Start hfssh ... \\"; \
echo 'exec hfssh "$$0" "$$@"'; \
echo; \
cat hfs.tcl; \
) > $@
chmod a+x $@
xhfs.c: xhfs.tcl
( echo '# include "xhfs.h"'; \
echo; \
echo "char xhfs[] ="; \
sed -e 's|^[ ]*||' -e 's|^#.*||' -e '/^$$/d' \
-e 's| *| |g' \
-e 's|[\\"]|\\&|g' -e 's|.*|"&\\n"|' xhfs.tcl; \
echo ";"; \
) > $@
xhfs: $(LIBHFS) hfswish.o xhfs.o tclhfs.o $(UTILOBJS) $(LIBOBJS)
$(CC) $(LDFLAGS) hfswish.o xhfs.o tclhfs.o $(UTILOBJS) \
-lhfs $(LIBS) $(TKLIBS) $(LIBOBJS) -o $@
### DEPENDENCIES FOLLOW #######################################################
binhex.o: binhex.c config.h binhex.h crc.h
charset.o: charset.c config.h charset.h
copyin.o: copyin.c config.h libhfs/hfs.h libhfs/data.h copyin.h \
charset.h binhex.h crc.h
copyout.o: copyout.c config.h libhfs/hfs.h libhfs/data.h copyout.h \
charset.h binhex.h crc.h
crc.o: crc.c config.h crc.h
darray.o: darray.c config.h darray.h
dlist.o: dlist.c config.h dlist.h
dstring.o: dstring.c config.h dstring.h
glob.o: glob.c config.h dlist.h dstring.h libhfs/hfs.h glob.h
hattrib.o: hattrib.c config.h libhfs/hfs.h hcwd.h hfsutil.h hattrib.h
hcd.o: hcd.c config.h libhfs/hfs.h hcwd.h hfsutil.h hcd.h
hcopy.o: hcopy.c config.h libhfs/hfs.h hcwd.h hfsutil.h hcopy.h \
copyin.h copyout.h
hcwd.o: hcwd.c config.h libhfs/hfs.h hcwd.h
hdel.o: hdel.c config.h libhfs/hfs.h hcwd.h hfsutil.h hdel.h
hformat.o: hformat.c config.h libhfs/hfs.h hcwd.h hfsutil.h suid.h \
hformat.h
hfssh.o: hfssh.c config.h tclhfs.h suid.h
hfsutil.o: hfsutil.c config.h libhfs/hfs.h hcwd.h hfsutil.h suid.h \
glob.h version.h hattrib.h hcd.h hcopy.h hdel.h hformat.h hls.h \
hmkdir.h hmount.h hpwd.h hrename.h hrmdir.h humount.h hvol.h
hfswish.o: hfswish.c config.h tclhfs.h xhfs.h suid.h images.h \
images/macdaemon.xbm images/macdaemon_mask.xbm images/stop.xbm \
images/caution.xbm images/note.xbm images/floppy.xbm \
images/harddisk.xbm images/cdrom.xbm images/floppy_mask.xbm \
images/harddisk_mask.xbm images/cdrom_mask.xbm images/sm_floppy.xbm \
images/sm_harddisk.xbm images/sm_cdrom.xbm images/folder.xbm \
images/document.xbm images/application.xbm images/folder_mask.xbm \
images/document_mask.xbm images/application_mask.xbm \
images/sm_folder.xbm images/sm_document.xbm images/sm_application.xbm \
images/help.xbm images/padlock.xbm
hls.o: hls.c config.h libhfs/hfs.h hcwd.h hfsutil.h darray.h dlist.h \
dstring.h hls.h
hmkdir.o: hmkdir.c config.h libhfs/hfs.h hcwd.h hfsutil.h hmkdir.h
hmount.o: hmount.c config.h libhfs/hfs.h hcwd.h hfsutil.h suid.h \
hmount.h
hpwd.o: hpwd.c config.h libhfs/hfs.h hcwd.h hfsutil.h hpwd.h
hrename.o: hrename.c config.h libhfs/hfs.h hcwd.h hfsutil.h hrename.h
hrmdir.o: hrmdir.c config.h libhfs/hfs.h hcwd.h hfsutil.h hrmdir.h
humount.o: humount.c config.h libhfs/hfs.h hcwd.h hfsutil.h humount.h
hvol.o: hvol.c config.h libhfs/hfs.h hcwd.h hfsutil.h hvol.h
strdup.o: strdup.c config.h
strerror.o: strerror.c config.h
strstr.o: strstr.c config.h
strtol.o: strtol.c config.h
suid.o: suid.c config.h suid.h
tclhfs.o: tclhfs.c config.h tclhfs.h libhfs/hfs.h glob.h copyin.h \
copyout.h charset.h suid.h version.h
version.o: version.c version.h

132
README Normal file
View File

@ -0,0 +1,132 @@
hfsutils - tools for reading and writing Macintosh HFS volumes
Copyright (C) 1996-1998 Robert Leslie
$Id: README,v 1.10 1998/09/08 18:51:51 rob Exp $
===============================================================================
NOTES ON THIS RELEASE
This release uses GNU autoconf to automatically configure the software
for installation and use on your system. This means you should not have
to modify any files by hand to get the software to compile -- if you do,
please let the author know so it can be fixed.
For general installation instructions, please read the `INSTALL' file.
There are a few special options you can give the `configure' program that
you should know about:
--with-tcl build the Tcl/Tk components
--with-tk build the Tk-based X interface `xhfs'
--disable-cli do not build or install the command-line utils
--enable-devlibs enable installation of the developer libraries
To build the Tcl tools `hfssh' and `hfs', you must use `--with-tcl'.
To build the X interface `xhfs', you must use `--with-tcl --with-tk'.
In order to build the Tcl tools you must have Tcl 7.6 or newer already
installed on your system. To build the X interface, you must have Tk 4.2
or newer installed as well.
If `configure' is unable to locate your Tcl or Tk installation, you will
have to give it a hint. It looks for the files `tclConfig.sh' and
`tkConfig.sh' (respectively) which contain all the details about your
configuration; these files were created when Tcl/Tk was installed on your
system.
To help `configure' find these files, you can specify a directory name on
the command line. For example:
./configure --with-tcl=/usr/share/tcl --with-tk=/usr/share/tk
When in doubt, wait and see if `configure' complains.
By default, the command-line utilities (hmount, hls, hcopy, etc.) are
always built and installed. If you don't want them, use `--disable-cli'.
If you want to install the developer libraries (libhfs.a, librsrc.a, and
associated header files) as well as the programs, use `--enable-devlibs'.
The libraries are not installed by default.
The `INSTALL' file contains the rest of the details you will need to
compile and install the software. Please read it!
===============================================================================
NOTES ON "SETUID" INSTALLATION
Although the author has made some effort to make the programs in this
package somewhat setuid-safe, none are intended to be installed in such a
manner, and you do so at your own risk!
Specifically, installing the programs setuid root is a bad idea, as it will
allow anyone to attempt to open (or format) any file as an HFS volume,
disregarding the normal UNIX file permission checks.
A better idea is to modify the permissions on the necessary device files to
allow access to appropriate users. For example, if you make your floppy
device group-writable to a special group of floppy users, then only those
users will be able to access an inserted floppy disk and nothing needs to
be made setuid.
Here is an example:
% ls -l /dev/fd0 /usr/local/bin/xhfs
brw-rw---- 1 root floppy 2, 0 Sep 17 13:51 /dev/fd0
-rwxr-xr-x 1 root staff 339874 Jan 17 20:18 /usr/local/bin/xhfs
% grep floppy /etc/group
floppy:*:25:rob,thigpen
This configuration permits users `rob' and `thigpen' read/write access to
the floppy device, without needing to make any programs setuid.
Another possibility is to make some of the programs in this package setgid
(NOT setuid) to a similar group which has access to the necessary devices.
This avoids the need to add specific users to a group, since it allows
anyone to access the devices using the utilities, while still maintaining
the integrity of the data on the devices since they are not world-writable.
(A world-writable device lends itself to the possibility that someone may
corrupt some portion of it by other means and render an HFS volume
unusable, whereas limiting access only through the utilities means the
volume is unlikely to be corrupted under normal usage -- although note that
since HFS itself does not provide any file permission structure, anyone may
still modify the HFS volume in any way. The only protection here is that
the modifications must be made in an HFS-compatible way, so that the
possibility of corruption is reduced.)
Here is another example:
% ls -l /dev/fd0 /usr/local/bin/xhfs
brw-rw---- 1 root floppy 2, 0 Sep 17 13:51 /dev/fd0
-rwxr-sr-x 1 root floppy 339874 Jan 17 20:18 /usr/local/bin/xhfs
% grep floppy /etc/group
floppy:*:25:
In this case, only setgid `floppy' programs (such as `/usr/local/bin/xhfs')
are permitted access to the floppy device.
To summarize: it is suggested that the utilities NOT be installed setuid or
setgid. It is possible to install the utilities setgid as described above,
but it is NOT recommended that the utilities be installed setuid root under
any circumstances.
===============================================================================
CONTACTING THE AUTHOR
Please see the `COPYRIGHT' file for copyright and warranty information.
Send comments, bug reports, suggestions, patches, etc. to:
* Robert Leslie <rob@mars.org>
See also the HFS Utilities home page on the Web:
* http://www.mars.org/home/rob/proj/hfs/
===============================================================================

79
TODO Normal file
View File

@ -0,0 +1,79 @@
hfsutils - tools for reading and writing Macintosh HFS volumes
Copyright (C) 1996-1998 Robert Leslie
$Id: TODO,v 1.14 1998/11/02 22:08:22 rob Exp $
===============================================================================
General to-do items (aka bugs):
libhfs
* support HFS+ (aka Sequoia, Extended Format)
* don't allow reads from spared blocks
* further improve efficiency of b*-tree searches?
* concurrency considerations: opening same file multiple times;
performing directory manipulations on open files
* b*-tree record balancing?
* smarter block allocation algorithm
* volume full: hfs_write() should return bytes written < len, return -1
on next call?
* seek beyond end of file?
* touch directory timestamps on file updates?
* improve efficiency of bitmap operations
* improve efficiency of search operations
* CNID wrapping?
* bad block sparing by physical block
librsrc
* determine resource sizes without reading them
* support writability
hfsck
* modify libhfs to support low-level grubbing
command-line tools
* preserve timestamps (-p) for hcopy
* recursive hcopy (-r)
* allow hformat to create files and/or set size?
* write Linux utilities mkfs.hfs, fsck.hfs
* eliminate ftruncate()
* more flags for hdel (-i, -r, -f)
* glob :*:foo correctly
* glob hcopy destination HFS path?
* formalize hdisk.pl into the distribution
xhfs
* open arbitrary partitions
* rename volumes
* change file type/creator
* more support for other platforms (correct device defaults; df output)
* graphical partition map editor?
* recursive copy: map illegal directory name chars
copyin/copyout
* finish/fix timestamp preservation
* revisit buffer sizes
* remember src/dst filenames (for preserve/delete)
* allow name mangling to be optional
* don't unconditionally clobber
* delete incomplete files after failed transfers
* AppleSingle, Netatalk-/CAP-style AppleDouble?
Future wish-list:
* raw SCSI access for hideous platforms
* partitioning utility
* defragmenting utility
Acknowledged limitations:
* null characters (ASCII 0x00) not supported in filenames
* partition maps not managed with A/UX support

53
acconfig.h Normal file
View File

@ -0,0 +1,53 @@
/*
* hfsutils - tools 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: acconfig.h,v 1.5 1998/04/11 08:26:53 rob Exp $
*/
/*****************************************************************************
* Definitions selected automatically by `configure' *
*****************************************************************************/
@TOP@
/* Define if you want to enable diagnostic debugging support. */
#undef DEBUG
/* Define if your system has sys_errlist[] and sys_nerr. */
#undef HAVE_SYS_ERRLIST
@BOTTOM@
/*****************************************************************************
* End of automatically configured definitions *
*****************************************************************************/
# ifndef HAVE_STRDUP
char *strdup(const char *);
# endif
# ifndef HAVE_STRERROR
char *strerror(int);
# endif
# ifndef HAVE_STRSTR
char *strstr(const char *, const char *);
# endif
# ifndef HAVE_STRTOL
long strtol(const char *, char **, int);
# endif

616
binhex.c Normal file
View File

@ -0,0 +1,616 @@
/*
* hfsutils - tools 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: binhex.c,v 1.11 1998/09/18 22:56:22 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# else
int dup(int);
# endif
# include <stdio.h>
# include <string.h>
# include <errno.h>
# include "binhex.h"
# include "crc.h"
const char *bh_error = "no error";
extern int errno;
# define ERROR(code, str) (bh_error = (str), errno = (code))
static FILE *file; /* input/output file */
static char line[67]; /* ASCII line buffer */
static int lptr; /* next char in line buffer */
static int state86; /* 8->6 encoding state */
static unsigned char lastch; /* last encoded data byte */
static int runlen; /* runlength of last data byte */
static unsigned short crc; /* incremental CRC word */
static const
unsigned char zero[2] = { 0, 0 };
static const
char hqxheader[] = "(This file must be converted with BinHex 4.0)\n";
static const
char enmap[] = "!\"#$%&'()*+,-012345689@ABCDEFGHI"
"JKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
static const
signed char demap[256] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, -1, -1, 0, 0, -1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
-1, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 0, 0,
14, 15, 16, 17, 18, 19, 20, 0,
21, 22, 0, 0, 0, 0, 0, 0,
23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 0,
38, 39, 40, 41, 42, 43, 44, 0,
45, 46, 47, 48, 0, 0, 0, 0,
49, 50, 51, 52, 53, 54, 55, 0,
56, 57, 58, 59, 60, 61, 0, 0,
62, 63, 64, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
# define HEADERMATCH 40
# define MAXLINELEN 64
# define ISRETURN(c) (demap[(unsigned char) (c)] == -1)
/* BinHex Encoding ========================================================= */
/*
* NAME: bh->start()
* DESCRIPTION: begin BinHex encoding
*/
int bh_start(int fd)
{
int dupfd;
dupfd = dup(fd);
if (dupfd == -1)
{
ERROR(errno, "error duplicating output stream");
return -1;
}
file = fdopen(dupfd, "ab");
if (file == 0)
{
ERROR(errno, "error creating output buffer");
close(dupfd);
return -1;
}
line[0] = ':';
lptr = 1;
state86 = 0;
runlen = 0;
crc = 0x0000;
if (fputs(hqxheader, file) == EOF)
{
ERROR(EIO, "error writing hqx header");
fclose(file);
return -1;
}
return 0;
}
/*
* NAME: flushline()
* DESCRIPTION: flush a line to the output file
*/
static
int flushline(void)
{
line[lptr++] = '\n';
line[lptr++] = 0;
if (fputs(line, file) == EOF)
{
ERROR(EIO, "error writing output data");
return -1;
}
lptr = 0;
return 0;
}
/*
* NAME: addchars()
* DESCRIPTION: insert bytes of data to the output stream
*/
static
int addchars(const unsigned char *data, register int len)
{
register unsigned char c;
while (len--)
{
c = *data++;
if (lptr == MAXLINELEN &&
flushline() == -1)
return -1;
switch (state86 & 0xff00)
{
case 0x0000:
line[lptr++] = enmap[c >> 2];
state86 = 0x0100 | (c & 0x03);
break;
case 0x0100:
line[lptr++] = enmap[((state86 & 0x03) << 4) | (c >> 4)];
state86 = 0x0200 | (c & 0x0f);
break;
case 0x0200:
line[lptr++] = enmap[((state86 & 0x0f) << 2) | (c >> 6)];
if (lptr == MAXLINELEN &&
flushline() == -1)
return -1;
line[lptr++] = enmap[c & 0x3f];
state86 = 0;
break;
}
}
return 0;
}
/*
* NAME: rleflush()
* DESCRIPTION: run-length encode data
*/
static
int rleflush(void)
{
unsigned char rle[] = { 0x90, 0x00, 0x90, 0x00 };
if ((lastch != 0x90 && runlen < 4) ||
(lastch == 0x90 && runlen < 3))
{
/* self representation */
if (lastch == 0x90)
{
while (runlen--)
if (addchars(rle, 2) == -1)
return -1;
}
else
{
while (runlen--)
if (addchars(&lastch, 1) == -1)
return -1;
}
}
else
{
/* run-length encoded */
if (lastch == 0x90)
{
rle[3] = runlen;
if (addchars(rle, 4) == -1)
return -1;
}
else
{
rle[1] = lastch;
rle[3] = runlen;
if (addchars(&rle[1], 3) == -1)
return -1;
}
}
runlen = 0;
return 0;
}
/*
* NAME: bh->insert()
* DESCRIPTION: encode bytes of data, buffering lines and flushing
*/
int bh_insert(const void *buf, register int len)
{
register const unsigned char *data = buf;
crc = crc_binh(data, len, crc);
for ( ; len--; ++data)
{
if (runlen)
{
if (runlen == 0xff || lastch != *data)
{
if (rleflush() == -1)
return -1;
}
if (lastch == *data)
{
++runlen;
continue;
}
}
lastch = *data;
runlen = 1;
}
return 0;
}
/*
* NAME: bh->insertcrc()
* DESCRIPTION: insert a two-byte CRC checksum
*/
int bh_insertcrc(void)
{
unsigned char word[2];
crc = crc_binh(zero, 2, crc);
word[0] = (crc & 0xff00) >> 8;
word[1] = (crc & 0x00ff) >> 0;
if (bh_insert(word, 2) == -1)
return -1;
crc = 0x0000;
return 0;
}
/*
* NAME: bh->end()
* DESCRIPTION: finish BinHex encoding
*/
int bh_end(void)
{
int result = 0;
if (runlen &&
rleflush() == -1)
result = -1;
if (state86 && result == 0 &&
addchars(zero, 1) == -1)
result = -1;
line[lptr++] = ':';
if (result == 0 &&
flushline() == -1)
result = -1;
if (fclose(file) == EOF && result == 0)
{
ERROR(errno, "error flushing output data");
result = -1;
}
return result;
}
/* BinHex Decoding ========================================================= */
/*
* NAME: bh->open()
* DESCRIPTION: begin BinHex decoding
*/
int bh_open(int fd)
{
int dupfd, c;
const char *ptr;
dupfd = dup(fd);
if (dupfd == -1)
{
ERROR(errno, "error duplicating input stream");
return -1;
}
file = fdopen(dupfd, "rb");
if (file == 0)
{
ERROR(errno, "error creating input buffer");
close(dupfd);
return -1;
}
state86 = 0;
runlen = 0;
crc = 0x0000;
/* find hqx header */
ptr = hqxheader;
while (ptr == 0 || ptr - hqxheader < HEADERMATCH)
{
c = getc(file);
if (c == EOF)
{
ERROR(EINVAL, "hqx file header not found");
fclose(file);
return -1;
}
if (c == '\n' || c == '\r')
{
ptr = hqxheader;
continue;
}
if (ptr && c != *ptr++)
ptr = 0;
}
/* skip to CR/LF */
do
{
c = getc(file);
if (c == EOF)
{
ERROR(EINVAL, "corrupt hqx file");
fclose(file);
return -1;
}
}
while (c != '\n' && c != '\r');
/* skip whitespace */
do
{
c = getc(file);
if (c == EOF)
{
ERROR(EINVAL, "corrupt hqx file");
fclose(file);
return -1;
}
}
while (ISRETURN(c));
if (c != ':')
{
ERROR(EINVAL, "corrupt hqx file");
fclose(file);
return -1;
}
return 0;
}
/*
* NAME: hqxchar()
* DESCRIPTION: return the next hqx character from the input stream
*/
static
int hqxchar(void)
{
int c;
do
c = getc(file);
while (c != EOF && ISRETURN(c));
if (c == EOF)
{
if (feof(file))
ERROR(EINVAL, "unexpected end of file");
else
ERROR(EIO, "error reading input file");
return -1;
}
c = demap[(unsigned char) c];
if (c == 0)
{
ERROR(EINVAL, "illegal character in hqx file");
return -1;
}
return c - 1;
}
/*
* NAME: nextchar()
* DESCRIPTION: decode one character from the hqx stream
*/
static
int nextchar(void)
{
int c, c2, ch;
c = hqxchar();
if (c == -1)
return -1;
switch (state86 & 0xff00)
{
case 0x0000:
c2 = hqxchar();
if (c2 == -1)
return -1;
ch = (c << 2) | (c2 >> 4);
state86 = 0x0100 | (c2 & 0x0f);
break;
case 0x0100:
ch = ((state86 & 0x0f) << 4) | (c >> 2);
state86 = 0x0200 | (c & 0x03);
break;
case 0x0200:
ch = ((state86 & 0x03) << 6) | c;
state86 = 0;
break;
}
return ch;
}
/*
* NAME: bh->read()
* DESCRIPTION: decode and return bytes from the hqx stream
*/
int bh_read(void *buf, register int len)
{
register unsigned char *data = buf;
const unsigned char *ptr = data;
int c, rl, count = len;
while (len--)
{
if (runlen)
{
*data++ = lastch;
--runlen;
continue;
}
c = nextchar();
if (c == -1)
return -1;
if (c == 0x90)
{
rl = nextchar();
if (rl == -1)
return -1;
if (rl > 0)
{
runlen = rl - 1;
++len;
continue;
}
}
*data++ = lastch = c;
}
crc = crc_binh(ptr, count, crc);
return count;
}
/*
* NAME: bh->readcrc()
* DESCRIPTION: read and compare CRC bytes
*/
int bh_readcrc(void)
{
unsigned short check;
unsigned char word[2];
check = crc_binh(zero, 2, crc);
if (bh_read(word, 2) < 2)
return -1;
crc = (word[0] << 8) |
(word[1] << 0);
if (crc != check)
{
ERROR(EINVAL, "CRC checksum error");
return -1;
}
crc = 0x0000;
return 0;
}
/*
* NAME: bh->close()
* DESCRIPTION: finish BinHex decoding
*/
int bh_close(void)
{
int c, result = 0;
/* skip whitespace */
do
c = getc(file);
while (c != EOF && ISRETURN(c));
/* skip optional exclamation */
if (c == '!')
{
do
c = getc(file);
while (c != EOF && ISRETURN(c));
}
/* verify trailing colon */
if (c != ':')
{
ERROR(EINVAL, "corrupt end of hqx file");
result = -1;
}
if (fclose(file) == EOF && result == 0)
{
ERROR(errno, "error closing input file");
result = -1;
}
return result;
}

32
binhex.h Normal file
View File

@ -0,0 +1,32 @@
/*
* hfsutils - tools 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: binhex.h,v 1.7 1998/04/11 08:26:53 rob Exp $
*/
extern const char *bh_error;
int bh_start(int);
int bh_insert(const void *, register int);
int bh_insertcrc(void);
int bh_end(void);
int bh_open(int);
int bh_read(void *, register int);
int bh_readcrc(void);
int bh_close(void);

285
charset.c Normal file
View File

@ -0,0 +1,285 @@
/*
* hfsutils - tools 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: charset.c,v 1.5 1998/11/02 22:08:23 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdlib.h>
# include <string.h>
# include "charset.h"
static const
UCS2 macroman[256] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x2126, 0x00e6, 0x00f8,
0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
0x00ff, 0x0178, 0x2044, 0x00a4, 0x2039, 0x203a, 0xfb01, 0xfb02,
0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7
};
static const
char *macroman_subst[128] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
"+", 0, 0, 0, 0, "*", 0, 0, /* 0xa0 - 0xa7 */
0, 0, "[tm]", 0, 0, "!=", 0, 0, /* 0xa8 - 0xaf */
"[inf]", 0, "<=", ">=", 0, 0, "[partial]", "[Sum]", /* 0xb0 - 0xb7 */
"[Prod]", "[pi]", "[Integral]", 0, 0, "[ohm]", 0, 0, /* 0xb8 - 0xbf */
0, 0, 0, "[Sqrt]", "[f]", "~=", "[delta]", 0, /* 0xc0 - 0xc7 */
0, "...", 0, 0, 0, 0, "OE", "oe", /* 0xc8 - 0xcf */
"-", "--", "``", "''", "`", "'", 0, "#", /* 0xd0 - 0xd7 */
0, "Y", "/", 0, "<", ">", "fi", "fl", /* 0xd8 - 0xdf */
"++", 0, ",", ",,", "o/oo", 0, 0, 0, /* 0xe0 - 0xe7 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0xe8 - 0xef */
"[Apple]", 0, 0, 0, 0, "i", "^", "~", /* 0xf0 - 0xf7 */
0, "-", "\267", "\260", 0, "\"", "-", "^" /* 0xf8 - 0xff */
};
static
unsigned char latin1[256];
static const
char *latin1_subst[128] = {
"", "", "", "", "", "", "", "", /* 0x80 - 0x87 */
"", "", "", "", "", "", "", "", /* 0x88 - 0x8f */
"", "", "", "", "", "", "", "", /* 0x90 - 0x97 */
"", "", "", "", "", "", "", "", /* 0x98 - 0x9f */
0, 0, 0, 0, 0, 0, "|", 0, /* 0xa0 - 0xa7 */
0, 0, 0, 0, 0, "-", 0, 0, /* 0xa8 - 0xaf */
0, 0, "[^2]", "[^3]", 0, 0, 0, 0, /* 0xb0 - 0xb7 */
0, "[^1]", 0, 0, "[1/4]", "[1/2]", "[3/4]", 0, /* 0xb8 - 0xbf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
"D", 0, 0, 0, 0, 0, 0, "x", /* 0xd0 - 0xd7 */
0, 0, 0, 0, 0, "Y", "P", 0, /* 0xd8 - 0xdf */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
"d", 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xf7 */
0, 0, 0, 0, 0, "y", "p", 0 /* 0xf8 - 0xff */
};
/*
* NAME: charset->unicode()
* DESCRIPTION: return a Unicode string for MacOS Standard Roman
*/
UCS2 *cs_unicode(char *mstr, int *lenptr)
{
int len, i;
UCS2 *unicode, *ptr;
len = lenptr ? *lenptr : strlen(mstr);
unicode = malloc((len + 1) * sizeof(UCS2));
if (unicode == 0)
return 0;
ptr = unicode;
for (i = 0; i < len; ++i)
*ptr++ = macroman[*(unsigned char *) mstr++];
*ptr = 0;
return unicode;
}
/*
* NAME: charset->latin1()
* DESCRIPTION: return a Latin-1 (ISO 8859-1) string for MacOS Standard Roman
*/
char *cs_latin1(char *mstr, int *lenptr)
{
int ilen, olen, i;
char *latin1, *ptr;
const char *subst;
unsigned char ch;
UCS2 unicode;
ilen = lenptr ? *lenptr : strlen(mstr);
olen = 0;
for (i = 0; i < ilen; ++i)
{
ch = *((unsigned char *) mstr + i);
unicode = macroman[ch];
if (unicode & 0xff00)
olen += strlen(macroman_subst[ch & 0x7f]);
else
++olen;
}
latin1 = malloc(olen + 1);
if (latin1 == 0)
return 0;
ptr = latin1;
for (i = 0; i < ilen; ++i)
{
ch = *(unsigned char *) mstr++;
unicode = macroman[ch];
if (unicode & 0xff00)
{
/* substitute similar Latin-1 character(s) */
subst = macroman_subst[ch & 0x7f];
strcpy(ptr, subst);
ptr += strlen(subst);
}
else
*ptr++ = unicode;
}
*ptr = 0;
if (lenptr)
*lenptr = olen;
return latin1;
}
/*
* NAME: charset->mktable()
* DESCRIPTION: construct latin1[] table from macroman[]
*/
static
void mktable(void)
{
int i;
for (i = 0x00; i <= 0xff; ++i)
latin1[i] = 0xff;
for (i = 0x00; i <= 0xff; ++i)
{
UCS2 unicode = macroman[i];
if (! (unicode & 0xff00))
latin1[unicode] = i;
}
}
/*
* NAME: charset->macroman()
* DESCRIPTION: return a MacOS Standard Roman string for Latin-1 (ISO 8859-1)
*/
char *cs_macroman(char *lstr, int *lenptr)
{
int ilen, olen, i;
char *macroman, *ptr;
const char *subst;
unsigned char ch, msr;
if (latin1[0x80] != 0xff)
mktable();
ilen = lenptr ? *lenptr : strlen(lstr);
olen = 0;
for (i = 0; i < ilen; ++i)
{
ch = *((unsigned char *) lstr + i);
msr = latin1[ch];
if (msr == 0xff)
olen += strlen(latin1_subst[ch & 0x7f]);
else
++olen;
}
macroman = malloc(olen + 1);
if (macroman == 0)
return 0;
ptr = macroman;
for (i = 0; i < ilen; ++i)
{
ch = *(unsigned char *) lstr++;
msr = latin1[ch];
if (msr == 0xff)
{
/* substitute similar MacOS Standard Roman character(s) */
subst = latin1_subst[ch & 0x7f];
strcpy(ptr, subst);
ptr += strlen(subst);
}
else
*ptr++ = msr;
}
*ptr = 0;
if (lenptr)
*lenptr = olen;
return macroman;
}

27
charset.h Normal file
View File

@ -0,0 +1,27 @@
/*
* hfsutils - tools 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: charset.h,v 1.3 1998/04/11 08:26:53 rob Exp $
*/
typedef unsigned short UCS2;
UCS2 *cs_unicode(char *, int *);
char *cs_latin1(char *, int *);
char *cs_macroman(char *, int *);

93
config.h.in Normal file
View File

@ -0,0 +1,93 @@
/* config.h.in. Generated automatically from configure.in by autoheader. */
/*
* hfsutils - tools 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: acconfig.h,v 1.5 1998/04/11 08:26:53 rob Exp $
*/
/*****************************************************************************
* Definitions selected automatically by `configure' *
*****************************************************************************/
/* Define to empty if the keyword does not work. */
#undef const
/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t
/* Define to `unsigned' if <sys/types.h> doesn't define. */
#undef size_t
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t
/* Define if you want to enable diagnostic debugging support. */
#undef DEBUG
/* Define if your system has sys_errlist[] and sys_nerr. */
#undef HAVE_SYS_ERRLIST
/* Define if you have the setreuid function. */
#undef HAVE_SETREUID
/* Define if you have the strdup function. */
#undef HAVE_STRDUP
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
/* Define if you have the strstr function. */
#undef HAVE_STRSTR
/* Define if you have the strtol function. */
#undef HAVE_STRTOL
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/*****************************************************************************
* End of automatically configured definitions *
*****************************************************************************/
# ifndef HAVE_STRDUP
char *strdup(const char *);
# endif
# ifndef HAVE_STRERROR
char *strerror(int);
# endif
# ifndef HAVE_STRSTR
char *strstr(const char *, const char *);
# endif
# ifndef HAVE_STRTOL
long strtol(const char *, char **, int);
# endif

2116
configure vendored Executable file

File diff suppressed because it is too large Load Diff

301
configure.in Normal file
View File

@ -0,0 +1,301 @@
dnl -*- shell-script -*-
dnl
dnl hfsutils - tools 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.10 1998/09/15 19:19:42 rob Exp $
dnl
AC_INIT(libhfs/libhfs.h)
AC_CONFIG_HEADER(config.h)
AC_CONFIG_SUBDIRS(libhfs librsrc)
AC_ARG_WITH(tcl,
[ --with-tcl[=DIR] build the Tcl components], [
case "$with_tcl" in
yes|no)
tcl_dir="DEFAULT"
;;
*)
tcl_dir="$with_tcl"
with_tcl=yes
;;
esac
])
AC_ARG_WITH(tk,
[ --with-tk[=DIR] build the Tk components], [
case "$with_tk" in
yes|no)
tk_dir="DEFAULT"
;;
*)
tk_dir="$with_tk"
with_tk=yes
;;
esac
])
if test "$with_tk" = yes && test "$with_tcl" != yes
then
AC_MSG_ERROR(--with-tk requires --with-tcl)
fi
dnl Checks for programs.
AC_PROG_MAKE_SET
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_RANLIB
AC_PROG_GCC_TRADITIONAL
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(unistd.h fcntl.h termios.h sys/ioctl.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T
AC_TYPE_SIZE_T
AC_C_CONST
dnl Checks for library functions.
AC_REPLACE_FUNCS(strdup strerror strstr strtol)
AC_CHECK_FUNCS(setreuid)
AC_CACHE_CHECK(for sys_errlist, hfs_cv_decl_syserrlist, [
AC_TRY_LINK([], [
extern char *sys_errlist[];
extern int sys_nerr;
sys_errlist[sys_nerr - 1][0] = 0;
], hfs_cv_decl_syserrlist=yes, hfs_cv_decl_syserrlist=no)
])
if test "$hfs_cv_decl_syserrlist" = yes
then
AC_DEFINE(HAVE_SYS_ERRLIST)
fi
dnl Prepare target variables.
MAKE_TARGETS=""
INSTALL_TARGETS=""
AC_SUBST(MAKE_TARGETS)
AC_SUBST(INSTALL_TARGETS)
dnl Tcl configuration.
TCL_INCLUDES=""
TCL_LIB_SPEC=""
TCL_LIBS=""
AC_SUBST(TCL_INCLUDES)
AC_SUBST(TCL_LIB_SPEC)
AC_SUBST(TCL_LIBS)
if test "$with_tcl" = yes
then
AC_MSG_CHECKING(for Tcl)
found=""
for dir in \
"$tcl_dir" \
"$tcl_dir/lib" \
"$tcl_dir/../lib" \
/usr/local/lib \
/usr/local/lib/tcl* \
/usr/local/tcl*/lib \
/usr/lib \
/usr/lib/tcl* \
/usr/tcl*/lib \
; \
do
if test -r "$dir/tclConfig.sh"
then
found="$dir"
break
fi
done
if test -z "$found"
then
AC_MSG_RESULT(cannot find installation)
AC_MSG_ERROR(use --without-tcl or --with-tcl=DIR)
fi
tcl_dir="$found"
. "$tcl_dir/tclConfig.sh"
AC_MSG_RESULT(version $TCL_VERSION in $tcl_dir)
AC_MSG_CHECKING(for tcl.h)
found=""
for dir in \
$TCL_PREFIX/include \
$TCL_PREFIX/include/tcl* \
$TCL_PREFIX/tcl*/include \
"$tcl_dir" \
"$tcl_dir/include" \
"$tcl_dir/../include" \
`echo "$tcl_dir" | sed -e 's|/lib|/include|'` \
; \
do
if test -r "$dir/tcl.h"
then
found="$dir"
break
fi
done
if test -z "$found"
then
AC_MSG_RESULT(not found)
AC_MSG_WARN(compilation of Tcl components may fail)
AC_MSG_WARN(edit Makefile if necessary and contact author)
else
AC_MSG_RESULT($found)
TCL_INCLUDES="-I$found"
fi
MAKE_TARGETS="$MAKE_TARGETS all_tcl"
INSTALL_TARGETS="$INSTALL_TARGETS install_tcl"
fi
dnl Tk configuration.
TK_INCLUDES=""
TK_LIB_SPEC=""
TK_LIBS=""
AC_SUBST(TK_INCLUDES)
AC_SUBST(TK_LIB_SPEC)
AC_SUBST(TK_LIBS)
if test "$with_tk" = yes
then
AC_MSG_CHECKING(for Tk)
found=""
for dir in \
"$tk_dir" \
"$tk_dir/lib" \
"$tk_dir/../lib" \
/usr/local/lib \
/usr/local/lib/tk* \
/usr/local/tk*/lib \
/usr/lib \
/usr/lib/tk* \
/usr/tk*/lib \
; \
do
if test -r "$dir/tkConfig.sh"
then
found="$dir"
break
fi
done
if test -z "$found"
then
AC_MSG_RESULT(cannot find installation)
AC_MSG_ERROR(use --without-tk or --with-tk=DIR)
fi
tk_dir="$found"
. "$tk_dir/tkConfig.sh"
AC_MSG_RESULT(version $TK_VERSION in $tk_dir)
AC_MSG_CHECKING(for tk.h)
found=""
for dir in \
$TK_PREFIX/include \
$TK_PREFIX/include/tk* \
$TK_PREFIX/tk*/include \
"$tk_dir" \
"$tk_dir/include" \
"$tk_dir/../include" \
`echo "$tk_dir" | sed -e 's|/lib|/include|'` \
; \
do
if test -r "$dir/tk.h"
then
found="$dir"
break
fi
done
if test -z "$found"
then
AC_MSG_RESULT(not found)
AC_MSG_WARN(compilation of Tk components may fail)
AC_MSG_WARN(edit Makefile if necessary and contact author)
else
AC_MSG_RESULT($found)
if test "x-I$found" != "x$TCL_INCLUDES"
then
TK_INCLUDES="-I$found"
fi
fi
TK_INCLUDES="$TK_INCLUDES $TK_XINCLUDES"
MAKE_TARGETS="$MAKE_TARGETS all_tk"
INSTALL_TARGETS="$INSTALL_TARGETS install_tk"
fi
dnl Other options.
AC_ARG_ENABLE(cli,
[ --disable-cli do not build or install the command-line utils])
if test "x$enable_cli" != xno
then
MAKE_TARGETS="all_cli $MAKE_TARGETS"
INSTALL_TARGETS="install_cli $INSTALL_TARGETS"
fi
AC_ARG_ENABLE(devlibs,
[ --enable-devlibs enable installation of the developer libraries])
if test "x$enable_devlibs" = xyes
then
MAKE_TARGETS="$MAKE_TARGETS all_lib"
INSTALL_TARGETS="$INSTALL_TARGETS install_lib"
fi
AC_ARG_ENABLE(debug,
[ --enable-debug enable diagnostic debugging support])
if test "x$enable_debug" = xyes
then
AC_DEFINE(DEBUG)
fi
dnl Create output files.
AC_OUTPUT(hfsck/Makefile linux/Makefile Makefile)

769
copyin.c Normal file
View File

@ -0,0 +1,769 @@
/*
* hfsutils - tools 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: copyin.c,v 1.8 1998/11/02 22:08:25 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# ifdef HAVE_FCNTL_H
# include <fcntl.h>
# else
int open(const char *, int, ...);
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# else
int dup(int);
# endif
# include <stdlib.h>
# include <string.h>
# include <errno.h>
# include "hfs.h"
# include "data.h"
# include "copyin.h"
# include "charset.h"
# include "binhex.h"
# include "crc.h"
const char *cpi_error = "no error";
extern int errno;
# define ERROR(code, str) (cpi_error = (str), errno = (code))
# define MACB_BLOCKSZ 128
# define TEXT_TYPE "TEXT"
# define TEXT_CREA "UNIX"
# define RAW_TYPE "????"
# define RAW_CREA "UNIX"
/* Copy routines =========================================================== */
/*
* NAME: fork->macb()
* DESCRIPTION: copy a single fork for MacBinary II
*/
static
int fork_macb(int ifile, hfsfile *ofile, unsigned long size)
{
char buf[HFS_BLOCKSZ * 4];
unsigned long chunk, bytes;
while (size)
{
chunk = (size < sizeof(buf)) ?
(size + (MACB_BLOCKSZ - 1)) & ~(MACB_BLOCKSZ - 1) : sizeof(buf);
bytes = read(ifile, buf, chunk);
if (bytes == (unsigned long) -1)
{
ERROR(errno, "error reading data");
return -1;
}
else if (bytes != chunk)
{
ERROR(EIO, "read incomplete chunk");
return -1;
}
chunk = (size > bytes) ? bytes : size;
bytes = hfs_write(ofile, buf, chunk);
if (bytes == (unsigned long) -1)
{
ERROR(errno, hfs_error);
return -1;
}
else if (bytes != chunk)
{
ERROR(EIO, "wrote incomplete chunk");
return -1;
}
size -= chunk;
}
return 0;
}
/*
* NAME: do_macb()
* DESCRIPTION: perform copy using MacBinary II translation
*/
static
int do_macb(int ifile, hfsfile *ofile,
unsigned long dsize, unsigned long rsize)
{
if (hfs_setfork(ofile, 0) == -1)
{
ERROR(errno, hfs_error);
return -1;
}
if (fork_macb(ifile, ofile, dsize) == -1)
return -1;
if (hfs_setfork(ofile, 1) == -1)
{
ERROR(errno, hfs_error);
return -1;
}
if (fork_macb(ifile, ofile, rsize) == -1)
return -1;
return 0;
}
/*
* NAME: fork->binh()
* DESCRIPTION: copy a single fork for BinHex
*/
static
int fork_binh(hfsfile *ofile, unsigned long size)
{
char buf[HFS_BLOCKSZ * 4];
long chunk, bytes;
while (size)
{
chunk = (size > sizeof(buf)) ? sizeof(buf) : size;
bytes = bh_read(buf, chunk);
if (bytes == -1)
{
ERROR(errno, bh_error);
return -1;
}
else if (bytes != chunk)
{
ERROR(EIO, "read incomplete chunk");
return -1;
}
bytes = hfs_write(ofile, buf, chunk);
if (bytes == -1)
{
ERROR(errno, hfs_error);
return -1;
}
else if (bytes != chunk)
{
ERROR(EIO, "wrote incomplete chunk");
return -1;
}
size -= chunk;
}
if (bh_readcrc() == -1)
{
ERROR(errno, bh_error);
return -1;
}
return 0;
}
/*
* NAME: do_binh()
* DESCRIPTION: perform copy using BinHex translation
*/
static
int do_binh(hfsfile *ofile, unsigned long dsize, unsigned long rsize)
{
if (hfs_setfork(ofile, 0) == -1)
{
ERROR(errno, hfs_error);
return -1;
}
if (fork_binh(ofile, dsize) == -1)
return -1;
if (hfs_setfork(ofile, 1) == -1)
{
ERROR(errno, hfs_error);
return -1;
}
if (fork_binh(ofile, rsize) == -1)
return -1;
return 0;
}
/*
* NAME: do_text()
* DESCRIPTION: perform copy using text translation
*/
static
int do_text(int ifile, hfsfile *ofile)
{
char buf[HFS_BLOCKSZ * 4], *ptr;
long chunk, bytes;
int len;
while (1)
{
chunk = read(ifile, buf, sizeof(buf));
if (chunk == -1)
{
ERROR(errno, "error reading source file");
return -1;
}
else if (chunk == 0)
break;
for (ptr = buf; ptr < buf + chunk; ++ptr)
{
if (*ptr == '\n')
*ptr = '\r';
}
len = chunk;
ptr = cs_macroman(buf, &len);
if (ptr == 0)
{
ERROR(ENOMEM, 0);
return -1;
}
bytes = hfs_write(ofile, ptr, len);
free(ptr);
if (bytes == -1)
{
ERROR(errno, hfs_error);
return -1;
}
else if (bytes != len)
{
ERROR(EIO, "wrote incomplete chunk");
return -1;
}
}
return 0;
}
/*
* NAME: do_raw()
* DESCRIPTION: perform copy using no translation
*/
static
int do_raw(int ifile, hfsfile *ofile)
{
char buf[HFS_BLOCKSZ * 4];
long chunk, bytes;
while (1)
{
chunk = read(ifile, buf, sizeof(buf));
if (chunk == -1)
{
ERROR(errno, "error reading source file");
return -1;
}
else if (chunk == 0)
break;
bytes = hfs_write(ofile, buf, chunk);
if (bytes == -1)
{
ERROR(errno, hfs_error);
return -1;
}
else if (bytes != chunk)
{
ERROR(EIO, "wrote incomplete chunk");
return -1;
}
}
return 0;
}
/* Utility Routines ======================================================== */
/*
* NAME: opensrc()
* DESCRIPTION: open the source file; set hint for destination filename
*/
static
int opensrc(const char *srcname, const char **dsthint, const char *ext,
int binary)
{
int fd, len;
static char name[HFS_MAX_FLEN + 1];
const char *cptr;
char *ptr;
if (strcmp(srcname, "-") == 0)
{
fd = dup(STDIN_FILENO);
srcname = "";
}
else
fd = open(srcname, O_RDONLY);
if (fd == -1)
{
ERROR(errno, "error opening source file");
return -1;
}
cptr = strrchr(srcname, '/');
if (cptr == 0)
cptr = srcname;
else
++cptr;
if (ext == 0)
len = strlen(cptr);
else
{
ext = strstr(cptr, ext);
if (ext == 0)
len = strlen(cptr);
else
len = ext - cptr;
}
if (len > HFS_MAX_FLEN)
len = HFS_MAX_FLEN;
memcpy(name, cptr, len);
name[len] = 0;
for (ptr = name; *ptr; ++ptr)
{
switch (*ptr)
{
case ':':
*ptr = '-';
break;
case '_':
*ptr = ' ';
break;
}
}
*dsthint = name;
return fd;
}
/*
* NAME: opendst()
* DESCRIPTION: open the destination file
*/
static
hfsfile *opendst(hfsvol *vol, const char *dstname, const char *hint,
const char *type, const char *creator)
{
hfsdirent ent;
hfsfile *file;
unsigned long cwd;
if (hfs_stat(vol, dstname, &ent) != -1 &&
(ent.flags & HFS_ISDIR))
{
cwd = hfs_getcwd(vol);
if (hfs_setcwd(vol, ent.cnid) == -1)
{
ERROR(errno, hfs_error);
return 0;
}
dstname = hint;
}
hfs_delete(vol, dstname);
file = hfs_create(vol, dstname, type, creator);
if (file == 0)
{
ERROR(errno, hfs_error);
if (dstname == hint)
hfs_setcwd(vol, cwd);
return 0;
}
if (dstname == hint)
{
if (hfs_setcwd(vol, cwd) == -1)
{
ERROR(errno, hfs_error);
hfs_close(file);
return 0;
}
}
return file;
}
/*
* NAME: closefiles()
* DESCRIPTION: close source and destination files
*/
static
void closefiles(int ifile, hfsfile *ofile, int *result)
{
if (ofile && hfs_close(ofile) == -1 && *result == 0)
{
ERROR(errno, hfs_error);
*result = -1;
}
if (close(ifile) == -1 && *result == 0)
{
ERROR(errno, "error closing source file");
*result = -1;
}
}
/* Interface Routines ====================================================== */
/*
* NAME: cpi->macb()
* DESCRIPTION: copy a UNIX file to an HFS file using MacBinary II translation
*/
int cpi_macb(const char *srcname, hfsvol *vol, const char *dstname)
{
int ifile, result = 0;
hfsfile *ofile;
hfsdirent ent;
const char *dsthint;
char type[5], creator[5];
unsigned char buf[MACB_BLOCKSZ];
unsigned short crc;
unsigned long dsize, rsize;
ifile = opensrc(srcname, &dsthint, ".bin", 1);
if (ifile == -1)
return -1;
if (read(ifile, buf, MACB_BLOCKSZ) < MACB_BLOCKSZ)
{
ERROR(errno, "error reading MacBinary file header");
close(ifile);
return -1;
}
if (buf[0] != 0 || buf[74] != 0)
{
ERROR(EINVAL, "invalid MacBinary file header");
close(ifile);
return -1;
}
crc = d_getuw(&buf[124]);
if (crc_macb(buf, 124, 0x0000) != crc)
{
/* (buf[82] == 0) => MacBinary I? */
ERROR(EINVAL, "unknown, unsupported, or corrupt MacBinary file");
close(ifile);
return -1;
}
if (buf[123] > 129)
{
ERROR(EINVAL, "unsupported MacBinary file version");
close(ifile);
return -1;
}
if (buf[1] < 1 || buf[1] > 63 ||
buf[2 + buf[1]] != 0)
{
ERROR(EINVAL, "invalid MacBinary file header (bad file name)");
close(ifile);
return -1;
}
dsize = d_getul(&buf[83]);
rsize = d_getul(&buf[87]);
if (dsize > 0x7fffffff || rsize > 0x7fffffff)
{
ERROR(EINVAL, "invalid MacBinary file header (bad file length)");
close(ifile);
return -1;
}
dsthint = (char *) &buf[2];
memcpy(type, &buf[65], 4);
memcpy(creator, &buf[69], 4);
type[4] = creator[4] = 0;
ofile = opendst(vol, dstname, dsthint, type, creator);
if (ofile == 0)
{
close(ifile);
return -1;
}
result = do_macb(ifile, ofile, dsize, rsize);
if (result == 0 && hfs_fstat(ofile, &ent) == -1)
{
ERROR(errno, hfs_error);
result = -1;
}
ent.fdflags = (buf[73] << 8 | buf[101]) &
~(HFS_FNDR_ISONDESK | HFS_FNDR_HASBEENINITED | HFS_FNDR_RESERVED);
ent.crdate = d_ltime(d_getul(&buf[91]));
ent.mddate = d_ltime(d_getul(&buf[95]));
if (result == 0 && hfs_fsetattr(ofile, &ent) == -1)
{
ERROR(errno, hfs_error);
result = -1;
}
closefiles(ifile, ofile, &result);
return result;
}
/*
* NAME: binhx()
* DESCRIPTION: auxiliary BinHex routine
*/
static
int binhx(char *fname, char *type, char *creator, short *fdflags,
unsigned long *dsize, unsigned long *rsize)
{
int len;
unsigned char byte, word[2], lword[4];
if (bh_read(&byte, 1) < 1)
{
ERROR(errno, bh_error);
return -1;
}
len = (unsigned char) byte;
if (len < 1 || len > HFS_MAX_FLEN)
{
ERROR(EINVAL, "invalid BinHex file header (bad file name)");
return -1;
}
if (bh_read(fname, len + 1) < len + 1)
{
ERROR(errno, bh_error);
return -1;
}
if (fname[len] != 0)
{
ERROR(EINVAL, "invalid BinHex file header (bad file name)");
return -1;
}
if (bh_read(type, 4) < 4 ||
bh_read(creator, 4) < 4 ||
bh_read(word, 2) < 2)
{
ERROR(errno, bh_error);
return -1;
}
*fdflags = d_getsw(word);
if (bh_read(lword, 4) < 4)
{
ERROR(errno, bh_error);
return -1;
}
*dsize = d_getul(lword);
if (bh_read(lword, 4) < 4)
{
ERROR(errno, bh_error);
return -1;
}
*rsize = d_getul(lword);
if (*dsize > 0x7fffffff || *rsize > 0x7fffffff)
{
ERROR(EINVAL, "invalid BinHex file header (bad file length)");
return -1;
}
if (bh_readcrc() == -1)
{
ERROR(errno, bh_error);
return -1;
}
return 0;
}
/*
* NAME: cpi->binh()
* DESCRIPTION: copy a UNIX file to an HFS file using BinHex translation
*/
int cpi_binh(const char *srcname, hfsvol *vol, const char *dstname)
{
int ifile, result;
hfsfile *ofile;
hfsdirent ent;
const char *dsthint;
char fname[HFS_MAX_FLEN + 1], type[5], creator[5];
short fdflags;
unsigned long dsize, rsize;
ifile = opensrc(srcname, &dsthint, ".hqx", 0);
if (ifile == -1)
return -1;
if (bh_open(ifile) == -1)
{
ERROR(errno, bh_error);
close(ifile);
return -1;
}
if (binhx(fname, type, creator, &fdflags, &dsize, &rsize) == -1)
{
bh_close();
close(ifile);
return -1;
}
dsthint = fname;
ofile = opendst(vol, dstname, dsthint, type, creator);
if (ofile == 0)
{
bh_close();
close(ifile);
return -1;
}
result = do_binh(ofile, dsize, rsize);
if (bh_close() == -1 && result == 0)
{
ERROR(errno, bh_error);
result = -1;
}
if (result == 0 && hfs_fstat(ofile, &ent) == -1)
{
ERROR(errno, hfs_error);
result = -1;
}
ent.fdflags = fdflags &
~(HFS_FNDR_ISONDESK | HFS_FNDR_HASBEENINITED | HFS_FNDR_ISINVISIBLE);
if (result == 0 && hfs_fsetattr(ofile, &ent) == -1)
{
ERROR(errno, hfs_error);
result = -1;
}
closefiles(ifile, ofile, &result);
return result;
}
/*
* NAME: cpi->text()
* DESCRIPTION: copy a UNIX file to an HFS file using text translation
*/
int cpi_text(const char *srcname, hfsvol *vol, const char *dstname)
{
int ifile, result = 0;
hfsfile *ofile;
const char *dsthint;
ifile = opensrc(srcname, &dsthint, ".txt", 0);
if (ifile == -1)
return -1;
ofile = opendst(vol, dstname, dsthint, TEXT_TYPE, TEXT_CREA);
if (ofile == 0)
{
close(ifile);
return -1;
}
result = do_text(ifile, ofile);
closefiles(ifile, ofile, &result);
return result;
}
/*
* NAME: cpi->raw()
* DESCRIPTION: copy a UNIX file to the data fork of an HFS file
*/
int cpi_raw(const char *srcname, hfsvol *vol, const char *dstname)
{
int ifile, result = 0;
hfsfile *ofile;
const char *dsthint;
ifile = opensrc(srcname, &dsthint, 0, 1);
if (ifile == -1)
return -1;
ofile = opendst(vol, dstname, dsthint, RAW_TYPE, RAW_CREA);
if (ofile == 0)
{
close(ifile);
return -1;
}
result = do_raw(ifile, ofile);
closefiles(ifile, ofile, &result);
return result;
}

29
copyin.h Normal file
View File

@ -0,0 +1,29 @@
/*
* hfsutils - tools 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: copyin.h,v 1.6 1998/04/11 08:26:54 rob Exp $
*/
extern const char *cpi_error;
typedef int (*cpifunc)(const char *, hfsvol *, const char *);
int cpi_macb(const char *, hfsvol *, const char *);
int cpi_binh(const char *, hfsvol *, const char *);
int cpi_text(const char *, hfsvol *, const char *);
int cpi_raw(const char *, hfsvol *, const char *);

652
copyout.c Normal file
View File

@ -0,0 +1,652 @@
/*
* hfsutils - tools 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: copyout.c,v 1.9 1998/04/11 08:26:54 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# ifdef HAVE_FCNTL_H
# include <fcntl.h>
# else
int open(const char *, int, ...);
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# else
int dup(int);
# endif
# include <stdlib.h>
# include <string.h>
# include <errno.h>
# include <sys/stat.h>
# include "hfs.h"
# include "data.h"
# include "copyout.h"
# include "charset.h"
# include "binhex.h"
# include "crc.h"
const char *cpo_error = "no error";
extern int errno;
# define ERROR(code, str) (cpo_error = (str), errno = (code))
# define MACB_BLOCKSZ 128
/* Copy Routines =========================================================== */
/*
* NAME: fork->macb()
* DESCRIPTION: copy a single fork for MacBinary II
*/
static
int fork_macb(hfsfile *ifile, int ofile, unsigned long size)
{
char buf[HFS_BLOCKSZ * 4];
long chunk, bytes;
unsigned long total = 0;
while (1)
{
chunk = hfs_read(ifile, buf, sizeof(buf));
if (chunk == -1)
{
ERROR(errno, hfs_error);
return -1;
}
else if (chunk == 0)
break;
bytes = write(ofile, buf, chunk);
if (bytes == -1)
{
ERROR(errno, "error writing data");
return -1;
}
else if (bytes != chunk)
{
ERROR(EIO, "wrote incomplete chunk");
return -1;
}
total += bytes;
}
if (total != size)
{
ERROR(EIO, "inconsistent fork length");
return -1;
}
chunk = total % MACB_BLOCKSZ;
if (chunk)
{
memset(buf, 0, MACB_BLOCKSZ);
bytes = write(ofile, buf, MACB_BLOCKSZ - chunk);
if (bytes == -1)
{
ERROR(errno, "error writing data");
return -1;
}
else if (bytes != MACB_BLOCKSZ - chunk)
{
ERROR(EIO, "wrong incomplete chunk");
return -1;
}
}
return 0;
}
/*
* NAME: do_macb()
* DESCRIPTION: perform copy using MacBinary II translation
*/
static
int do_macb(hfsfile *ifile, int ofile)
{
hfsdirent ent;
unsigned char buf[MACB_BLOCKSZ];
long bytes;
if (hfs_fstat(ifile, &ent) == -1)
{
ERROR(errno, hfs_error);
return -1;
}
memset(buf, 0, MACB_BLOCKSZ);
buf[1] = strlen(ent.name);
strcpy((char *) &buf[2], ent.name);
memcpy(&buf[65], ent.u.file.type, 4);
memcpy(&buf[69], ent.u.file.creator, 4);
buf[73] = ent.fdflags >> 8;
d_putul(&buf[83], ent.u.file.dsize);
d_putul(&buf[87], ent.u.file.rsize);
d_putul(&buf[91], d_mtime(ent.crdate));
d_putul(&buf[95], d_mtime(ent.mddate));
buf[101] = ent.fdflags & 0xff;
buf[122] = buf[123] = 129;
d_putuw(&buf[124], crc_macb(buf, 124, 0x0000));
bytes = write(ofile, buf, MACB_BLOCKSZ);
if (bytes == -1)
{
ERROR(errno, "error writing data");
return -1;
}
else if (bytes != MACB_BLOCKSZ)
{
ERROR(EIO, "wrote incomplete chunk");
return -1;
}
if (hfs_setfork(ifile, 0) == -1)
{
ERROR(errno, hfs_error);
return -1;
}
if (fork_macb(ifile, ofile, ent.u.file.dsize) == -1)
return -1;
if (hfs_setfork(ifile, 1) == -1)
{
ERROR(errno, hfs_error);
return -1;
}
if (fork_macb(ifile, ofile, ent.u.file.rsize) == -1)
return -1;
return 0;
}
/*
* NAME: fork->binh()
* DESCRIPTION: copy a single fork for BinHex
*/
static
int fork_binh(hfsfile *ifile, unsigned long size)
{
char buf[HFS_BLOCKSZ * 4];
long bytes;
unsigned long total = 0;
while (1)
{
bytes = hfs_read(ifile, buf, sizeof(buf));
if (bytes == -1)
{
ERROR(errno, hfs_error);
return -1;
}
else if (bytes == 0)
break;
if (bh_insert(buf, bytes) == -1)
{
ERROR(errno, bh_error);
return -1;
}
total += bytes;
}
if (total != size)
{
ERROR(EIO, "inconsistent fork length");
return -1;
}
if (bh_insertcrc() == -1)
{
ERROR(errno, bh_error);
return -1;
}
return 0;
}
/*
* NAME: binhx()
* DESCRIPTION: auxiliary BinHex routine
*/
static
int binhx(hfsfile *ifile)
{
hfsdirent ent;
unsigned char byte, word[2], lword[4];
if (hfs_fstat(ifile, &ent) == -1)
{
ERROR(errno, hfs_error);
return -1;
}
byte = strlen(ent.name);
if (bh_insert(&byte, 1) == -1 ||
bh_insert(ent.name, byte + 1) == -1 ||
bh_insert(ent.u.file.type, 4) == -1 ||
bh_insert(ent.u.file.creator, 4) == -1)
{
ERROR(errno, bh_error);
return -1;
}
d_putsw(word, ent.fdflags);
if (bh_insert(word, 2) == -1)
{
ERROR(errno, bh_error);
return -1;
}
d_putul(lword, ent.u.file.dsize);
if (bh_insert(lword, 4) == -1)
{
ERROR(errno, bh_error);
return -1;
}
d_putul(lword, ent.u.file.rsize);
if (bh_insert(lword, 4) == -1 ||
bh_insertcrc() == -1)
{
ERROR(errno, bh_error);
return -1;
}
if (hfs_setfork(ifile, 0) == -1)
{
ERROR(errno, hfs_error);
return -1;
}
if (fork_binh(ifile, ent.u.file.dsize) == -1)
return -1;
if (hfs_setfork(ifile, 1) == -1)
{
ERROR(errno, hfs_error);
return -1;
}
if (fork_binh(ifile, ent.u.file.rsize) == -1)
return -1;
return 0;
}
/*
* NAME: do_binh()
* DESCRIPTION: perform copy using BinHex translation
*/
static
int do_binh(hfsfile *ifile, int ofile)
{
int result;
if (bh_start(ofile) == -1)
{
ERROR(errno, bh_error);
return -1;
}
result = binhx(ifile);
if (bh_end() == -1 && result == 0)
{
ERROR(errno, bh_error);
result = -1;
}
return result;
}
/*
* NAME: do_text()
* DESCRIPTION: perform copy using text translation
*/
static
int do_text(hfsfile *ifile, int ofile)
{
char buf[HFS_BLOCKSZ * 4], *ptr;
long chunk, bytes;
int len;
while (1)
{
chunk = hfs_read(ifile, buf, sizeof(buf));
if (chunk == -1)
{
ERROR(errno, hfs_error);
return -1;
}
else if (chunk == 0)
break;
for (ptr = buf; ptr < buf + chunk; ++ptr)
{
if (*ptr == '\r')
*ptr = '\n';
}
len = chunk;
ptr = cs_latin1(buf, &len);
if (ptr == 0)
{
ERROR(ENOMEM, 0);
return -1;
}
bytes = write(ofile, ptr, len);
free(ptr);
if (bytes == -1)
{
ERROR(errno, "error writing data");
return -1;
}
else if (bytes != len)
{
ERROR(EIO, "wrote incomplete chunk");
return -1;
}
}
return 0;
}
/*
* NAME: do_raw()
* DESCRIPTION: perform copy using no translation
*/
static
int do_raw(hfsfile *ifile, int ofile)
{
char buf[HFS_BLOCKSZ * 4];
long chunk, bytes;
while (1)
{
chunk = hfs_read(ifile, buf, sizeof(buf));
if (chunk == -1)
{
ERROR(errno, hfs_error);
return -1;
}
else if (chunk == 0)
break;
bytes = write(ofile, buf, chunk);
if (bytes == -1)
{
ERROR(errno, "error writing data");
return -1;
}
else if (bytes != chunk)
{
ERROR(EIO, "wrote incomplete chunk");
return -1;
}
}
return 0;
}
/* Utility Routines ======================================================== */
/*
* NAME: opensrc()
* DESCRIPTION: open the source file; set hint for destination filename
*/
static
hfsfile *opensrc(hfsvol *vol, const char *srcname,
const char **dsthint, const char *ext)
{
hfsfile *file;
hfsdirent ent;
static char name[HFS_MAX_FLEN + 4 + 1];
char *ptr;
file = hfs_open(vol, srcname);
if (file == 0)
{
ERROR(errno, hfs_error);
return 0;
}
if (hfs_fstat(file, &ent) == -1)
{
ERROR(errno, hfs_error);
hfs_close(file);
return 0;
}
strcpy(name, ent.name);
for (ptr = name; *ptr; ++ptr)
{
switch (*ptr)
{
case '/':
*ptr = '-';
break;
case ' ':
*ptr = '_';
break;
}
}
if (ext)
strcat(name, ext);
*dsthint = name;
return file;
}
/*
* NAME: opendst()
* DESCRIPTION: open the destination file
*/
static
int opendst(const char *dstname, const char *hint)
{
int fd;
if (strcmp(dstname, "-") == 0)
fd = dup(STDOUT_FILENO);
else
{
struct stat sbuf;
char *path = 0;
if (stat(dstname, &sbuf) != -1 &&
S_ISDIR(sbuf.st_mode))
{
path = malloc(strlen(dstname) + 1 + strlen(hint) + 1);
if (path == 0)
{
ERROR(ENOMEM, 0);
return -1;
}
strcpy(path, dstname);
strcat(path, "/");
strcat(path, hint);
dstname = path;
}
fd = open(dstname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (path)
free(path);
}
if (fd == -1)
{
ERROR(errno, "error opening destination file");
return -1;
}
return fd;
}
/*
* NAME: openfiles()
* DESCRIPTION: open source and destination files
*/
static
int openfiles(hfsvol *vol, const char *srcname, const char *dstname,
const char *ext, hfsfile **ifile, int *ofile)
{
const char *dsthint;
*ifile = opensrc(vol, srcname, &dsthint, ext);
if (*ifile == 0)
return -1;
*ofile = opendst(dstname, dsthint);
if (*ofile == -1)
{
hfs_close(*ifile);
return -1;
}
return 0;
}
/*
* NAME: closefiles()
* DESCRIPTION: close source and destination files
*/
static
void closefiles(hfsfile *ifile, int ofile, int *result)
{
if (close(ofile) == -1 && *result == 0)
{
ERROR(errno, "error closing destination file");
*result = -1;
}
if (hfs_close(ifile) == -1 && *result == 0)
{
ERROR(errno, hfs_error);
*result = -1;
}
}
/* Interface Routines ====================================================== */
/*
* NAME: cpo->macb()
* DESCRIPTION: copy an HFS file to a UNIX file using MacBinary II translation
*/
int cpo_macb(hfsvol *vol, const char *srcname, const char *dstname)
{
hfsfile *ifile;
int ofile, result = 0;
if (openfiles(vol, srcname, dstname, ".bin", &ifile, &ofile) == -1)
return -1;
result = do_macb(ifile, ofile);
closefiles(ifile, ofile, &result);
return result;
}
/*
* NAME: cpo->binh()
* DESCRIPTION: copy an HFS file to a UNIX file using BinHex translation
*/
int cpo_binh(hfsvol *vol, const char *srcname, const char *dstname)
{
hfsfile *ifile;
int ofile, result;
if (openfiles(vol, srcname, dstname, ".hqx", &ifile, &ofile) == -1)
return -1;
result = do_binh(ifile, ofile);
closefiles(ifile, ofile, &result);
return result;
}
/*
* NAME: cpo->text()
* DESCRIPTION: copy an HFS file to a UNIX file using text translation
*/
int cpo_text(hfsvol *vol, const char *srcname, const char *dstname)
{
const char *ext = 0;
hfsfile *ifile;
int ofile, result = 0;
if (strchr(srcname, '.') == 0)
ext = ".txt";
if (openfiles(vol, srcname, dstname, ext, &ifile, &ofile) == -1)
return -1;
result = do_text(ifile, ofile);
closefiles(ifile, ofile, &result);
return result;
}
/*
* NAME: cpo->raw()
* DESCRIPTION: copy the data fork of an HFS file to a UNIX file
*/
int cpo_raw(hfsvol *vol, const char *srcname, const char *dstname)
{
hfsfile *ifile;
int ofile, result = 0;
if (openfiles(vol, srcname, dstname, 0, &ifile, &ofile) == -1)
return -1;
result = do_raw(ifile, ofile);
closefiles(ifile, ofile, &result);
return result;
}

29
copyout.h Normal file
View File

@ -0,0 +1,29 @@
/*
* hfsutils - tools 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: copyout.h,v 1.7 1998/04/11 08:26:54 rob Exp $
*/
extern const char *cpo_error;
typedef int (*cpofunc)(hfsvol *, const char *, const char *);
int cpo_macb(hfsvol *, const char *, const char *);
int cpo_binh(hfsvol *, const char *, const char *);
int cpo_text(hfsvol *, const char *, const char *);
int cpo_raw(hfsvol *, const char *, const char *);

98
crc.c Normal file
View File

@ -0,0 +1,98 @@
/*
* hfsutils - tools 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: crc.c,v 1.8 1998/09/18 22:56:24 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include "crc.h"
static const
unsigned short magic[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
/*
* NAME: crc->binh()
* DESCRIPTION: compute BinHex-style CRC value for a block of data
*/
unsigned short crc_binh(register const unsigned char *ptr, register int count,
register unsigned short crc)
{
while (count--)
crc = ((crc << 8) | *ptr++) ^ magic[crc >> 8];
return crc;
}
/*
* NAME: crc->macb()
* DESCRIPTION: compute MacBinary II-style CRC value for a block of data
*/
unsigned short crc_macb(register const unsigned char *ptr, register int count,
register unsigned short crc)
{
while (count--)
{
crc ^= *ptr++ << 8;
crc = (crc << 8) ^ magic[crc >> 8];
}
return crc;
}

25
crc.h Normal file
View File

@ -0,0 +1,25 @@
/*
* hfsutils - tools 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: crc.h,v 1.7 1998/04/11 08:26:55 rob Exp $
*/
unsigned short crc_binh(register const unsigned char *, register int,
register unsigned short);
unsigned short crc_macb(register const unsigned char *, register int,
register unsigned short);

141
darray.c Normal file
View File

@ -0,0 +1,141 @@
/*
* hfsutils - tools 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: darray.c,v 1.7 1998/11/02 22:08:26 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdlib.h>
# include <string.h>
# include "darray.h"
struct _darray_ {
char *mem;
size_t memsz;
char *eltend;
size_t elemsz;
};
/*
* NAME: darray->new()
* DESCRIPTION: allocate and return a new dynamic array
*/
darray *darr_new(size_t elemsz)
{
darray *array;
array = malloc(sizeof(darray));
if (array == 0)
return 0;
array->memsz = 8 * elemsz;
array->mem = malloc(array->memsz);
if (array->mem == 0)
{
free(array);
return 0;
}
array->eltend = array->mem;
array->elemsz = elemsz;
return array;
}
/*
* NAME: darray->free()
* DESCRIPTION: dispose of a dynamic array
*/
void darr_free(darray *array)
{
free(array->mem);
free(array);
}
/*
* NAME: darray->size()
* DESCRIPTION: return the number of elements in a dynamic array
*/
unsigned int darr_size(darray *array)
{
return (array->eltend - array->mem) / array->elemsz;
}
/*
* NAME: darray->array()
* DESCRIPTION: return the array as an indexable block
*/
void *darr_array(darray *array)
{
return (void *) array->mem;
}
/*
* NAME: darray->append()
* DESCRIPTION: add an element to the end of a dynamic array
*/
void *darr_append(darray *array, void *elem)
{
char *eltend = array->eltend;
size_t elemsz = array->elemsz;
if ((size_t) (eltend - array->mem) == array->memsz)
{
char *newmem;
size_t newsz;
newsz = array->memsz * 2;
newmem = realloc(array->mem, newsz);
if (newmem == 0)
return 0;
eltend = newmem + array->memsz;
array->mem = newmem;
array->memsz = newsz;
}
memcpy(eltend, elem, elemsz);
array->eltend = eltend + elemsz;
return eltend;
}
/*
* NAME: darray->shrink()
* DESCRIPTION: truncate elements from the end of a dynamic array
*/
void darr_shrink(darray *array, unsigned int nelts)
{
if (nelts < (array->eltend - array->mem) / array->elemsz)
array->eltend = array->mem + nelts * array->elemsz;
}
/*
* NAME: darray->sort()
* DESCRIPTION: arrange items according to sorting criteria
*/
void darr_sort(darray *array, int (*compare)(const void *, const void *))
{
qsort(array->mem, (array->eltend - array->mem) / array->elemsz,
array->elemsz, compare);
}

30
darray.h Normal file
View File

@ -0,0 +1,30 @@
/*
* hfsutils - tools 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: darray.h,v 1.6 1998/04/11 08:26:55 rob Exp $
*/
typedef struct _darray_ darray;
darray *darr_new(size_t);
void darr_free(darray *);
unsigned int darr_size(darray *);
void *darr_array(darray *);
void *darr_append(darray *, void *);
void darr_shrink(darray *, unsigned int);
void darr_sort(darray *, int (*)(const void *, const void *));

119
dlist.c Normal file
View File

@ -0,0 +1,119 @@
/*
* hfsutils - tools 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: dlist.c,v 1.7 1998/11/02 22:08:27 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdlib.h>
# include <string.h>
# include "dlist.h"
/*
* NAME: dlist->init()
* DESCRIPTION: initialize a new dynamic list
*/
int dl_init(dlist *list)
{
list->memsz = 100;
list->mem = malloc(list->memsz);
if (list->mem == 0)
return -1;
list->eltend = (char **) list->mem;
list->strs = list->mem + list->memsz;
return 0;
}
/*
* NAME: dlist->free()
* DESCRIPTION: dispose of a dynamic list
*/
void dl_free(dlist *list)
{
free(list->mem);
}
/*
* NAME: dlist->array()
* DESCRIPTION: return the array of strings in a list; can dispose with free()
*/
char **dl_array(dlist *list)
{
return (char **) list->mem;
}
/*
* NAME: dlist->size()
* DESCRIPTION: return the number of strings in a list
*/
int dl_size(dlist *list)
{
return list->eltend - (char **) list->mem;
}
/*
* NAME: dlist->append()
* DESCRIPTION: insert a string to the end of a list
*/
int dl_append(dlist *list, const char *str)
{
size_t len;
len = strlen(str) + 1;
/* make sure there is room */
if (sizeof(char *) + len > (size_t) (list->strs - (char *) list->eltend))
{
dlist newlist;
size_t strsz;
char **elt;
strsz = (list->mem + list->memsz) - list->strs;
newlist.memsz = list->memsz * 2 + sizeof(char *) + len;
newlist.mem = malloc(newlist.memsz);
if (newlist.mem == 0)
return -1;
newlist.eltend = (char **) newlist.mem;
newlist.strs = newlist.mem + newlist.memsz - strsz;
memcpy(newlist.strs, list->strs, strsz);
for (elt = (char **) list->mem; elt < list->eltend; ++elt)
*newlist.eltend++ = newlist.strs + (*elt - list->strs);
free(list->mem);
*list = newlist;
}
list->strs -= len;
strcpy(list->strs, str);
*list->eltend++ = list->strs;
return 0;
}

33
dlist.h Normal file
View File

@ -0,0 +1,33 @@
/*
* hfsutils - tools 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: dlist.h,v 1.6 1998/04/11 08:26:55 rob Exp $
*/
typedef struct {
char *mem;
size_t memsz;
char **eltend;
char *strs;
} dlist;
int dl_init(dlist *);
void dl_free(dlist *);
char **dl_array(dlist *);
int dl_size(dlist *);
int dl_append(dlist *, const char *);

249
doc/charset.txt Normal file
View File

@ -0,0 +1,249 @@
hfsutils - tools for reading and writing Macintosh HFS volumes
Copyright (C) 1996-1998 Robert Leslie
$Id: charset.txt,v 1.4 1998/11/02 22:08:46 rob Exp $
===============================================================================
HFS uses the MacOS Standard Roman character set for volume, file, and path
names, as well as potentially for the data contained within some files.
Although MacOS Standard Roman shares the same characters as US ASCII for
values 0x00 through 0x7F, the remaining characters have values which are
primarily unique to MacOS Standard Roman.
The following is a translation table from MacOS Standard Roman to Unicode.
Note that ISO 8859-1 is a subset of Unicode, directly mapped from U+0000
through U+00FF. Since the Unicode values for MacOS Standard Roman characters
do not all fall within this range, it is not possible to map MacOS Standard
Roman completely and directly to ISO 8859-1 (and, incidentally, neither is it
possible to map ISO 8859-1 completely and directly to MacOS Standard Roman.)
(All numeric values in this table are hexadecimal.)
Part I: Control Characters (00 - 1F)
+----+--------+-----------------------+----+--------+--------------------------
|ASR |Unicode | Character |ASR |Unicode | Character
+----+--------+-----------------------+----+--------+--------------------------
| 00 | U+0000 | NULL | 10 | U+0010 | DATA LINK ESCAPE
| 01 | U+0001 | START OF HEADING | 11 | U+0011 | DEVICE CONTROL ONE
| 02 | U+0002 | START OF TEXT | 12 | U+0012 | DEVICE CONTROL TWO
| 03 | U+0003 | END OF TEXT | 13 | U+0013 | DEVICE CONTROL THREE
| 04 | U+0004 | END OF TRANSMISSION | 14 | U+0014 | DEVICE CONTROL FOUR
| 05 | U+0005 | ENQUIRY | 15 | U+0015 | NEGATIVE ACKNOWLEDGE
| 06 | U+0006 | ACKNOWLEDGE | 16 | U+0016 | SYNCHRONOUS IDLE
| 07 | U+0007 | BELL | 17 | U+0017 | END OF TRANSMISSION BLOCK
| 08 | U+0008 | BACKSPACE | 18 | U+0018 | CANCEL
| 09 | U+0009 | HORIZONTAL TABULATION | 19 | U+0019 | END OF MEDIUM
| 0A | U+000A | LINE FEED | 1A | U+001A | SUBSTITUTE
| 0B | U+000B | VERTICAL TABULATION | 1B | U+001B | ESCAPE
| 0C | U+000C | FORM FEED | 1C | U+001C | FILE SEPARATOR
| 0D | U+000D | CARRIAGE RETURN | 1D | U+001D | GROUP SEPARATOR
| 0E | U+000E | SHIFT OUT | 1E | U+001E | RECORD SEPARATOR
| 0F | U+000F | SHIFT IN | 1F | U+001F | UNIT SEPARATOR
+----+--------+-----------------------+----+--------+--------------------------
Part II: Printable ASCII Characters and Delete (20 - 7E, and 7F)
+----+--------+-------------------------+----+--------+------------------------
|ASR |Unicode | Character |ASR |Unicode | Character
+----+--------+-------------------------+----+--------+------------------------
| 20 | U+0020 | SPACE | 30 | U+0030 | DIGIT ZERO
| 21 | U+0021 | EXCLAMATION MARK | 31 | U+0031 | DIGIT ONE
| 22 | U+0022 | QUOTATION MARK | 32 | U+0032 | DIGIT TWO
| 23 | U+0023 | NUMBER SIGN | 33 | U+0033 | DIGIT THREE
| 24 | U+0024 | DOLLAR SIGN | 34 | U+0034 | DIGIT FOUR
| 25 | U+0025 | PERCENT SIGN | 35 | U+0035 | DIGIT FIVE
| 26 | U+0026 | AMPERSAND | 36 | U+0036 | DIGIT SIX
| 27 | U+0027 | APOSTROPHE | 37 | U+0037 | DIGIT SEVEN
| 28 | U+0028 | LEFT PARENTHESIS | 38 | U+0038 | DIGIT EIGHT
| 29 | U+0029 | RIGHT PARENTHESIS | 39 | U+0039 | DIGIT NINE
| 2A | U+002A | ASTERISK | 3A | U+003A | COLON
| 2B | U+002B | PLUS SIGN | 3B | U+003B | SEMICOLON
| 2C | U+002C | COMMA | 3C | U+003C | LESS-THAN SIGN
| 2D | U+002D | HYPHEN-MINUS | 3D | U+003D | EQUALS SIGN
| 2E | U+002E | FULL STOP | 3E | U+003E | GREATER-THAN SIGN
| 2F | U+002F | SOLIDUS | 3F | U+003F | QUESTION MARK
+----+--------+-------------------------+----+--------+------------------------
| 40 | U+0040 | COMMERCIAL AT | 50 | U+0050 | LATIN CAPITAL LETTER P
| 41 | U+0041 | LATIN CAPITAL LETTER A | 51 | U+0051 | LATIN CAPITAL LETTER Q
| 42 | U+0042 | LATIN CAPITAL LETTER B | 52 | U+0052 | LATIN CAPITAL LETTER R
| 43 | U+0043 | LATIN CAPITAL LETTER C | 53 | U+0053 | LATIN CAPITAL LETTER S
| 44 | U+0044 | LATIN CAPITAL LETTER D | 54 | U+0054 | LATIN CAPITAL LETTER T
| 45 | U+0045 | LATIN CAPITAL LETTER E | 55 | U+0055 | LATIN CAPITAL LETTER U
| 46 | U+0046 | LATIN CAPITAL LETTER F | 56 | U+0056 | LATIN CAPITAL LETTER V
| 47 | U+0047 | LATIN CAPITAL LETTER G | 57 | U+0057 | LATIN CAPITAL LETTER W
| 48 | U+0048 | LATIN CAPITAL LETTER H | 58 | U+0058 | LATIN CAPITAL LETTER X
| 49 | U+0049 | LATIN CAPITAL LETTER I | 59 | U+0059 | LATIN CAPITAL LETTER Y
| 4A | U+004A | LATIN CAPITAL LETTER J | 5A | U+005A | LATIN CAPITAL LETTER Z
| 4B | U+004B | LATIN CAPITAL LETTER K | 5B | U+005B | LEFT SQUARE BRACKET
| 4C | U+004C | LATIN CAPITAL LETTER L | 5C | U+005C | REVERSE SOLIDUS
| 4D | U+004D | LATIN CAPITAL LETTER M | 5D | U+005D | RIGHT SQUARE BRACKET
| 4E | U+004E | LATIN CAPITAL LETTER N | 5E | U+005E | CIRCUMFLEX ACCENT
| 4F | U+004F | LATIN CAPITAL LETTER O | 5F | U+005F | LOW LINE
+----+--------+-------------------------+----+--------+------------------------
| 60 | U+0060 | GRAVE ACCENT | 70 | U+0070 | LATIN SMALL LETTER P
| 61 | U+0061 | LATIN SMALL LETTER A | 71 | U+0071 | LATIN SMALL LETTER Q
| 62 | U+0062 | LATIN SMALL LETTER B | 72 | U+0072 | LATIN SMALL LETTER R
| 63 | U+0063 | LATIN SMALL LETTER C | 73 | U+0073 | LATIN SMALL LETTER S
| 64 | U+0064 | LATIN SMALL LETTER D | 74 | U+0074 | LATIN SMALL LETTER T
| 65 | U+0065 | LATIN SMALL LETTER E | 75 | U+0075 | LATIN SMALL LETTER U
| 66 | U+0066 | LATIN SMALL LETTER F | 76 | U+0076 | LATIN SMALL LETTER V
| 67 | U+0067 | LATIN SMALL LETTER G | 77 | U+0077 | LATIN SMALL LETTER W
| 68 | U+0068 | LATIN SMALL LETTER H | 78 | U+0078 | LATIN SMALL LETTER X
| 69 | U+0069 | LATIN SMALL LETTER I | 79 | U+0079 | LATIN SMALL LETTER Y
| 6A | U+006A | LATIN SMALL LETTER J | 7A | U+007A | LATIN SMALL LETTER Z
| 6B | U+006B | LATIN SMALL LETTER K | 7B | U+007B | LEFT CURLY BRACKET
| 6C | U+006C | LATIN SMALL LETTER L | 7C | U+007C | VERTICAL LINE
| 6D | U+006D | LATIN SMALL LETTER M | 7D | U+007D | RIGHT CURLY BRACKET
| 6E | U+006E | LATIN SMALL LETTER N | 7E | U+007E | TILDE
| 6F | U+006F | LATIN SMALL LETTER O | 7F | U+007F | DELETE
+----+--------+-------------------------+----+--------+------------------------
Part III: Extended Characters (80 - FF)
+----+--------+----------------------------------------------------------------
|ASR |Unicode | Character
+----+--------+----------------------------------------------------------------
| 80 | U+00C4 | LATIN CAPITAL LETTER A WITH DIAERESIS
| 81 | U+00C5 | LATIN CAPITAL LETTER A WITH RING ABOVE
| 82 | U+00C7 | LATIN CAPITAL LETTER C WITH CEDILLA
| 83 | U+00C9 | LATIN CAPITAL LETTER E WITH ACUTE
| 84 | U+00D1 | LATIN CAPITAL LETTER N WITH TILDE
| 85 | U+00D6 | LATIN CAPITAL LETTER O WITH DIAERESIS
| 86 | U+00DC | LATIN CAPITAL LETTER U WITH DIAERESIS
| 87 | U+00E1 | LATIN SMALL LETTER A WITH ACUTE
| 88 | U+00E0 | LATIN SMALL LETTER A WITH GRAVE
| 89 | U+00E2 | LATIN SMALL LETTER A WITH CIRCUMFLEX
| 8A | U+00E4 | LATIN SMALL LETTER A WITH DIAERESIS
| 8B | U+00E3 | LATIN SMALL LETTER A WITH TILDE
| 8C | U+00E5 | LATIN SMALL LETTER A WITH RING ABOVE
| 8D | U+00E7 | LATIN SMALL LETTER C WITH CEDILLA
| 8E | U+00E9 | LATIN SMALL LETTER E WITH ACUTE
| 8F | U+00E8 | LATIN SMALL LETTER E WITH GRAVE
+----+--------+----------------------------------------------------------------
| 90 | U+00EA | LATIN SMALL LETTER E WITH CIRCUMFLEX
| 91 | U+00EB | LATIN SMALL LETTER E WITH DIAERESIS
| 92 | U+00ED | LATIN SMALL LETTER I WITH ACUTE
| 93 | U+00EC | LATIN SMALL LETTER I WITH GRAVE
| 94 | U+00EE | LATIN SMALL LETTER I WITH CIRCUMFLEX
| 95 | U+00EF | LATIN SMALL LETTER I WITH DIAERESIS
| 96 | U+00F1 | LATIN SMALL LETTER N WITH TILDE
| 97 | U+00F3 | LATIN SMALL LETTER O WITH ACUTE
| 98 | U+00F2 | LATIN SMALL LETTER O WITH GRAVE
| 99 | U+00F4 | LATIN SMALL LETTER O WITH CIRCUMFLEX
| 9A | U+00F6 | LATIN SMALL LETTER O WITH DIAERESIS
| 9B | U+00F5 | LATIN SMALL LETTER O WITH TILDE
| 9C | U+00FA | LATIN SMALL LETTER U WITH ACUTE
| 9D | U+00F9 | LATIN SMALL LETTER U WITH GRAVE
| 9E | U+00FB | LATIN SMALL LETTER U WITH CIRCUMFLEX
| 9F | U+00FC | LATIN SMALL LETTER U WITH DIAERESIS
+----+--------+----------------------------------------------------------------
| A0 | U+2020 | DAGGER
| A1 | U+00B0 | DEGREE SIGN
| A2 | U+00A2 | CENT SIGN
| A3 | U+00A3 | POUND SIGN
| A4 | U+00A7 | SECTION SIGN
| A5 | U+2022 | BULLET
| A6 | U+00B6 | PILCROW SIGN
| A7 | U+00DF | LATIN SMALL LETTER SHARP S
| A8 | U+00AE | REGISTERED SIGN
| A9 | U+00A9 | COPYRIGHT SIGN
| AA | U+2122 | TRADE MARK SIGN
| AB | U+00B4 | ACUTE ACCENT
| AC | U+00A8 | DIAERESIS
| AD | U+2260 | NOT EQUAL TO
| AE | U+00C6 | LATIN CAPITAL LIGATURE AE
| AF | U+00D8 | LATIN CAPITAL LETTER O WITH STROKE
+----+--------+----------------------------------------------------------------
| B0 | U+221E | INFINITY
| B1 | U+00B1 | PLUS-MINUS SIGN
| B2 | U+2264 | LESS-THAN OR EQUAL TO
| B3 | U+2265 | GREATER-THAN OR EQUAL TO
| B4 | U+00A5 | YEN SIGN
| B5 | U+00B5 | MICRO SIGN
| B6 | U+2202 | PARTIAL DIFFERENTIAL
| B7 | U+2211 | N-ARY SUMMATION
| B8 | U+220F | N-ARY PRODUCT
| B9 | U+03C0 | GREEK SMALL LETTER PI
| BA | U+222B | INTEGRAL
| BB | U+00AA | FEMININE ORDINAL INDICATOR
| BC | U+00BA | MASCULINE ORDINAL INDICATOR
| BD | U+2126 | OHM SIGN
| BE | U+00E6 | LATIN SMALL LIGATURE AE
| BF | U+00F8 | LATIN SMALL LETTER O WITH STROKE
+----+--------+----------------------------------------------------------------
| C0 | U+00BF | INVERTED QUESTION MARK
| C1 | U+00A1 | INVERTED EXCLAMATION MARK
| C2 | U+00AC | NOT SIGN
| C3 | U+221A | SQUARE ROOT
| C4 | U+0192 | LATIN SMALL LETTER F WITH HOOK
| C5 | U+2248 | ALMOST EQUAL TO
| C6 | U+2206 | INCREMENT
| C7 | U+00AB | LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
| C8 | U+00BB | RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
| C9 | U+2026 | HORIZONTAL ELLIPSIS
| CA | U+00A0 | NO-BREAK SPACE
| CB | U+00C0 | LATIN CAPITAL LETTER A WITH GRAVE
| CC | U+00C3 | LATIN CAPITAL LETTER A WITH TILDE
| CD | U+00D5 | LATIN CAPITAL LETTER O WITH TILDE
| CE | U+0152 | LATIN CAPITAL LIGATURE OE
| CF | U+0153 | LATIN SMALL LIGATURE OE
+----+--------+----------------------------------------------------------------
| D0 | U+2013 | EN DASH
| D1 | U+2014 | EM DASH
| D2 | U+201C | LEFT DOUBLE QUOTATION MARK
| D3 | U+201D | RIGHT DOUBLE QUOTATION MARK
| D4 | U+2018 | LEFT SINGLE QUOTATION MARK
| D5 | U+2019 | RIGHT SINGLE QUOTATION MARK
| D6 | U+00F7 | DIVISION SIGN
| D7 | U+25CA | LOZENGE
| D8 | U+00FF | LATIN SMALL LETTER Y WITH DIAERESIS
| D9 | U+0178 | LATIN CAPITAL LETTER Y WITH DIAERESIS
| DA | U+2044 | FRACTION SLASH
| DB | U+00A4 | CURRENCY SIGN
| DC | U+2039 | SINGLE LEFT-POINTING ANGLE QUOTATION MARK
| DD | U+203A | SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
| DE | U+FB01 | LATIN SMALL LIGATURE FI
| DF | U+FB02 | LATIN SMALL LIGATURE FL
+----+--------+----------------------------------------------------------------
| E0 | U+2021 | DOUBLE DAGGER
| E1 | U+00B7 | MIDDLE DOT
| E2 | U+201A | SINGLE LOW-9 QUOTATION MARK
| E3 | U+201E | DOUBLE LOW-9 QUOTATION MARK
| E4 | U+2030 | PER MILLE SIGN
| E5 | U+00C2 | LATIN CAPITAL LETTER A WITH CIRCUMFLEX
| E6 | U+00CA | LATIN CAPITAL LETTER E WITH CIRCUMFLEX
| E7 | U+00C1 | LATIN CAPITAL LETTER A WITH ACUTE
| E8 | U+00CB | LATIN CAPITAL LETTER E WITH DIAERESIS
| E9 | U+00C8 | LATIN CAPITAL LETTER E WITH GRAVE
| EA | U+00CD | LATIN CAPITAL LETTER I WITH ACUTE
| EB | U+00CE | LATIN CAPITAL LETTER I WITH CIRCUMFLEX
| EC | U+00CF | LATIN CAPITAL LETTER I WITH DIAERESIS
| ED | U+00CC | LATIN CAPITAL LETTER I WITH GRAVE
| EE | U+00D3 | LATIN CAPITAL LETTER O WITH ACUTE
| EF | U+00D4 | LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+----+--------+----------------------------------------------------------------
| F0 | U+F8FF | Apple logo
| F1 | U+00D2 | LATIN CAPITAL LETTER O WITH GRAVE
| F2 | U+00DA | LATIN CAPITAL LETTER U WITH ACUTE
| F3 | U+00DB | LATIN CAPITAL LETTER U WITH CIRCUMFLEX
| F4 | U+00D9 | LATIN CAPITAL LETTER U WITH GRAVE
| F5 | U+0131 | LATIN SMALL LETTER DOTLESS I
| F6 | U+02C6 | MODIFIER LETTER CIRCUMFLEX ACCENT
| F7 | U+02DC | SMALL TILDE
| F8 | U+00AF | MACRON
| F9 | U+02D8 | BREVE
| FA | U+02D9 | DOT ABOVE
| FB | U+02DA | RING ABOVE
| FC | U+00B8 | CEDILLA
| FD | U+02DD | DOUBLE ACUTE ACCENT
| FE | U+02DB | OGONEK
| FF | U+02C7 | CARON
+----+--------+----------------------------------------------------------------
===============================================================================

517
doc/libhfs.txt Normal file
View File

@ -0,0 +1,517 @@
This file documents the libhfs.a library for accessing HFS volumes.
Copyright (C) 1996-1998 Robert Leslie
$Id: libhfs.txt,v 1.11 1998/11/02 22:08:47 rob Exp $
===============================================================================
Exported Data
const char *hfs_error;
This contains a pointer to a C string describing the last HFS error.
It is generally only valid after an HFS routine has returned an error
code (-1 or a NULL pointer).
This string is encoded using ISO 8859-1.
In all cases when an error occurs, the global variable `errno' is also
set to an appropriate value.
unsigned char hfs_charorder[];
This array contains the relative sorting order of characters in HFS
filenames according to the semantics of the Macintosh character set
and the MacOS string comparison routines as used by HFS. The array can
be indexed by unsigned character quantities; the resulting value can be
compared to other array values to determine the relative sorting order
of the corresponding character indices.
Public Routines
----- Volume Routines -----
hfsvol *hfs_mount(const char *path, int pnum, int flags);
This routine attempts to open an HFS volume from a source pathname. The
given `pnum' indicates which ordinal HFS partition is to be mounted,
or can be 0 to indicate the entire medium should be mounted (ignoring
any partition structure). If this value is not 0, the requested
partition must exist.
The `flags' argument specifies how the volume should be mounted.
HFS_MODE_RDONLY means the volume should be mounted read-only.
HFS_MODE_RDWR means the volume must be opened read/write. HFS_MODE_ANY
means the volume can be mounted either read-only or read/write, with
preference for the latter.
The `flags' argument may also specify volume options. HFS_OPT_NOCACHE
means not to perform any internal block caching, such as would be
unnecessary for a volume residing in RAM, or if the associated overhead
is not desired. HFS_OPT_ZERO means that newly-allocated blocks should be
zero-initialized before use, primarily as a security feature for systems
on which blocks may otherwise contain random data. Neither of these
options should normally be necessary, and both may affect performance.
If an error occurs, this function returns NULL. Otherwise a pointer to a
volume structure is returned. This pointer is used to access the volume
and must eventually be passed to hfs_umount() to flush and close the
volume and free all associated memory.
int hfs_flush(hfsvol *vol);
This routine causes all pending changes to be flushed to an HFS volume.
If a volume is kept open for a long period of time, it would be wise
to call this periodically to avoid corrupting the volume due to
unforeseen circumstances (power failure, floppy eject, etc.)
If an error occurs, this function returns -1. Otherwise it returns 0.
void hfs_flushall(void);
This routine is similar to hfs_flush() except that all mounted volumes
are flushed, and errors are not reported.
int hfs_umount(hfsvol *vol);
The specified HFS volume is unmounted; all open files and directories
on the volume are closed, all pending changes to the volume are
flushed, and all memory allocated for the volume is freed.
All volumes opened with hfs_mount() must eventually be closed with
hfs_umount(), or they will risk corruption.
If an error occurs, this function returns -1. Otherwise it returns 0.
In either case, the volume structure pointer will become invalid, as
will all pointers to open file or directory structures associated with
the volume.
void hfs_umountall(void);
This routine is similar to hfs_umount() except that all mounted volumes
are closed, and errors are not reported.
This routine may be useful to call just before a process terminates to
make sure any remaining open volumes are properly closed.
hfsvol *hfs_getvol(const char *name);
This routines searches all mounted volumes for one having the given
`name', and returns its volume structure pointer. If more than one
volume have the same name, the most recently mounted one is returned. If
no volume matches the given name, a NULL pointer is returned.
The given `name' is assumed to be encoded using MacOS Standard Roman.
If a NULL pointer is passed to this routine, the current volume is
returned, if any.
void hfs_setvol(hfsvol *vol);
The routine changes the "current" volume. Most HFS routines will accept
a NULL volume pointer to mean the current volume; by default, the
current volume is the last one which was mounted.
int hfs_vstat(hfsvol *vol, hfsvolent *ent);
This routine fills the volume entity structure `*ent' with information
about a mounted volume. The fields of the structure are defined in
the hfs.h header file.
This routine returns 0 unless a NULL pointer is passed for the volume
and no volume is current, in which case it returns -1.
int hfs_vsetattr(hfsvol *vol, hfsvolent *ent);
This routine allows some attributes of a volume to be changed. The
attributes which may be changed are: ent->clumpsz, ent->crdate,
ent->mddate, ent->bkdate, and ent->blessed. Note that the default file
clump size may only be changed to be a multiple of the volume's
allocation block size, and the "blessed" folder must either be 0 or a
valid folder CNID.
To change the volume's name, use hfs_rename().
If an error occurs, this function returns -1. Otherwise it returns 0.
----- Directory Routines -----
int hfs_chdir(hfsvol *vol, const char *path);
The "current working directory" for the given volume is changed.
`path' can be either a relative or absolute HFS path.
The given `path' is assumed to be encoded using MacOS Standard Roman.
If an error occurs, this function returns -1. Otherwise it returns 0.
long hfs_getcwd(hfsvol *vol);
The internal directory ID of the current working directory for the
given volume is returned. This value is typically only useful for
passing to hfs_setcwd() or hfs_dirinfo().
int hfs_setcwd(hfsvol *vol, long id);
This routine changes the current working directory for the given
volume. A directory must exist with the given id.
If an error occurs, this function returns -1. Otherwise it returns 0.
int hfs_dirinfo(hfsvol *vol, long *id, char *name);
This function looks up the given directory ID `*id' and stores in its
place the directory ID of its parent. If `name' is not NULL, the name
of the (child) directory is also stored in the buffer pointed to by it,
which must be at least HFS_MAX_FLEN + 1 (32) bytes long.
The string `name' will be encoded using MacOS Standard Roman.
If an error occurs, this function returns -1. Otherwise it returns 0.
This function can be called repeatedly to construct a full pathname
to the current working directory. The root directory of a volume
always has a directory ID of HFS_CNID_ROOTDIR, and a pseudo-parent ID
of HFS_CNID_ROOTPAR.
hfsdir *hfs_opendir(hfsvol *vol, const char *path);
This function prepares to read the contents of a directory. `path'
must be either an absolute or relative pathname to the desired HFS
directory. As a special case, if `path' is an empty string, a
"meta-directory" will be opened containing the root directories from
all of the currently mounted volumes.
The string `path' is assumed to be encoded using MacOS Standard Roman.
This function returns a pointer which must be passed to the other
directory-related routines to read the directory.
If an error occurs, this function returns a NULL pointer.
int hfs_readdir(hfsdir *dir, hfsdirent *ent);
This routine fills the directory entity structure `*ent' with
information about the next item in the given open directory. The
fields of the structure are defined in the hfs.h header file.
If an error occurs, this function returns -1. Otherwise it returns 0.
When no more items occur in the directory, this function returns -1
and sets `errno' to ENOENT.
int hfs_closedir(hfsdir *dir);
This function closes an open directory and frees all associated
memory.
If an error occurs, this function returns -1. Otherwise it returns 0.
In either case, the directory structure pointer will no longer be valid.
----- File Routines -----
hfsfile *hfs_create(hfsvol *vol, const char *path,
const char *type, const char *creator);
This routine creates a new, empty file with the given path, type, and
creator. The type and creator must be strings of length 4, and have
particular meaning under MacOS.
The given `path' is assumed to be encoded using MacOS Standard Roman.
If the creation is successful, the file is opened and a pointer to a
file structure is returned, the same as if hfs_open() had been called.
If an error occurs, this function returns a NULL pointer.
hfsfile *hfs_open(hfsvol *vol, const char *path);
This function opens an HFS file in preparation for I/O. Both forks of
the file may be manipulated once the file is opened; hfs_setfork() is
used to select the current fork. By default, the data fork is current.
The given `path' is assumed to be encoded using MacOS Standard Roman.
A pointer to a file structure is returned. This pointer should be
passed to other routines to manipulate the file.
If an error occurs, this function returns a NULL pointer.
int hfs_setfork(hfsfile *file, int fork);
This routine selects the current fork in an open file for I/O. HFS
files have two forks, data and resource. Resource forks normally contain
structured data, although these HFS routines make no distinction
between forks when reading or writing. It is up to higher-level
applications to make sense of the information read or written from
either fork.
If 0 is passed to this routine, the data fork is selected. Otherwise
the resource fork is selected. The seek pointer for the file is
automatically reset to the beginning of the newly selected fork.
As a side effect, this routine causes any excess disk blocks allocated
for the fork which was current before the call to be freed; normally
extra blocks are allocated during file writes to promote contiguity.
This routine will return -1 if an error occurs in this process;
otherwise it will return 0. The current fork will have been changed
regardless.
int hfs_getfork(hfsfile *file);
This routine returns an indication of which fork is currently active
for I/O operations on the given file. If 0 is returned, the data fork
is selected. Otherwise the resource fork is selected.
long hfs_read(hfsfile *file, void *ptr, unsigned long len);
This routine reads up to `len' bytes from the current fork of an HFS
file and places them into the buffer pointed to by `ptr' (which must be
at least `len' bytes long.) The number of bytes actually read is
returned, and may be less than `len' if the end of the file is reached.
If this routine returns 0, there is no more data to be read from the
file. If an error occurs, this routine will return -1.
It is most efficient to read data in multiples of HFS_BLOCKSZ byte
blocks at a time.
long hfs_write(hfsfile *file, const void *ptr, unsigned long len);
This routine writes up to `len' bytes of data to the current fork of an
HFS file from the buffer pointed to by `ptr'. The number of bytes
actually written is returned. If an error occurs, this routine will
return -1.
If the end of the file is reached before all bytes have been written,
the file is automatically extended.
It is most efficient to write data in multiples of HFS_BLOCKSZ byte
blocks at a time.
int hfs_truncate(hfsfile *file, unsigned long len);
This routine causes the current fork of the specified open file to be
truncated to at most `len' bytes.
The disk blocks associated with the freed portion of the file are not
actually deallocated until either the current fork is changed or the
file is closed.
If an error occurs, this function returns -1. Otherwise it returns 0.
long hfs_seek(hfsfile *file, long offset, int from);
This routine changes the current seek pointer for the specified open
file. This pointer determines where the next call to hfs_read() or
hfs_write() will read or write data within the current fork.
If `from' is HFS_SEEK_SET, the pointer is set to the absolute position
given by `offset'.
If `from' is HFS_SEEK_CUR, the pointer is offset from its current
position by the amount `offset'. Positive offsets seek forward; negative
offsets seek backward.
If `from' is HFS_SEEK_END, the pointer is offset from the end of the
file by the amount `offset', which ought not be positive.
It is not presently possible to set the seek pointer beyond the logical
end of the file.
The new absolute position of the seek pointer is returned, unless an
invalid argument was specified, in which case -1 is returned.
int hfs_close(hfsfile *file);
This routine causes all pending changes to the specified file to be
flushed, and all storage associated with the file structure to be
freed. Any excess disk blocks associated with the file are also
deallocated at this time.
If an error occurs, this routine returns -1. Otherwise it returns 0.
In either case, the file structure pointer will no longer be valid.
----- Catalog Routines -----
int hfs_stat(hfsvol *vol, const char *path, hfsdirent *ent);
This routine fills the directory entity structure `*ent' with
information about the file or directory specified by `path' on the
given volume. The fields of the structure are defined in the hfs.h
header file.
The given `path' is assumed to be encoded using MacOS Standard Roman.
If there is no such path, or if another error occurs, this routine
returns -1. Otherwise it returns 0.
int hfs_fstat(hfsfile *file, hfsdirent *ent);
This routine is similar to hfs_stat() except it returns information
about a file that is already open.
If an error occurs, this routine returns -1. Otherwise it returns 0.
int hfs_setattr(hfsvol *vol, const char *path, const hfsdirent *ent);
This routine changes various attributes of an existing file or
directory. The attributes which may be changed are: ent->crdate,
ent->mddate, ent->bkdate, ent->fdflags, ent->fdlocation,
ent->u.file.type, ent->u.file.creator, and ent->u.dir.rect. Also, the
locked status of a file may be changed with ent->flags & HFS_ISLOCKED.
The given `path' is assumed to be encoded using MacOS Standard Roman.
If an error occurs, this routine returns -1. Otherwise it returns 0.
int hfs_fsetattr(hfsfile *file, const hfsdirent *ent);
This routine is similar to hfs_setattr() except it manipulates a file
that is already open.
If an error occurs, this routine returns -1. Otherwise it returns 0.
int hfs_mkdir(hfsvol *vol, const char *path);
This routine creates a new, empty directory with the given path.
All parent directories must already exist, but there must not already
be a file or directory with the complete given path.
The given `path' is assumed to be encoded using MacOS Standard Roman.
If an error occurs, this function returns -1. Otherwise it returns 0.
int hfs_rmdir(hfsvol *vol, const char *path);
This routine deletes the directory with the given path. The directory
must be empty.
The given `path' is assumed to be encoded using MacOS Standard Roman.
If an error occurs, this function returns -1. Otherwise it returns 0.
int hfs_delete(hfsvol *vol, const char *path);
This routine deletes both forks of the file with the given path.
The given `path' is assumed to be encoded using MacOS Standard Roman.
If an error occurs, this function returns -1. Otherwise it returns 0.
int hfs_rename(hfsvol *vol, const char *srcpath, const char *dstpath);
This routine moves and/or renames the given `srcpath' to `dstpath'.
The source must exist; the destination must not exist, unless it is a
directory, in which case an attempt will be made to move the source
into the destination directory without changing its name.
If both `srcpath' and `dstpath' refer to root directories, the volume
specified by `srcpath' will be renamed. Note that volume names may
only have 1-27 (HFS_MAX_VLEN) characters, while all other names may
have 1-31 (HFS_MAX_FLEN) characters.
The given `srcpath' and `dstpath' are assumed to be encoded using MacOS
Standard Roman.
If an error occurs, this function returns -1. Otherwise it returns 0.
----- Media Routines -----
int hfs_zero(const char *path, unsigned int maxparts,
unsigned long *blocks);
This routine initializes a medium with a new, empty driver descriptor
record and partition map. This is only necessary if it is desired to
partition the medium; the medium can be used as a whole without
partitions by specifying 0 to the routines which require a partition
number.
The partition map will be empty, with the exception of an entry for the
partition map itself, plus an entry for the rest of the medium as free
space. To be useful, one or more HFS partitions should be created with
hfs_mkpart().
The partition map will be created just large enough to allow `maxparts'
individual partitions to be created, not counting the partitions created
automatically by this routine. This number should be conservative, as
it may be impossible to create more than this many partitions for the
lifetime of the medium without re-initializing.
If `blocks' is not NULL, the total number of blocks available for
partitioning (after the partition map structures have been created) will
be stored at this location.
If an error occurs, this function returns -1. Otherwise it returns 0.
int hfs_mkpart(const char *path, unsigned long len);
This routine creates a new HFS partition having `len' blocks on the
given medium. Space for the partition will be taken from the available
free space as indicated in the existing partition map.
It may not be possible to create the requested partition if there are
not enough free contiguous blocks on the medium, or if there is only
one slot left in the partition map and the request does not specify
all the remaining blocks in the free space. (The partition map cannot
leave any blocks in the medium unaccounted for.)
If an error occurs, this function returns -1. Otherwise it returns 0.
int hfs_nparts(const char *path);
This routine determines the number of HFS partitions present on the
given medium, if any. If the medium specified by `path' is not
partitioned, -1 will be returned. Otherwise, a number denoting the total
number of HFS partitions is returned, including (possibly) 0.
The number returned by this routine can help determine if a particular
medium is partitioned, and if so, the allowable range of partition
numbers which can be passed to the routines which require one. However,
passing 0 as a partition number always refers to the entire medium,
ignoring all partitions.
If an error occurs, this function returns -1.
int hfs_format(const char *path, int pnum, int mode, const char *vname,
int nbadblocks, const unsigned long badblocks[]);
This routine writes a new HFS file system to the specified `path', which
should be a block device or a writable file. The size of the volume is
determined either by the maximum size of the device or size of the file,
or by the size of the indicated partition within the medium.
If `pnum' is > 0, it selects an ordinal HFS partition in the device
to receive the file system. The partition must already exist; an error
will result if it cannot be found. With `pnum' == 0, any partition
structure on the existing medium will be ignored, and the entire
device will be used for the new HFS volume.
Volume options may be specified in the `mode' argument. In addition to
the options accepted by hfs_mount(), HFS_OPT_2048 may be specified to
request that the volume allocation blocks be aligned on physical
2048-byte block boundaries. Such a constraint is necessary to support
some hybrid CD-ROM file system formats, but is otherwise unnecessary and
may result in fewer allocation blocks altogether.
The volume is given the name `vname', which must be between 1 and
HFS_MAX_VLEN (27) characters in length inclusively, and cannot contain
any colons (':'). This string is assumed to be encoded using MacOS
Standard Roman.
It is possible to map out or "spare" bad blocks on the device such that
the file system will be made aware of these blocks and will not attempt
to use them to store data. To perform this magic, hfs_format() may be
passed an array of block numbers to spare. These numbers must
correspond to logical 512-byte blocks on the device and should be
relative to the beginning of the volume's partition, if any. If no
blocks need to be spared, 0 should be passed for `nbadblocks', and
`badblocks' may be a NULL pointer. Note that an error can occur if a
bad block occurs in a critical disk structure, or if there are too
many bad blocks (more than 25%) in the volume.
If an error occurs, this function returns -1. Otherwise it returns 0.
===============================================================================

119
doc/librsrc.txt Normal file
View File

@ -0,0 +1,119 @@
This file documents the librsrc.a library for accessing resource forks.
Copyright (C) 1996-1998 Robert Leslie
$Id: librsrc.txt,v 1.6 1998/09/19 05:06:32 rob Exp $
===============================================================================
Exported Data
const char *rsrc_error;
This contains a pointer to a C string describing the last resource
library error. It is generally only valid after a resource routine has
returned an error code (-1 or a NULL pointer).
In all cases when an error occurs, the global variable `errno' is also
set to an appropriate value.
Public Routines
rsrcfile *rsrc_init(void *priv, const rsrcprocs *procs);
This routine prepares an open file access path to be treated as a
Macintosh resource fork. `priv' is treated as private file access data,
and is passed transparently as the first argument to each of:
procs->seek(priv, ...);
procs->read(priv, ...);
procs->write(priv, ...);
Normally when using this library with libhfs, `priv' will be the
`hfsfile *' returned from hfs_open(), and `procs' will point to a
structure containing { hfs_seek, hfs_read, hfs_write }.
However, any suitable routines may be substituted which accept
the appropriate arguments.
Note that the file access path must already exist, and must be ready
to read and/or write resource data. When using libhfs, this means
hfs_setfork(..., 1) must be called prior to rsrc_init().
If an error occurs, this function returns -1. Otherwise it returns 0.
int rsrc_finish(rsrcfile *rfile);
Calling this routine causes the library to flush all changes to the
given resource file `rfile', and release all storage associated with it.
Note that this routine does not close the underlying file access path;
this must be done separately after calling rsrc_finish().
If an error occurs, this function returns -1. Otherwise it returns 0.
int rsrc_counttypes(rsrcfile *rfile);
This function returns the number of unique resource types in the given
resource file `rfile'.
int rsrc_count(rsrcfile *rfile, const char *type);
This function returns the number of actual resources in the given
resource file `rfile' of the given type `type', which must be a pointer
to a four-character string naming the type.
void rsrc_gettype(rsrcfile *rfile, int index, char *type);
This routine stores at `type' a four-character string (plus terminating
null) representing a resource type present in the given resource file
`rfile'. The ordinal `index' must be from 1 to the total number of
types present in the file, given by rsrc_counttypes().
If `index' is out of range, the effect of this function is undefined.
void *rsrc_get(rsrcfile *rfile, const char *type, int id);
This routine fetches an individual resource identified by the given
`type' and `id' from the resource file `rfile' and returns a pointer to
the beginning of a block containing the resource data.
The pointer returned by this function can be passed to other routines
in this library to manipulate the resource, and must finally be passed
to rsrc_release() when the resource is no longer needed.
If this function fails, a NULL pointer will be returned.
void *rsrc_getnamed(rsrcfile *rfile, const char *type, const char *name);
Like rsrc_get(), except the resource is identified by the given `name'
instead of by id.
void *rsrc_getind(rsrcfile *rfile, const char *type, int index);
Like rsrc_get(), except the resource is identified by the ordinal
`index' instead of by id. The `index' must be from 1 to the total number
of resources of type `type', given by rsrc_count().
unsigned long rsrc_size(void *rdata);
This function returns the size (in bytes) of the given resource `rdata'.
void *rsrc_resize(void *rdata, unsigned long len);
This routine changes the size of the resource data `rdata' to be `len'.
The resource data will be unchanged up to the lesser of the original
size and the new size; newly allocated space will be uninitialized.
If there is not enough memory to hold the new requested size, a NULL
pointer is returned and the original `rdata' pointer remains valid.
Otherwise, a new resource data pointer is returned and the original
becomes invalid.
void rsrc_release(void *rdata);
This function releases the resource data `rdata'. It should be called
once the data is no longer needed so the associated memory can be freed.
===============================================================================

46
doc/man/hattrib.1 Normal file
View File

@ -0,0 +1,46 @@
.TH HATTRIB 1 30-Aug-1998 HFSUTILS
.SH NAME
hattrib \- change HFS file or directory attributes
.SH SYNOPSIS
hattrib
[-t
.IR TYPE ]
[-c
.IR CREA ]
[-|+i] [-|+l]
.I hfs-path
[...]
.PP
hattrib -b
.I hfs-path
.SH DESCRIPTION
.B hattrib
permits the alteration of HFS file attributes. In the first form, the
MacOS-defined
.I type
and
.I creator
attributes can be set using the -t and -c flags, respectively. A file's
.I invisible
flag can be set or cleared with +i and -i, respectively. Finally, a file's
.I locked
flag can be set or cleared with +l and -l.
.PP
All files mentioned on the command line will receive the specified attributes,
regardless of the file's current attributes. Any attribute not mentioned in
the command line is left unchanged.
.PP
In the second form, a single HFS pathname refering to a folder is given with
the -b option, causing it to become "blessed" as the MacOS System Folder. For
this to be useful, the folder should contain valid Macintosh System and Finder
files.
.PP
Note that the
.I locked
and "blessed" attributes have little consequence to hfsutils.
.SH SEE ALSO
hfsutils(1), hls(1)
.SH FILES
$HOME/.hcwd
.SH AUTHOR
Robert Leslie <rob@mars.org>

31
doc/man/hcd.1 Normal file
View File

@ -0,0 +1,31 @@
.TH HCD 1 13-Jan-1997 HFSUTILS
.SH NAME
hcd \- change working HFS directory
.SH SYNOPSIS
hcd
.RI [ hfs-path ]
.SH DESCRIPTION
.B hcd
is used to change the notion of the "current working directory" for the
current HFS volume. All subsequent HFS commands will interpret filenames
relative to this directory, unless absolute pathnames are used.
.PP
If the argument pathname is omitted,
.B hcd
will change to the root of the current volume.
.SH SEE ALSO
hfsutils(1), hpwd(1), hls(1)
.SH FILES
$HOME/.hcwd
.SH BUGS
Although absolute pathnames can be given to
.BR hcd ,
the full pathname must match the current volume; it cannot specify a path for
a different volume. Use
.B hvol
or
.B hmount
to change the current volume. (Each volume has its own independent current
working directory.)
.SH AUTHOR
Robert Leslie <rob@mars.org>

64
doc/man/hcopy.1 Normal file
View File

@ -0,0 +1,64 @@
.TH HCOPY 1 13-Jan-1997 HFSUTILS
.SH NAME
hcopy \- copy files from or to an HFS volume
.SH SYNOPSIS
hcopy [-m|-b|-t|-r|-a]
.I source-path
[...]
.I target-path
.SH DESCRIPTION
.B hcopy
transfers files from an HFS volume to UNIX or vice versa. The named source
files are copied to the named destination target, which must be a directory if
multiple files are to be copied.
.PP
Copies are performed using a translation mode, which must be one of:
.TP
-m
.BR "MacBinary II" :
A popular format for binary file transfer. Both forks of the Macintosh file
are preserved. This is the recommended mode for transferring arbitrary
Macintosh files.
.TP
-b
.BR BinHex :
An alternative format for ASCII file transfer. Both forks of the Macintosh
file are preserved.
.TP
-t
.BR Text :
Performs end-of-line translation. Only the data fork of the Macintosh file is
copied.
.TP
-r
.BR "Raw Data" :
Performs no translation. Only the data fork of the Macintosh file is copied.
.TP
-a
.BR Automatic :
A mode will be chosen automatically for each file based on a set of predefined
heuristics.
.PP
If no mode is specified, -a is assumed.
.PP
If a UNIX source pathname is specified as a single dash (-),
.B hcopy
will copy from standard input to the HFS destination. Likewise, a single dash
used as a UNIX destination pathname will cause
.B hcopy
to copy the HFS source to standard output.
.SH NOTES
Copied files may have their filenames altered during translation. For example,
an appropriate file extension may be added or removed, and certain other
characters may also be transliterated.
.PP
The destination target must not be ambiguous; that is, it must be obvious
whether the target is on the UNIX filesystem or on an HFS volume. As a rule,
HFS targets must contain at least one colon (:), usually as the beginning of a
relative pathname or by itself to represent the current working directory. To
make a UNIX target unambiguous, either use an absolute pathname or precede a
relative pathname with a dot and slash (./).
.SH SEE ALSO
hfsutils(1), hls(1), hattrib(1)
.SH AUTHOR
Robert Leslie <rob@mars.org>

17
doc/man/hdel.1 Normal file
View File

@ -0,0 +1,17 @@
.TH HDEL 1 05-Apr-1996 HFSUTILS
.SH NAME
hdel \- delete both forks of an HFS file
.SH SYNOPSIS
hdel
.I hfs-path
[...]
.SH DESCRIPTION
.B hdel
deletes files from the current HFS volume. Both forks (resource and data) of
each named file are removed, freeing space for other files.
.SH SEE ALSO
hfsutils(1), hrmdir(1)
.SH FILES
$HOME/.hcwd
.SH AUTHOR
Robert Leslie <rob@mars.org>

21
doc/man/hdir.1 Normal file
View File

@ -0,0 +1,21 @@
.TH HDIR 1 14-Jan-1997 HFSUTILS
.SH NAME
hdir \- display an HFS directory in long format
.SH SYNOPSIS
hdir
.RI [ options ]
.RI [ hfs-path
.RI ...]
.SH DESCRIPTION
.B hdir
is an alternative interface to
.BR hls .
It is equivalent to supplying
.B hls
the -l flag.
.SH SEE ALSO
hfsutils(1), hls(1)
.SH FILES
$HOME/.hcwd
.SH AUTHOR
Robert Leslie <rob@mars.org>

94
doc/man/hformat.1 Normal file
View File

@ -0,0 +1,94 @@
.TH HFORMAT 1 08-Nov-1997 HFSUTILS
.SH NAME
hformat \- create a new HFS filesystem and make it current
.SH SYNOPSIS
hformat
[-f] [-l
.IR label ]
.I destination-path
.RI [ partition-no ]
.SH DESCRIPTION
.B hformat
is used to write a new HFS filesystem to a volume. A UNIX pathname to the
volume's destination must be specified. The destination may be either a block
device or a regular file, but it must already exist and be writable.
.PP
An optional label can be specified to name the volume. The name must be
between 1-27 characters and cannot contain a colon (:). By default, the volume
will be named
.BR Untitled .
.PP
If the destination medium is partitioned, one partition must be selected to
receive the filesystem. If there is only one HFS partition on the medium, it
will be selected by default. Otherwise, the desired partition number must be
specified (as the ordinal
.IR n th
HFS partition) on the command-line. The size of the partition determines the
size of the resulting volume.
.PP
Partition number
.B 0
can be specified to format the entire medium as a single filesystem without a
partition map, erasing any existing partition information. Since this will
destroy all the partitions, the
.B -f
option must be specified to force this operation if the medium currently
contains a partition map.
.PP
If the medium is not partitioned (or if partition 0 is specified), the size or
capacity of the medium determines the size of the resulting volume.
.PP
The new volume will be empty and will become "current" so subsequent commands
will refer to it. The current working directory for the volume is set to the
root of the volume.
.SH EXAMPLES
.SP
.TP
% hformat /dev/fd0
If a floppy disk is available as
.BR /dev/fd0 ,
this formats the disk as an HFS volume named
.BR Untitled .
(N.B. The floppy must already have received a low-level format by other
means.)
.TP
% dd if=/dev/zero of=disk.hfs bs=1k count=800
.PD 0
.TP
% hformat -l "Test Disk" disk.hfs
.PD 1
This sequence creates an 800K HFS volume image in the file
.B
disk.hfs
in the current directory, and names it
.BR "Test Disk" .
.TP
% hformat -l "Loma Prieta" /dev/sd2 1
If a SCSI disk is available as
.BR /dev/sd2 ,
this initializes the first HFS partition on the disk (which must already
exist) with a new filesystem, naming the resulting volume
.BR "Loma Prieta" .
.TP
% hformat -f /dev/sd2 0
This causes the medium accessible as
.B /dev/sd2
to be reformatted as a single HFS volume, ignoring and erasing any existing
partition information on the medium. The
.B -f
option must be specified if the medium is currently partitioned; otherwise the
command will fail.
.SH NOTES
This command does not create or alter partition maps, although it can erase
them (as described above). Any partition number specified on the command line
must already exist.
.PP
The smallest volume size which can be formatted with
.B hformat
is 800K.
.SH SEE ALSO
hfsutils(1), hmount(1)
.SH FILES
$HOME/.hcwd
.SH AUTHOR
Robert Leslie <rob@mars.org>

111
doc/man/hfs.1 Normal file
View File

@ -0,0 +1,111 @@
.TH HFS 1 15-Jan-1997 HFSUTILS
.SH NAME
hfs \- shell for manipulating HFS volumes
.SH SYNOPSIS
hfs
.RI [ "hfs-path " [ partition-no ]]
.SH DESCRIPTION
.B hfs
is an interactive command-oriented tool for manipulating HFS volumes.
.B hfs
is based on the Tcl interpreter, so basic Tcl constructs can be used in
addition to the following commands:
.SP
.TP
.BR mount " path [partition-no]"
The specified UNIX path is opened as an HFS volume. If a partition number
.I n
is specified and the volume source is located on a partitioned medium, the
.IR n th
discovered HFS partition will be mounted. The default
.I partition-no
is 1.
.TP
.BR umount " [path]"
The volume previously mounted from the specified path (or the current volume,
if none specified) is unmounted.
.TP
.BR vol " path"
The volume previously mounted from the specified path is made current.
.TP
.B info
General information about the currently mounted volume is displayed. This
information is also displayed automatically when the volume is mounted.
.TP
.B pwd
The full path to the current working HFS directory is displayed.
.TP
.BR cd " [hfs-path]"
The current working directory is changed to the given HFS path. If no path is
given, the working directory is changed to the root of the volume.
.TP
.BR dir " [hfs-path]"
A directory listing of the specified HFS directory is displayed. If no path is
given, the contents of the current working directory are shown.
.TP
.BR mkdir " hfs-path"
A new, empty directory is created with the specified path.
.TP
.BR rmdir " hfs-path"
The specified directory is removed. It must be empty.
.TP
.BR create " hfs-path [type [creator]]"
An empty file is created with the specified path. The Macintosh type and
creator may be specified, or they will default to
.B TEXT
and
.BR UNIX ,
respectively.
.TP
.BR del " hfs-path"
Both forks of the specified file are deleted.
.TP
.BR stat " hfs-path"
Status information about the specified HFS path-identified entity is
displayed.
.TP
.BR cat " hfs-path"
The data fork of the specified HFS file is displayed.
.TP
.BR copyin " unix-path [hfs-path [mode]]"
The specified UNIX file is copied to the named HFS destination path. Unless
specified otherwise, the file will be copied into the current HFS working
directory using a heuristically chosen mode. The
.I mode
may be one of:
.B macb
(MacBinary II),
.B binh
(BinHex),
.BR text ,
or
.BR raw .
.TP
.BR copyout " hfs-path [unix-path [mode]]"
The specified HFS file is copied into the named UNIX destination path. Unless
specified otherwise, the file will be copied into the current UNIX working
directory using a heuristically chosen mode. The modes are the same as for
.BR copyin .
.TP
.BR format " path [partition-no [volume-name]]"
The specified UNIX path is initialized as an empty HFS volume with the given
name, and this volume is subsequently mounted. The default volume name is
.BR Untitled .
.PP
The shell is scriptable, however it should be understood that the above
commands are actually implemented by Tcl procedures prefixed with the
character "h", e.g. hmount, hcd, etc., in order to avoid name collisions with
other Tcl utilities. The "h" may be omitted in interactive use for
convenience.
.SH SEE ALSO
hfsutils(1), xhfs(1)
.SH BUGS
.B cat
can only display the data fork of a file. Text translations are performed
unconditionally on the output. Furthermore, binary data cannot be handled
properly from within Tcl scripts since the character with value 0 cannot be
represented in Tcl strings. Use
.B copyout
to copy files without these limitations.
.SH AUTHOR
Robert Leslie <rob@mars.org>

424
doc/man/hfssh.1 Normal file
View File

@ -0,0 +1,424 @@
.TH HFSSH 1 19-Feb-1998 HFSUTILS
.SH NAME
hfssh \- Tcl interpreter with HFS extensions
.SH SYNOPSIS
hfssh
.RI [ script ]
.SH DESCRIPTION
.B hfssh
is a Tcl interpreter like tclsh(1) but which also implements the following
extensions to support manipulation of Macintosh HFS media:
.SP
.TP
.BI "hfs mount" " path [partno]"
Mounts the indicated HFS partition from the given
.IR path .
An HFS volume handle is returned, which may be used for further volume
commands described below.
.TP
.BI "hfs zero" " path nparts"
The given
.I path
is overwritten with a Macintosh partition structure which can accommodate up to
.I nparts
partitions. All space on the medium is initially allocated to an empty
partition, from which new partitions can be created using
.BR "hfs mkpart" .
The number of blocks in this empty space available for partitioning is
returned.
.TP
.BI "hfs mkpart" " path nblocks"
A new HFS partition is created from the available free space on the specified
Macintosh-partitioned medium. The partition is created with a size of
.IR nblocks .
Any remaining free blocks left in the empty partition space can be further
allocated to other new partitions, as long as there are enough partition slots
remaining.
.IP
N.B. When the last remaining partition slot is used, all remaining free space
must be allocated to it. It is therefore best to consider this when initially
creating the total number of partition slots with
.BR "hfs zero" .
.TP
.BI "hfs nparts" " path"
This command returns the number of HFS partitions which exist on the
Macintosh-formatted medium specified by
.IR path .
If
.I path
does not appear to have a Macintosh partition map, or if an error occurs, this
command will return -1. Otherwise, it will return a number greater than or
equal to 0.
.TP
.BI "hfs format" " path partno vname [bblist]"
This command creates a new HFS volume by formatting the given
.I path
and partition
.I partno
and giving it a volume label
.IR vname .
.IP
If it is desired to "spare" some blocks from being used by the volume, a list
of "bad block" numbers can be given, relative to the beginning of the
partition. The given blocks will be mapped out of use (if possible) and the
size of the resulting volume will be decreased.
.TP
.B "hfs flushall"
All pending changes to all open volumes are flushed immediately.
This is useful to do periodically to avoid accidental loss of data when
volumes are open for long periods of time.
.TP
.BI "hfs chartrans" " fromset toset string"
This command translates the given
.I string
from the
.I fromset
character set to the
.I toset
set. Both
.I fromset
and
.I toset
can be one of
.B latin1
(ISO 8859-1)
or
.B macroman
(MacOS Standard Roman).
A new (translated) string is returned.
.IP
The translation is not necessarily reversible, since the two character sets do
not have a complete one-to-one mapping.
.TP
.B "hfs version"
The current running version of
.B hfsutils
is returned.
.TP
.B "hfs copyright"
A copyright notice is returned.
.TP
.B "hfs author"
The name and email address of the author of
.B hfsutils
is returned.
.TP
.B "hfs license"
A license statement for
.B hfsutils
is returned.
.TP
.IB "vol " vname
The volume name of the given
.I vol
handle is returned. This is also the name of the volume's root directory,
needed to construct absolute pathnames on the volume.
.TP
.IB "vol " size
A list of two numbers is returned; the first is the total size of the given
.I vol
(in bytes), and the second is the number of free bytes that are currently
available.
.TP
.IB "vol " crdate
The creation date of the given
.I vol
is returned, expressed as a number of seconds since 00:00:00 01-Jan-1970 UTC.
.TP
.IB "vol " mddate
The last modification date of the given
.I vol
is returned, expressed as a number of seconds since 00:00:00 01-Jan-1970 UTC.
.TP
.IB "vol " islocked
A boolean value (either 1 or 0) is returned, indicating whether the given
.I vol
handle is locked for read-only access. It may be locked because the medium is
physically locked through hardware, or because the medium was opened read-only
for special reasons (such as another process also has the medium open).
.TP
.IB "vol " umount
The indicated
.I vol
is unmounted, flushing any unsaved data to the volume and closing the access
path to the medium. The
.I vol
handle subsequently becomes invalid for further use.
.TP
.IB "vol " cwd
A numeric value is returned indicating the catalog node ID (CNID) of the
current working directory on the given
.IR vol .
This value can be passed to
.IB "vol " dirinfo
to learn the directory's name and parent CNID.
.TP
.IB "vol " path
A list of directory names is returned, representing the hierarchy between the
root and the current directory. These names can be joined with
.IB "vol " sepchar
characters (:) to construct an absolute pathname to the current directory.
.IP
The same information can be acquired by traversing the CNIDs from the current
directory to the root using
.I vol
.BR dirinfo .
(The root directory always has a CNID of 2.)
.TP
.IB "vol " dir " [path]"
A list is returned describing the contents of the given directory
.I path
(defaulting to the current directory) on the given
.IR vol .
Each element of the list describes one entry, and contains a set of
attribute/value pairs represented as another list, suitable for assignment to
a Tcl array using
.BR "array set" .
.TP
.IB "vol " flush
All pending changes to the given volume are flushed immediately.
.TP
.IB "vol " sepchar
The HFS path separator character ":" is returned.
.TP
.IB "vol " cd " path"
.PD 0
.TP
.IB "vol " chdir " path"
.PD 1
The current working directory on the given volume is changed to
.IR path ,
which may be either an absolute or relative path.
.TP
.IB "vol " dirinfo " cnid"
A two-element list describing the directory having the given
.I cnid
on the given
.I vol
is returned. The first element contains the name of the directory, while the
second element contains the CNID of the directory's parent. Two CNID values
are special: the root directory of the volume has CNID 2, and the "parent" of
the root directory is returned with CNID 1.
.TP
.IB "vol " open " path"
The file on
.I vol
having the given
.I path
is opened. An HFS file handle is returned, which may be used for further file
commands described below.
.TP
.IB "vol " stat " path"
Information about the file or directory having the given
.I path
is returned in much the same way as
.IB "vol " dir
except that only the single argument is described (not its contents).
.TP
.IB "vol " mkdir " path"
A new directory on
.I vol
having the given
.I path
is created. All of the parent directories leading to
.I path
must already exist, but
.I path
itself must not.
.TP
.IB "vol " rmdir " path"
The directory on
.I vol
with the given
.I path
is removed. The directory must be empty.
.TP
.IB "vol " delete " path"
The file on
.I vol
with the given
.I path
is removed. Both resource and data forks of the file are deleted.
.TP
.IB "vol " touch " path"
The modification time for the file or directory specified by
.I path
on the given
.I vol
is updated to the current time.
.TP
.IB "vol " glob " pattern"
The given
.I pattern
is treated as a list of globbing patterns, each of which may be expanded to
the names of files or directories on the given
.I vol
according to the globbing rules described in the hfsutils(1) documentation.
The resulting pathnames are returned in a (possibly longer) list. If a pattern
does not match any file or directory name, it is returned in the resulting
list unchanged.
.TP
.IB "vol " bless " path"
The folder named by the given path is "blessed" as the MacOS System Folder.
For this to be useful, the folder should contain valid Macintosh System and
Finder files.
.TP
.IB "vol " rename " oldpath newpath"
The existing
.I oldpath
on the given
.I vol
is renamed to
.IR newpath ,
possibly changing its location at the same time. If
.I newpath
already exists, it must be a directory, and the item will simply be moved into
it keeping the same name. (In the latter case, there must not be another file
or directory already with the same name; in no case will another file or
directory be overwritten.)
.TP
.IB "vol " create " path type creator"
A new, empty file is created on
.I vol
having the given
.IR path ,
and an HFS file handle is returned in the same manner as
.I vol
.BR open .
The file is given the specified MacOS
.I type
and
.I creator
codes, which must be 4 character strings.
.TP
.IB "vol " copy " srcpath dstvol dstpath"
The given file
.I srcpath
located on
.I vol
is copied to
.I dstpath
located on
.I dstvol
(which may be the same as
.IR vol ).
The file and its attributes are copied verbatim; no translation is performed.
.TP
.IB "vol " copyin " mode srcpath dstpath"
The specified local (UNIX)
.I srcpath
is copied into the given
.I vol
as a file having the specified (HFS)
.IR dstpath .
A translation
.I mode
must be given as one of
.BR macbinary ,
.BR binhex ,
.BR text ,
or
.BR raw .
.TP
.IB "vol " copyout " mode srcpath dstpath"
The specified (HFS)
.I srcpath
on the given
.I vol
is copied out as a local file having the specified (UNIX)
.IR dstpath .
A translation
.I mode
must be given as one of
.BR macbinary ,
.BR binhex ,
.BR text ,
or
.BR raw .
.TP
.IB "file " close
The indicated
.I file
is closed, all pending changes to the file are flushed, and the file handle
becomes invalid for any subsequent operation.
.TP
.IB "file " tell
A numeric index is returned indicating the character position within
.I file
at which the next read or write operation will occur.
.TP
.IB "file " stat
Information about the given
.I file
is returned in much the same way as
.I vol
.BR stat .
.TP
.IB "file " getfork
If the given
.I file
is currently performing I/O on its data fork, the string "data" is returned.
Otherwise, the string "rsrc" is returned. When files are opened, they will
default to read/write on their data fork. The current fork may be changed with
.I file
.BR setfork .
.TP
.IB "file " setfork " fork"
The current fork of the given
.I file
is set to
.I fork
(which must be one of
.B data
or
.BR rsrc ),
and the current read/write position is reset to the beginning of the file.
.TP
.IB "file " seek " pos [from]"
The character position for the next read or write on
.I file
is changed to
.IR pos ,
relative to the indicated
.I from
position, which must be one of
.BR start ,
.BR current ,
or
.BR end .
The default is to position relative to the
.B start
of the file.
.TP
.IB "file " read " length"
.I length
bytes are read from the current read/write position in
.IR file ,
and these bytes are returned as a string. This string may be shorter than
.I length
in some circumstances, or may even be empty, indicating the end of the file
has been reached.
.TP
.IB "file " write " string"
The given
.I string
is written to
.I file
at the current read/write position. The number of bytes actually written to
the file is returned, and may be less than the length of the string in unusual
circumstances (such as when the volume is full).
.SH SEE ALSO
hfsutils(1), hfs(1), tclsh(1)
.SH NOTES
Precautions are taken to ensure all open files and mounted volumes are cleanly
closed and unmounted before exiting the shell, however abnormal termination
(e.g. CTRL-C) can circumvent this, potentially leaving volumes in an
inconsistent state. Judicious use of
.B "hfs flushall"
may help reduce this risk.
.SH BUGS
Tcl does not provide a mechanism for manipulating arbitrary binary data.
Therefore caution should be used when reading or writing files containing
anything other than plain text.
.SH AUTHOR
Robert Leslie <rob@mars.org>

109
doc/man/hfsutils.1 Normal file
View File

@ -0,0 +1,109 @@
.TH HFSUTILS 1 08-Nov-1997 HFSUTILS
.SH NAME
hfsutils \- tools for reading and writing Macintosh HFS volumes
.SH SYNOPSIS
.nf
\fBhattrib\fR \- change HFS file or directory attributes
\fBhcd\fR \- change working HFS directory
\fBhcopy\fR \- copy files from or to an HFS volume
\fBhdel\fR \- delete both forks of an HFS file
\fBhdir\fR \- display an HFS directory in long format
\fBhformat\fR \- create a new HFS filesystem and make it current
\fBhls\fR \- list files in an HFS directory
\fBhmkdir\fR \- create a new HFS directory
\fBhmount\fR \- introduce a new HFS volume and make it current
\fBhpwd\fR \- print the full path to the current HFS working directory
\fBhrename\fR \- rename or move an HFS file or directory
\fBhrmdir\fR \- remove an empty HFS directory
\fBhumount\fR \- remove an HFS volume from the list of known volumes
\fBhvol\fR \- display or change the current HFS volume
.fi
.PP
.nf
\fBhfssh\fR \- Tcl interpreter with HFS extensions
.fi
.PP
.nf
\fBhfs\fR \- shell for manipulating HFS volumes
\fBxhfs\fR \- graphical interface for manipulating HFS volumes
.fi
.SH DESCRIPTION
.B hfsutils
is a collection of tools and programs for accessing Macintosh HFS-formatted
volumes. See the accompanying man page for each program above for more
information.
.SH NOTES
These utilities can manipulate HFS volumes on nearly any medium. A UNIX path
is initially specified to
.B hmount
or
.B hformat
which gives the location of the volume. This path can be a block device --
corresponding to, for example, a floppy disk, CD-ROM, SCSI disk, or other
device -- or it can be a regular file containing an image of any of the
above.
.PP
The medium specified by the UNIX path may or may not contain an Apple
partition map. If partitioned, it is possible for more than one HFS volume to
be present on the medium. In this case, a partition number must also be given
which selects the desired partition. This number refers to the
.IR n th
ordinal HFS partition on the volume. (Other, non-HFS partitions are ignored.)
Partition number
.B 0
refers to the entire medium, disregarding the partition map, if any.
.PP
HFS pathnames consist of colon-separated components. Unlike UNIX pathnames, an
HFS path which begins with a colon (e.g. :Foo:Bar) is a
.I relative
path, and one which does not (e.g. Foo:Bar) is an
.I absolute
path. As sole exception to this rule, a path not containing any colons is
assumed to be relative.
.PP
Absolute pathnames always begin with the name of the volume itself. Any
occurrence of two or more consecutive colons in a path causes resolution of
the path to ascend into parent directories.
.PP
Most of the command-line programs support HFS filename globbing. The following
forms of globbing are supported:
.SP
.TP
.B *
matches zero or more characters.
.TP
.B ?
matches exactly one character.
.TP
.BR [ ... ]
matches any single character enclosed within the brackets. A character range
may be specified by using a hypen (-). Note that matches are not case
sensitive.
.TP
.BR { ... , ... }
expands into the Cartesian product of each specified substring.
.TP
.B \\\\
causes the following character to be matched literally.
.PP
Note that since globbing is performed by each HFS command rather than by the
UNIX shell (which knows nothing about HFS volumes), care should always be
taken to protect pathnames from the shell by using an appropriate quoting
technique. Typically it is best to surround HFS pathnames containing glob
characters with single quotes (').
.PP
Time stamps on HFS volumes are interpreted as being relative to the current
time zone. This means that modification dates on HFS volumes written in
another time zone may appear to be off by some number of hours.
.PP
Hardware limitations prevent some systems from reading or writing native
Macintosh 800K floppy disks; only high-density 1440K disks can be used on
these systems.
.PP
The obsolete MFS volume format is not supported by this software.
.SH SEE ALSO
hattrib(1), hcd(1), hcopy(1), hdel(1), hdir(1), hformat(1), hls(1), hmkdir(1),
hmount(1), hpwd(1), hrename(1), hrmdir(1), hvol(1),
hfs(1), xhfs(1)
.SH AUTHOR
Robert Leslie <rob@mars.org>

119
doc/man/hls.1 Normal file
View File

@ -0,0 +1,119 @@
.TH HLS 1 14-Jan-1997 HFSUTILS
.SH NAME
hls \- list files in an HFS directory
.SH SYNOPSIS
hls
.RI [ options ]
.RI [ hfs-path
.RI ...]
.SH DESCRIPTION
.B hls
lists files and directories contained in an HFS volume. If one or more
arguments are given, each specified file or directory is shown; otherwise, the
contents of the current working directory are shown.
.SH OPTIONS
.TP
-1
Output is formatted such that each entry appears on a single line. This is the
default when stdout is not a terminal.
.TP
-a
All files and directories are shown, including "invisible" files, as would be
perceived by the Macintosh Finder. Normally invisible files are omitted from
directory listings.
.TP
-b
Special characters are displayed in an escaped backslash notation. Normally
special or non-printable characters in filenames are replaced by a question
mark (?).
.TP
-c
Sort and display entries by their creation date, rather than their
modification date.
.TP
-d
List directory entries themselves rather than their contents. Normally the
contents are shown for named directories on the command-line.
.TP
-f
Do not sort directory contents; list them in the order they appear in the
directory. This option effectively enables -a and -U and disables -l, -s, and
-t.
.TP
-i
Show the catalog IDs for each entry. Every file and directory on an HFS volume
has a unique catalog ID.
.TP
-l
Display entries in long format. This format shows the entry type ("d" for
directory or "f" for file), flags ("i" for invisible), file type and creator
(four-character strings for files only), size (number of directory
sub-contents or file resource and data bytes, respectively), date of last
modification (or creation, with -c flag), and pathname. Macintosh "locked"
files are indicated by "F" in place of "f".
.TP
-m
Display entries in a continuous format separated by commas.
.TP
-q
Replace special and non-printable characters in displayed filenames with
question marks (?). This is the default when stdout is connected to a
terminal.
.TP
-r
Sort entries in reverse order before displaying.
.TP
-s
Show the file size for each entry in 1K block units. The size includes blocks
used for both data and resource forks.
.TP
-t
Sort and display entries by time. Normally files will be sorted by name. This
option uses the last modification date to sort unless -c is also specified.
.TP
-x
Display entries in column format like -C, but sorted horizontally into rows
rather than columns.
.TP
.RI "-w " width
Format output lines suitable for display in the given
.IR width .
Normally the width will be determined from your terminal, from the environment
variable COLUMNS, or from a default value of 80.
.TP
-C
Display entries in column format with entries sorted vertically. This is the
default output format when stdout is connected to a terminal.
.TP
-F
Cause certain output filenames to be followed by a single-character flag
indicating the nature of the entry; directories are followed by a colon (:)
and executable Macintosh applications are followed by an asterisk (*).
.TP
-N
Cause all filenames to be output verbatim without any escaping or
question-mark substitution.
.TP
-Q
Cause all filenames to be enclosed within double-quotes (") and
special/non-printable characters to be properly escaped.
.TP
-R
For each directory that is encountered in a listing, recursively descend into
and display its contents.
.TP
-S
Sort and display entries by size. For files, the combined resource and data
lengths are used to compute a file's size.
.TP
-U
Do not sort directory contents; list them in the order they appear in the
directory. On HFS volumes, this is usually an alphabetical case-insensitive
ordering, although there are some idiosyncrasies to the Macintosh
implementation of ordering. This option does not affect -a, -l, or -s.
.SH SEE ALSO
hfsutils(1), hcd(1), hpwd(1), hdir(1), hcopy(1)
.SH FILES
$HOME/.hcwd
.SH AUTHOR
Robert Leslie <rob@mars.org>

17
doc/man/hmkdir.1 Normal file
View File

@ -0,0 +1,17 @@
.TH HMKDIR 1 13-Jan-1997 HFSUTILS
.SH NAME
hmkdir \- create a new HFS directory
.SH SYNOPSIS
hmkdir
.I hfs-path
[...]
.SH DESCRIPTION
.B hmkdir
creates new, empty directories (folders) on the current HFS volume. There must
not already be a file or directory with each named path.
.SH SEE ALSO
hfsutils(1), hrmdir(1), hcd(1), hpwd(1), hls(1)
.SH FILES
$HOME/.hcwd
.SH AUTHOR
Robert Leslie <rob@mars.org>

64
doc/man/hmount.1 Normal file
View File

@ -0,0 +1,64 @@
.TH HMOUNT 1 08-Nov-1997 HFSUTILS
.SH NAME
hmount \- introduce a new HFS volume and make it current
.SH SYNOPSIS
hmount
.I source-path
.RI [ partition-no ]
.SH DESCRIPTION
.B hmount
is used to introduce a new HFS volume. A UNIX pathname to the volume's source
must be specified. The source may be a block device or a regular file
containing an HFS volume image.
.PP
If the source medium is partitioned, one partition must be selected to be
mounted. If there is only one HFS partition on the medium, it will be selected
by default. Otherwise, the desired partition number must be specified (as the
ordinal
.IR n th
HFS partition) on the command-line. Partition number
.B 0
can be specified to refer to the entire medium, ignoring what might otherwise
be perceived as a partition map, although in practice this is probably only
useful if you want this command to fail when the medium is partitioned.
.PP
The mounted volume becomes "current" so subsequent commands will refer to it.
The current working directory for the volume is set to the root of the volume.
This information is kept in a file named
.I .hcwd
in the user's home directory.
.PP
If the source medium is changed (e.g. floppy or CD-ROM disc exchanged) after
.B hmount
has been called, subsequent HFS commands will fail until the original medium
is replaced or a different volume is made current. To use the same source
path with the different medium, reissue the
.B hmount
command.
.SH EXAMPLES
.SP
.TP
% hmount /dev/fd0
If a Macintosh floppy disk is available as
.BR /dev/fd0 ,
this command makes the floppy current for other HFS commands such as hls(1),
hcd(1), hcopy(1), etc.
.TP
% hmount /dev/sd2 1
If a SCSI disk is available as
.BR /dev/sd2 ,
this command finds the first HFS partition on the medium and makes it
available for other HFS operations.
.SH NOTES
.B hmount
does not actually mount an HFS partition over a UNIX directory in the
traditional mount(8) sense. It is merely a "virtual" mount, as a point of
convenience for future HFS operations. Each HFS command independently opens,
operates on, and closes the named source path given to
.BR hmount .
.SH SEE ALSO
hfsutils(1), hformat(1), humount(1), hvol(1)
.SH FILES
$HOME/.hcwd
.SH AUTHOR
Robert Leslie <rob@mars.org>

15
doc/man/hpwd.1 Normal file
View File

@ -0,0 +1,15 @@
.TH HPWD 1 05-Apr-1996 HFSUTILS
.SH NAME
hpwd \- print the full path to the current HFS working directory
.SH SYNOPSIS
hpwd
.SH DESCRIPTION
.B hpwd
displays the complete (absolute) HFS pathname to the current working directory
on the current volume. The current working directory can be changed with the
.B hcd
command.
.SH SEE ALSO
hfsutils(1), hcd(1)
.SH AUTHOR
Robert Leslie <rob@mars.org>

27
doc/man/hrename.1 Normal file
View File

@ -0,0 +1,27 @@
.TH HRENAME 1 04-Jun-1996 HFSUTILS
.SH NAME
hrename \- rename or move an HFS file or directory
.SH SYNOPSIS
hrename
.I hfs-src-path
[...]
.I hfs-target-path
.SH DESCRIPTION
.B hrename
changes the name and/or location of one or more files or directories. If only
one source path is specified and the target path is in the same directory as
the source, only the name is changed. Otherwise the source object is moved as
well as possibly being renamed.
.PP
If multiple source paths are specified, the target must be a directory, and
all of the source objects will be moved into it (keeping the same names.)
.PP
If the source path refers to the root directory of a volume, the volume name
will be changed. The root directory cannot be moved. Note that volume names
can only have 1-27 characters, while all other names may have 1-31 characters.
.SH SEE ALSO
hfsutils(1)
.SH FILES
$HOME/.hcwd
.SH AUTHOR
Robert Leslie <rob@mars.org>

17
doc/man/hrmdir.1 Normal file
View File

@ -0,0 +1,17 @@
.TH HRMDIR 1 05-Apr-1996 HFSUTILS
.SH NAME
hrmdir \- remove an empty HFS directory
.SH SYNOPSIS
hrmdir
.I hfs-path
[...]
.SH DESCRIPTION
.B hrmdir
deletes directories (folders) from the current HFS volume. Each named
directory must already be empty.
.SH SEE ALSO
hfsutils(1), hmkdir(1), hdel(1)
.SH FILES
$HOME/.hcwd
.SH AUTHOR
Robert Leslie <rob@mars.org>

24
doc/man/humount.1 Normal file
View File

@ -0,0 +1,24 @@
.TH HUMOUNT 1 05-Apr-1996 HFSUTILS
.SH NAME
humount \- remove an HFS volume from the list of known volumes
.SH SYNOPSIS
humount
.RI [ volume-name-or-path ]
.SH DESCRIPTION
.B humount
is used to forget about an HFS volume previously mounted with
.BR hmount .
Either the volume's name or the UNIX path to the volume may be used to specify
the volume. If no name or path is given, the current volume is assumed.
.SH NOTES
It is not strictly necessary to use this command. It does not affect any
physical volumes; it only updates the file named
.I .hcwd
in the user's home directory used to keep track of the currently known HFS
volumes.
.SH SEE ALSO
hfsutils(1), hmount(1)
.SH FILES
$HOME/.hcwd
.SH AUTHOR
Robert Leslie <rob@mars.org>

30
doc/man/hvol.1 Normal file
View File

@ -0,0 +1,30 @@
.TH HVOL 1 21-Apr-1996 HFSUTILS
.SH NAME
hvol \- display or change the current HFS volume
.SH SYNOPSIS
hvol
.RI [ volume-or-path ]
.SH DESCRIPTION
With no arguments,
.B hvol
displays the name and path to the "current" HFS volume as well as the names
and paths of all previously mounted ("known") volumes.
.PP
With an argument,
.B hvol
changes the current volume to be the one specified. Either the name of the
volume or the path to its UNIX source can be specified. The volume must have
been previously mounted using
.BR hmount .
.PP
A separate "current working directory" is maintained for each mounted volume.
This information is kept in a file named
.I .hcwd
in the user's home directory.
.SH SEE ALSO
hfsutils(1), hmount(1), humount(1)
.SH FILES
$HOME/.hcwd
.SH AUTHOR
Robert Leslie <rob@mars.org>

47
doc/man/xhfs.1 Normal file
View File

@ -0,0 +1,47 @@
.TH XHFS 1 02-Apr-1996 HFSUTILS
.SH NAME
xhfs \- graphical interface for manipulating HFS volumes
.SH SYNOPSIS
xhfs
.RI [ "left-path " [ right-path ]]
.SH DESCRIPTION
.B xhfs
presents a graphical front-end for browsing and copying files on HFS-formatted
volumes.
.PP
The display is divided into two parts, left and right, which can each
independently view a directory on either an HFS volume or the host (UNIX)
filesystem. Double-clicking the name of a directory in either view will open
that directory. A pop-up menu at the top of each directory view can be used to
navigate to any directory between the current and the beginning of the
hierarchy.
.PP
Text files can be viewed by double-clicking them. Any file or set of files can
be copied to the directory shown in the other view by selecting them and
clicking the "Copy" button. Copying is performed according to the selected
copy mode:
.SP
.TP
.B "MacBinary II"
The file(s) will be copied using the MacBinary II format. This is the
recommended mode for transferring arbitrary Macintosh files.
.TP
.B BinHex
The file(s) will be copied using the BinHex format. This mode should be used
to encode Macintosh files into strict ASCII format.
.TP
.B Text
In this mode, only the data fork(s) of the selected file(s) are copied.
Furthermore, translation is performed on the data's end-of-line characters to
conform to the standard for text files on the destination.
.TP
.B "Raw Data"
In this mode, only the data fork(s) of the selected file(s) are copied.
However, no translation is performed whatsoever on the data.
.TP
.B Automatic
A copy mode will be selected automatically according to a set of heuristics.
.SH SEE ALSO
hfsutils(1), hfs(1)
.SH AUTHOR
Robert Leslie <rob@mars.org>

124
dstring.c Normal file
View File

@ -0,0 +1,124 @@
/*
* hfsutils - tools 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: dstring.c,v 1.7 1998/11/02 22:08:28 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdlib.h>
# include <string.h>
# include "dstring.h"
/*
* NAME: dstring->init()
* DESCRIPTION: initialize a new dynamic string
*/
void dstr_init(dstring *string)
{
string->str = string->sbuf;
string->len = 0;
string->space = sizeof(string->sbuf);
string->sbuf[0] = 0;
}
/*
* NAME: dstring->append()
* DESCRIPTION: append to a dynamic string
*/
int dstr_append(dstring *string, const char *str, size_t len)
{
size_t newlen;
if (len == (size_t) -1)
len = strlen(str);
newlen = string->len + len;
/* make sure there is room */
if (newlen >= string->space)
{
char *new;
newlen *= 2;
new = malloc(newlen);
if (new == 0)
return -1;
string->space = newlen;
memcpy(new, string->str, string->len);
if (string->str != string->sbuf)
free(string->str);
string->str = new;
}
/* append the string */
memcpy(string->str + string->len, str, len);
string->len += len;
string->str[string->len] = 0;
return 0;
}
/*
* NAME: dstring->string()
* DESCRIPTION: return a pointer to a dynamic string's content
*/
char *dstr_string(dstring *string)
{
return string->str;
}
/*
* NAME: dstring->length()
* DESCRIPTION: return the length of a dynamic string
*/
int dstr_length(dstring *string)
{
return string->len;
}
/*
* NAME: dstring->shrink()
* DESCRIPTION: truncate a dynamic string to a shorter length
*/
void dstr_shrink(dstring *string, size_t len)
{
if (len < string->len)
string->len = len;
}
/*
* NAME: dstring->free()
* DESCRIPTION: free a dynamic string
*/
void dstr_free(dstring *string)
{
if (string->str != string->sbuf)
free(string->str);
}

34
dstring.h Normal file
View File

@ -0,0 +1,34 @@
/*
* hfsutils - tools 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: dstring.h,v 1.7 1998/11/02 22:08:29 rob Exp $
*/
typedef struct {
char *str;
size_t len;
size_t space;
char sbuf[50];
} dstring;
void dstr_init(dstring *);
int dstr_append(dstring *, const char *, size_t);
char *dstr_string(dstring *);
int dstr_length(dstring *);
void dstr_shrink(dstring *, size_t);
void dstr_free(dstring *);

359
glob.c Normal file
View File

@ -0,0 +1,359 @@
/*
* hfsutils - tools 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: glob.c,v 1.6 1998/04/11 08:26:55 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdlib.h>
# include <string.h>
# include "dlist.h"
# include "dstring.h"
# include "hfs.h"
# include "glob.h"
/*
* NAME: strmatch()
* DESCRIPTION: return 1 iff a string matches a given (glob) pattern
*/
static
int strmatch(const char *str, const char *pat)
{
while (1)
{
if (*str == 0 && *pat != 0 && *pat != '*')
return 0;
switch (*pat)
{
case 0:
return (*str == 0);
case '*':
if (*++pat == 0)
return 1;
while (1)
{
if (strmatch(str, pat))
return 1;
if (*str++ == 0)
return 0;
}
case '?':
break;
case '[':
{
++pat;
while (1)
{
unsigned char p0, p1, s;
p0 = *pat;
if (p0 == ']' || p0 == 0)
return 0;
s = *str;
if (hfs_charorder[p0] == hfs_charorder[s])
break;
if (pat[1] == '-')
{
p1 = pat[2];
if (p1 == 0)
return 0;
if ((hfs_charorder[p0] <= hfs_charorder[s] &&
hfs_charorder[p1] >= hfs_charorder[s]) ||
(hfs_charorder[p0] >= hfs_charorder[s] &&
hfs_charorder[p1] <= hfs_charorder[s]))
break;
pat += 2;
}
++pat;
}
while (*pat != ']')
{
if (*pat == 0)
{
--pat;
break;
}
++pat;
}
}
break;
case '\\':
if (*++pat == 0)
return 0;
/* fall through */
default:
if (hfs_charorder[(unsigned char) *pat] !=
hfs_charorder[(unsigned char) *str])
return 0;
}
++pat, ++str;
}
}
/*
* NAME: doglob()
* DESCRIPTION: perform recursive depth-first traversal of path to be globbed
*/
static
int doglob(hfsvol *vol, dlist *list, const char *dir, const char *rem)
{
dstring new;
int special, len, result = 0;
const char *obrace, *cbrace, *ptr;
dstr_init(&new);
special = 0;
obrace = cbrace = 0;
for (ptr = rem; *ptr && (obrace || *ptr != ':'); ++ptr)
{
switch (*ptr)
{
case '{':
if (obrace == 0)
obrace = ptr;
break;
case '}':
if (obrace && cbrace == 0)
cbrace = ptr;
break;
case '\\':
if (*++ptr == 0)
--ptr;
case '*':
case '[':
case '?':
special = 1;
break;
}
}
if (obrace)
{
const char *elt;
if (cbrace == 0 ||
dstr_append(&new, rem, obrace - rem) == -1)
{
dstr_free(&new);
return -1;
}
len = dstr_length(&new);
for (ptr = obrace; *ptr != '}'; )
{
elt = ptr + 1;
ptr = elt;
while (*ptr != '}' && *ptr != ',')
++ptr;
if (dstr_append(&new, elt, ptr - elt) == -1 ||
dstr_append(&new, cbrace + 1, -1) == -1 ||
doglob(vol, list, dir, dstr_string(&new)) == -1)
{
dstr_free(&new);
return -1;
}
dstr_shrink(&new, len);
}
dstr_free(&new);
return 0;
}
if (dstr_append(&new, dir, -1) == -1)
{
dstr_free(&new);
return -1;
}
len = dstr_length(&new);
if (special)
{
hfsdirent ent;
hfsdir *d;
dstring pat;
int found = 0;
dstr_init(&pat);
if (dstr_append(&pat, rem, ptr - rem) == -1)
{
dstr_free(&pat);
dstr_free(&new);
return -1;
}
if (*dir == 0 && strchr(rem, ':') == 0)
d = hfs_opendir(vol, ":");
else
d = hfs_opendir(vol, dir);
if (d == 0)
{
dstr_free(&pat);
dstr_free(&new);
return -1;
}
while (hfs_readdir(d, &ent) != -1)
{
if (ent.fdflags & HFS_FNDR_ISINVISIBLE)
continue;
if (strmatch(ent.name, dstr_string(&pat)))
{
dstr_shrink(&new, len);
if (dstr_append(&new, ent.name, -1) == -1)
{
result = -1;
break;
}
if (*ptr == 0)
{
found = 1;
result = dl_append(list, dstr_string(&new));
if (result == -1)
break;
}
else if (ent.flags & HFS_ISDIR)
{
if (dstr_append(&new, ":", 1) == -1)
result = -1;
else
{
found = 1;
result = doglob(vol, list, dstr_string(&new), ptr + 1);
}
if (result == -1)
break;
}
}
}
hfs_closedir(d);
if (result == 0 && ! found)
{
dstr_shrink(&new, len);
if (dstr_append(&new, rem, -1) == -1)
result = -1;
else
{
char *ptr, *rem;
for (rem = dstr_string(&new) + len, ptr = rem; *rem;
++rem, ++ptr)
{
if (*rem == '\\')
++rem;
*ptr = *rem;
}
*ptr = 0;
result = dl_append(list, dstr_string(&new));
}
}
dstr_free(&pat);
dstr_free(&new);
return result;
}
if (dstr_append(&new, rem, ptr - rem) == -1)
result = -1;
else
{
if (*ptr)
{
if (dstr_append(&new, ":", 1) == -1)
result = -1;
else
result = doglob(vol, list, dstr_string(&new), ptr + 1);
dstr_free(&new);
return result;
}
result = dl_append(list, dstr_string(&new));
}
dstr_free(&new);
return result;
}
/*
* NAME: hfs->glob()
* DESCRIPTION: perform glob pattern matching
*/
char **hfs_glob(hfsvol *vol, int argc, char *argv[], int *nelts)
{
dlist list;
int i;
if (dl_init(&list) == -1)
return 0;
for (i = 0; i < argc; ++i)
{
if (doglob(vol, &list, "", argv[i]) == -1)
{
dl_free(&list);
return 0;
}
}
*nelts = dl_size(&list);
return dl_array(&list);
}

22
glob.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: glob.h,v 1.6 1998/04/11 08:26:55 rob Exp $
*/
char **hfs_glob(hfsvol *, int, char *[], int *);

231
hattrib.c Normal file
View File

@ -0,0 +1,231 @@
/*
* hfsutils - tools 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: hattrib.c,v 1.8 1998/08/31 04:27:17 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "hattrib.h"
/*
* NAME: usage()
* DESCRIPTION: display usage message
*/
static
int usage(void)
{
fprintf(stderr,
"Usage: %s [-t TYPE] [-c CREA] [-|+i] [-|+l] hfs-path [...]\n"
" %s -b hfs-path\n",
argv0, argv0);
return 1;
}
/*
* NAME: hattrib->main()
* DESCRIPTION: implement hattrib command
*/
int hattrib_main(int argc, char *argv[])
{
const char *type = 0, *crea = 0;
int invis = 0, lock = 0, bless = 0;
hfsvol *vol;
int fargc;
char **fargv;
int i, result = 0;
for (i = 1; i < argc; ++i)
{
switch (argv[i][0])
{
case '-':
switch (argv[i][1])
{
case 't':
type = argv[++i];
if (type == 0)
return usage();
if (strlen(type) != 4)
{
fprintf(stderr, "%s: file type must be 4 characters\n",
argv0);
return 1;
}
continue;
case 'c':
crea = argv[++i];
if (crea == 0)
return usage();
if (strlen(crea) != 4)
{
fprintf(stderr, "%s: file creator must be 4 characters\n",
argv0);
return 1;
}
continue;
case 'i':
invis = -1;
continue;
case 'l':
lock = -1;
continue;
case 'b':
bless = 1;
continue;
default:
return usage();
}
break;
case '+':
switch (argv[i][1])
{
case 'i':
invis = 1;
continue;
case 'l':
lock = 1;
continue;
default:
return usage();
}
break;
}
break;
}
if (argc - i == 0)
return usage();
if (i == 1)
{
fprintf(stderr, "%s: no attributes specified\n", argv0);
return 1;
}
if (bless && (lock || invis || type || crea || argc - i > 1))
return usage();
vol = hfsutil_remount(hcwd_getvol(-1), HFS_MODE_ANY);
if (vol == 0)
return 1;
fargv = hfsutil_glob(vol, argc - i, &argv[i], &fargc, &result);
if (result == 0)
{
hfsdirent ent;
if (bless)
{
if (fargc != 1)
{
fprintf(stderr, "%s: %s: ambiguous path\n", argv0, argv[i]);
result = 1;
}
else
{
hfsvolent volent;
if (hfs_stat(vol, fargv[0], &ent) == -1 ||
hfs_vstat(vol, &volent) == -1)
{
hfsutil_perrorp(fargv[0]);
result = 1;
}
else
{
volent.blessed = ent.cnid;
if (hfs_vsetattr(vol, &volent) == -1)
{
hfsutil_perrorp(fargv[0]);
result = 1;
}
}
}
}
else
{
for (i = 0; i < fargc; ++i)
{
if (hfs_stat(vol, fargv[i], &ent) == -1)
{
hfsutil_perrorp(fargv[i]);
result = 1;
}
else
{
if (! (ent.flags & HFS_ISDIR))
{
if (type)
memcpy(ent.u.file.type, type, 4);
if (crea)
memcpy(ent.u.file.creator, crea, 4);
}
if (invis < 0)
ent.fdflags &= ~HFS_FNDR_ISINVISIBLE;
else if (invis > 0)
ent.fdflags |= HFS_FNDR_ISINVISIBLE;
if (lock < 0)
ent.flags &= ~HFS_ISLOCKED;
else if (lock > 0)
ent.flags |= HFS_ISLOCKED;
if (hfs_setattr(vol, fargv[i], &ent) == -1)
{
hfsutil_perrorp(fargv[i]);
result = 1;
}
}
}
}
}
hfsutil_unmount(vol, &result);
if (fargv)
free(fargv);
return result;
}

22
hattrib.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: hattrib.h,v 1.6 1998/04/11 08:26:56 rob Exp $
*/
int hattrib_main(int, char *[]);

115
hcd.c Normal file
View File

@ -0,0 +1,115 @@
/*
* hfsutils - tools 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: hcd.c,v 1.8 1998/11/02 22:08:30 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "hcd.h"
/*
* NAME: hcd->main()
* DESCRIPTION: implement hcd command
*/
int hcd_main(int argc, char *argv[])
{
mountent *ment;
hfsvol *vol;
hfsvolent vent;
char *path, root[HFS_MAX_VLEN + 1 + 1];
int fargc;
char **fargv = 0;
int result = 0;
if (argc > 2)
{
fprintf(stderr, "Usage: %s [hfs-path]\n", argv0);
return 1;
}
vol = hfsutil_remount(ment = hcwd_getvol(-1), HFS_MODE_RDONLY);
if (vol == 0)
return 1;
if (argc == 2)
{
fargv = hfsutil_glob(vol, 1, &argv[1], &fargc, &result);
if (result == 0)
{
if (fargc != 1)
{
fprintf(stderr, "%s: %s: ambiguous path\n", argv0, argv[1]);
result = 1;
}
else
path = fargv[0];
}
}
else
{
hfs_vstat(vol, &vent);
strcpy(root, vent.name);
strcat(root, ":");
path = root;
}
if (result == 0)
{
if (hfs_chdir(vol, path) == -1)
{
hfsutil_perrorp(path);
result = 1;
}
else
{
path = hfsutil_getcwd(vol);
if (path == 0)
{
hfsutil_perror("Can't get new HFS directory path");
result = 1;
}
if (result == 0 && hcwd_setcwd(ment, path) == -1)
{
perror("Can't set new HFS directory");
result = 1;
}
if (path)
free(path);
}
}
hfsutil_unmount(vol, &result);
if (fargv)
free(fargv);
return result;
}

22
hcd.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: hcd.h,v 1.7 1998/04/11 08:26:56 rob Exp $
*/
int hcd_main(int, char *[]);

318
hcopy.c Normal file
View File

@ -0,0 +1,318 @@
/*
* hfsutils - tools 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: hcopy.c,v 1.8 1998/04/11 08:26:56 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <errno.h>
# include <sys/stat.h>
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "hcopy.h"
# include "copyin.h"
# include "copyout.h"
extern int optind;
/*
* NAME: automode_unix()
* DESCRIPTION: automatically choose copyin transfer mode for UNIX path
*/
static
cpifunc automode_unix(const char *path)
{
int i;
struct {
const char *ext;
cpifunc func;
} exts[] = {
{ ".bin", cpi_macb },
{ ".hqx", cpi_binh },
{ ".txt", cpi_text },
{ ".c", cpi_text },
{ ".h", cpi_text },
{ ".html", cpi_text },
{ ".htm", cpi_text },
{ ".rtf", cpi_text },
{ 0, 0 }
};
path += strlen(path);
for (i = 0; exts[i].ext; ++i)
{
if (strcasecmp(path - strlen(exts[i].ext), exts[i].ext) == 0)
return exts[i].func;
}
return cpi_raw;
}
/*
* NAME: do_copyin()
* DESCRIPTION: copy files from UNIX to HFS
*/
static
int do_copyin(hfsvol *vol, int argc, char *argv[], const char *dest, int mode)
{
hfsdirent ent;
struct stat sbuf;
cpifunc copyfile;
int i, result = 0;
if (argc > 1 && (hfs_stat(vol, dest, &ent) == -1 ||
! (ent.flags & HFS_ISDIR)))
{
ERROR(ENOTDIR, 0);
hfsutil_perrorp(dest);
return 1;
}
switch (mode)
{
case 'm':
copyfile = cpi_macb;
break;
case 'b':
copyfile = cpi_binh;
break;
case 't':
copyfile = cpi_text;
break;
case 'r':
copyfile = cpi_raw;
break;
}
for (i = 0; i < argc; ++i)
{
if (stat(argv[i], &sbuf) != -1 &&
S_ISDIR(sbuf.st_mode))
{
ERROR(EISDIR, 0);
hfsutil_perrorp(argv[i]);
result = 1;
}
else
{
if (mode == 'a')
copyfile = automode_unix(argv[i]);
if (copyfile(argv[i], vol, dest) == -1)
{
ERROR(errno, cpi_error);
hfsutil_perrorp(argv[i]);
result = 1;
}
}
}
return result;
}
/*
* NAME: automode_hfs()
* DESCRIPTION: automatically choose copyout transfer mode for HFS path
*/
static
cpofunc automode_hfs(hfsvol *vol, const char *path)
{
hfsdirent ent;
if (hfs_stat(vol, path, &ent) != -1)
{
if (strcmp(ent.u.file.type, "TEXT") == 0 ||
strcmp(ent.u.file.type, "ttro") == 0)
return cpo_text;
else if (ent.u.file.rsize == 0)
return cpo_raw;
}
return cpo_macb;
}
/*
* NAME: do_copyout()
* DESCRIPTION: copy files from HFS to UNIX
*/
static
int do_copyout(hfsvol *vol, int argc, char *argv[], const char *dest, int mode)
{
struct stat sbuf;
hfsdirent ent;
cpofunc copyfile;
int i, result = 0;
if (argc > 1 && (stat(dest, &sbuf) == -1 ||
! S_ISDIR(sbuf.st_mode)))
{
ERROR(ENOTDIR, 0);
hfsutil_perrorp(dest);
return 1;
}
switch (mode)
{
case 'm':
copyfile = cpo_macb;
break;
case 'b':
copyfile = cpo_binh;
break;
case 't':
copyfile = cpo_text;
break;
case 'r':
copyfile = cpo_raw;
break;
}
for (i = 0; i < argc; ++i)
{
if (hfs_stat(vol, argv[i], &ent) != -1 &&
(ent.flags & HFS_ISDIR))
{
ERROR(EISDIR, 0);
hfsutil_perrorp(argv[i]);
result = 1;
}
else
{
if (mode == 'a')
copyfile = automode_hfs(vol, argv[i]);
if (copyfile(vol, argv[i], dest) == -1)
{
ERROR(errno, cpo_error);
hfsutil_perrorp(argv[i]);
result = 1;
}
}
}
return result;
}
/*
* NAME: usage()
* DESCRIPTION: display usage message
*/
static
int usage(void)
{
fprintf(stderr, "Usage: %s [-m|-b|-t|-r|-a] source-path [...] target-path\n",
argv0);
return 1;
}
/*
* NAME: hcopy->main()
* DESCRIPTION: implement hcopy command
*/
int hcopy_main(int argc, char *argv[])
{
int nargs, mode = 'a', result = 0;
const char *target;
int fargc;
char **fargv;
hfsvol *vol;
int (*copy)(hfsvol *, int, char *[], const char *, int);
while (1)
{
int opt;
opt = getopt(argc, argv, "mbtra");
if (opt == EOF)
break;
switch (opt)
{
case '?':
return usage();
default:
mode = opt;
}
}
nargs = argc - optind;
if (nargs < 2)
return usage();
target = argv[argc - 1];
if (strchr(target, ':') && target[0] != '.' && target[0] != '/')
{
vol = hfsutil_remount(hcwd_getvol(-1), HFS_MODE_ANY);
if (vol == 0)
return 1;
copy = do_copyin;
fargc = nargs - 1;
fargv = &argv[optind];
}
else
{
vol = hfsutil_remount(hcwd_getvol(-1), HFS_MODE_RDONLY);
if (vol == 0)
return 1;
copy = do_copyout;
fargv = hfsutil_glob(vol, nargs - 1, &argv[optind], &fargc, &result);
}
if (result == 0)
result = copy(vol, fargc, fargv, target, mode);
hfsutil_unmount(vol, &result);
if (fargv && fargv != &argv[optind])
free(fargv);
return result;
}

22
hcopy.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: hcopy.h,v 1.6 1998/04/11 08:26:56 rob Exp $
*/
int hcopy_main(int, char *[]);

371
hcwd.c Normal file
View File

@ -0,0 +1,371 @@
/*
* hfsutils - tools 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: hcwd.c,v 1.9 1998/04/11 08:26:56 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <errno.h>
# include "hfs.h"
# include "hcwd.h"
# define STATEFNAME ".hcwd"
# define TABCHUNKSZ 8
static FILE *statef = 0;
static mountent *mounts = 0;
static int mtabsz = 0, nmounts = 0;
static int curvol = -1, dirty = 0;
extern int errno;
/*
* NAME: addent()
* DESCRIPTION: insert mount entry into table
*/
static
int addent(mountent *ent)
{
if (nmounts >= mtabsz)
{
mountent *newmem;
mtabsz += TABCHUNKSZ;
newmem = mounts ? realloc(mounts, mtabsz * sizeof(mountent)) :
malloc(mtabsz * sizeof(mountent));
if (newmem == 0)
return -1;
mounts = newmem;
}
mounts[nmounts++] = *ent;
dirty = 1;
return 0;
}
/*
* NAME: hcwd->init()
* DESCRIPTION: read state file
*/
int hcwd_init(void)
{
const char *home, *start;
char buf[512], *path, *ptr;
mountent entry;
int newcur = -1;
home = getenv("HOME");
if (home == 0)
home = "";
path = malloc(strlen(home) + 1 + sizeof(STATEFNAME));
if (path == 0)
return -1;
strcpy(path, home);
strcat(path, "/" STATEFNAME);
statef = fopen(path, "r+");
if (statef == 0 && errno == ENOENT)
statef = fopen(path, "w+");
free(path);
if (statef == 0)
return -1;
if (fgets(buf, sizeof(buf), statef))
newcur = atoi(buf);
while (fgets(buf, sizeof(buf), statef))
{
start = ptr = buf;
while (*ptr && *ptr != '\n' && *ptr != '\t')
++ptr;
entry.vname[0] = 0;
if (*ptr == '\t')
{
*ptr++ = 0;
strcpy(entry.vname, start);
start = ptr;
}
while (*ptr && *ptr != '\n' && *ptr != '\t')
++ptr;
if (*ptr == '\t')
{
*ptr++ = 0;
entry.vcrdate = strtol(start, 0, 0);
start = ptr;
}
while (*ptr && *ptr != '\n' && *ptr != '\t')
++ptr;
if (*ptr == '\t')
{
*ptr++ = 0;
entry.path = strdup(start);
if (entry.path == 0)
return -1;
start = ptr;
}
while (*ptr && *ptr != '\n' && *ptr != '\t')
++ptr;
if (*ptr == '\t')
{
*ptr++ = 0;
entry.partno = atoi(start);
start = ptr;
}
while (*ptr && *ptr != '\n' && *ptr != '\t')
++ptr;
if (*ptr == '\n' || *ptr == '\t')
*ptr = 0;
if (*start)
{
entry.cwd = strdup(start);
if (entry.cwd == 0)
return -1;
if (addent(&entry) == -1)
return -1;
}
}
curvol = (newcur >= 0 && newcur < nmounts) ? newcur : -1;
return 0;
}
/*
* NAME: hcwd->finish()
* DESCRIPTION: flush changes to state file
*/
int hcwd_finish(void)
{
if (statef && mounts && dirty)
{
int i;
rewind(statef);
if (ftruncate(fileno(statef), 0) == -1)
return -1;
fprintf(statef, "%d\n", curvol);
for (i = 0; i < nmounts; ++i)
fprintf(statef, "%s\t%ld\t%s\t%d\t%s\n",
mounts[i].vname,
mounts[i].vcrdate,
mounts[i].path,
mounts[i].partno,
mounts[i].cwd);
dirty = 0;
}
if (mounts)
{
mountent *ent;
for (ent = mounts; ent < mounts + nmounts; ++ent)
{
if (ent->path)
free(ent->path);
if (ent->cwd)
free(ent->cwd);
}
free(mounts);
}
if (statef && fclose(statef) == EOF)
return -1;
return 0;
}
/*
* NAME: hcwd->mounted()
* DESCRIPTION: register a mounted volume
*/
int hcwd_mounted(const char *vname, long vcrdate, const char *path, int partno)
{
mountent *entry, new;
for (entry = mounts; entry < mounts + nmounts; ++entry)
{
if (strcmp(entry->path, path) == 0 &&
entry->partno == partno)
{
/* update entry */
if (entry->cwd)
free(entry->cwd);
strcpy(entry->vname, vname);
entry->vcrdate = vcrdate;
entry->cwd = strdup(":");
if (entry->cwd == 0)
return -1;
curvol = entry - mounts;
dirty = 1;
return 0;
}
}
strcpy(new.vname, vname);
new.vcrdate = vcrdate;
new.path = strdup(path);
new.partno = partno;
new.cwd = strdup(":");
if (new.path == 0 ||
new.cwd == 0)
return -1;
if (addent(&new) == -1)
return -1;
curvol = nmounts - 1;
return 0;
}
/*
* NAME: hcwd->umounted()
* DESCRIPTION: unregister a previously mounted volume
*/
int hcwd_umounted(int vol)
{
mountent *entry;
int i;
if (vol < 0)
vol = curvol;
if (vol < 0 || vol >= nmounts)
return -1;
entry = &mounts[vol];
if (entry->path)
free(entry->path);
if (entry->cwd)
free(entry->cwd);
for (i = vol + 1; i < nmounts; ++i)
mounts[i - 1] = mounts[i];
--nmounts;
if (curvol > vol)
--curvol;
else if (curvol == vol)
curvol = -1;
return 0;
}
/*
* NAME: hcwd->getvol()
* DESCRIPTION: return a mount entity
*/
mountent *hcwd_getvol(int vol)
{
if (vol < 0)
vol = curvol;
if (vol < 0 || vol >= nmounts)
return 0;
return &mounts[vol];
}
/*
* NAME: hcwd->setvol()
* DESCRIPTION: change the current volume
*/
int hcwd_setvol(int vol)
{
if (vol < 0 || vol >= nmounts)
return -1;
if (curvol != vol)
{
curvol = vol;
dirty = 1;
}
return 0;
}
/*
* NAME: hcwd->setcwd()
* DESCRIPTION: change the current working directory for a mount entity
*/
int hcwd_setcwd(mountent *ent, const char *newcwd)
{
const char *path;
char *cwd;
path = newcwd;
while (*path && *path != ':')
++path;
memcpy(ent->vname, newcwd, path - newcwd);
ent->vname[path - newcwd] = 0;
cwd = (*path == 0) ? strdup(":") : strdup(path);
if (cwd == 0)
return -1;
if (ent->cwd)
free(ent->cwd);
ent->cwd = cwd;
dirty = 1;
return 0;
}

37
hcwd.h Normal file
View File

@ -0,0 +1,37 @@
/*
* hfsutils - tools 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: hcwd.h,v 1.8 1998/04/11 08:26:56 rob Exp $
*/
typedef struct {
char vname[HFS_MAX_VLEN + 1];
long vcrdate;
char *path;
int partno;
char *cwd;
} mountent;
int hcwd_init(void);
int hcwd_finish(void);
int hcwd_mounted(const char *, long, const char *, int);
int hcwd_umounted(int vol);
mountent *hcwd_getvol(int);
int hcwd_setvol(int);
int hcwd_setcwd(mountent *, const char *);

75
hdel.c Normal file
View File

@ -0,0 +1,75 @@
/*
* hfsutils - tools 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: hdel.c,v 1.6 1998/04/11 08:26:56 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <stdlib.h>
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "hdel.h"
/*
* NAME: hdel->main()
* DESCRIPTION: implement hdel command
*/
int hdel_main(int argc, char *argv[])
{
hfsvol *vol;
int fargc;
char **fargv;
int i, result = 0;
if (argc < 2)
{
fprintf(stderr, "Usage: %s hfs-path [...]\n", argv0);
return 1;
}
vol = hfsutil_remount(hcwd_getvol(-1), HFS_MODE_ANY);
if (vol == 0)
return 1;
fargv = hfsutil_glob(vol, argc - 1, &argv[1], &fargc, &result);
if (result == 0)
{
for (i = 0; i < fargc; ++i)
{
if (hfs_delete(vol, fargv[i]) == -1)
{
hfsutil_perrorp(fargv[i]);
result = 1;
}
}
}
hfsutil_unmount(vol, &result);
if (fargv)
free(fargv);
return result;
}

22
hdel.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: hdel.h,v 1.6 1998/04/11 08:26:57 rob Exp $
*/
int hdel_main(int, char *[]);

64
hdisk.pl Normal file
View File

@ -0,0 +1,64 @@
#! /usr/bin/perl
#
# hfsutils - tools 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: hdisk.pl,v 1.6 1998/04/11 08:26:57 rob Exp $
#
die "Usage: $0 device-path\n" unless (@ARGV == 1);
($disk) = @ARGV;
format STDOUT_TOP =
# Partition Type HFS Volume Name Start Length
-------------------------------------------------------------------------------
.
format STDOUT =
@# @<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<< @####### @########
$bnum, $pmParType, $drVN, $pmPyPartStart, $pmPartBlkCnt
.
open(DISK, $disk) || die "$disk: $!\n";
$bnum = 1;
do {
seek(DISK, 512 * $bnum, 0) || die "seek: $!\n";
read(DISK, $block, 512) || die "read: $!\n";
($pmSig, $pmMapBlkCnt, $pmPyPartStart, $pmPartBlkCnt, $pmParType) =
(unpack('n2 N3 A32 A32 N10 A16', $block))[0, 2..4, 6];
die "$disk: unsupported partition map\n" if ($pmSig == 0x5453);
die "$disk: no partition map\n" unless ($pmSig == 0x504d);
if ($pmParType eq 'Apple_HFS') {
seek(DISK, 512 * ($pmPyPartStart + 2), 0) || die "seek: $!\n";
read(DISK, $block, 512) || die "read: $!\n";
($len, $drVN) = (unpack('n N2 n5 N2 n N n c A27', $block))[13, 14];
$drVN = substr($drVN, 0, $len);
} else {
$drVN = '';
}
write;
} while ($bnum++ < $pmMapBlkCnt);
close(DISK);

190
hformat.c Normal file
View File

@ -0,0 +1,190 @@
/*
* hfsutils - tools 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: hformat.c,v 1.9 1998/11/02 22:08:31 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "suid.h"
# include "hformat.h"
# define O_FORCE 0x01
extern char *optarg;
extern int optind;
/*
* NAME: usage()
* DESCRIPTION: display usage message
*/
static
void usage(void)
{
fprintf(stderr, "Usage: %s [-f] [-l label] path [partition-no]\n", argv0);
}
/*
* NAME: do_format()
* DESCRIPTION: call hfs_format() with necessary privileges
*/
static
hfsvol *do_format(const char *path, int partno, int mode, const char *vname)
{
hfsvol *vol = 0;
suid_enable();
if (hfs_format(path, partno, mode, vname, 0, 0) != -1)
vol = hfs_mount(path, partno, HFS_MODE_ANY);
suid_disable();
return vol;
}
/*
* NAME: hformat->main()
* DESCRIPTION: implement hformat command
*/
int hformat_main(int argc, char *argv[])
{
const char *vname;
char *path = 0;
hfsvol *vol;
hfsvolent ent;
int nparts, partno, options = 0, result = 0;
vname = "Untitled";
while (1)
{
int opt;
opt = getopt(argc, argv, "fl:");
if (opt == EOF)
break;
switch (opt)
{
case '?':
usage();
goto fail;
case 'f':
options |= O_FORCE;
break;
case 'l':
vname = optarg;
break;
}
}
if (argc - optind < 1 || argc - optind > 2)
{
usage();
goto fail;
}
path = hfsutil_abspath(argv[optind]);
if (path == 0)
{
fprintf(stderr, "%s: not enough memory\n", argv0);
goto fail;
}
suid_enable();
nparts = hfs_nparts(path);
suid_disable();
if (argc - optind == 2)
{
partno = atoi(argv[optind + 1]);
if (nparts != -1 && partno == 0)
{
if (options & O_FORCE)
{
fprintf(stderr,
"%s: warning: erasing partition information\n", argv0);
}
else
{
fprintf(stderr, "%s: medium is partitioned; "
"select partition > 0 or use -f\n", argv0);
goto fail;
}
}
}
else
{
if (nparts > 1)
{
fprintf(stderr,
"%s: must specify partition number (%d available)\n",
argv0, nparts);
goto fail;
}
else if (nparts == -1)
partno = 0;
else
partno = 1;
}
vol = do_format(path, partno, 0, vname);
if (vol == 0)
{
hfsutil_perror(path);
goto fail;
}
hfs_vstat(vol, &ent);
hfsutil_pinfo(&ent);
if (hcwd_mounted(ent.name, ent.crdate, path, partno) == -1)
{
perror("Failed to record mount");
result = 1;
}
hfsutil_unmount(vol, &result);
free(path);
return result;
fail:
if (path)
free(path);
return 1;
}

22
hformat.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: hformat.h,v 1.7 1998/04/11 08:26:57 rob Exp $
*/
int hformat_main(int, char *[]);

491
hfs.tcl Normal file
View File

@ -0,0 +1,491 @@
#
# hfsutils - tools 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: hfs.tcl,v 1.9 1998/08/31 04:27:18 rob Exp $
#
proc ctime {secs} {
return [clock format $secs -format "%c"]
}
proc getvol {var} {
global curvol
upvar $var vol
if {! [info exists curvol]} {
error "no volume is current"
}
set vol $curvol
}
proc hinfo {} {
getvol vol
if {[$vol islocked]} {
set locked " (locked)"
} else {
set locked ""
}
puts stdout "Volume name is \"[$vol vname]\"$locked"
puts stdout "Volume was created on [ctime [$vol crdate]]"
puts stdout "Volume was last modified on [ctime [$vol mddate]]"
puts stdout "Volume has [lindex [$vol size] 1] bytes free"
}
proc hmount {path {partno ""}} {
global mounts curpath curvol
set nparts [hfs nparts $path]
if {$nparts >= 0} {
puts stdout [concat "$path contains $nparts HFS" \
[ternary {$nparts == 1} "partition" "partitions"]]
}
if {[string length $partno] == 0} {
if {$nparts > 0} {
puts stderr "partition unspecified; selecting number 1"
set partno 1
} elseif {$nparts == -1} {
set partno 0
} else {
set partno 1
}
}
set vol [hfs mount $path $partno]
if {[info exists mounts($path)]} {
humount $path
}
set curpath $path
set curvol $vol
set mounts($path) $vol
hinfo
}
proc humount {{path {}}} {
global mounts curpath curvol
if {[string length $path] == 0} {
if {! [info exists curpath]} {
error "no volume is current"
}
set path $curpath
} elseif {! [info exists mounts($path)]} {
error "$path not mounted"
}
set vol $mounts($path)
unset mounts($path)
if {[string compare $vol $curvol] == 0} {
unset curpath
unset curvol
}
$vol umount
}
proc hvol {name} {
global mounts curpath curvol
if {[info exists mounts($name)]} {
set curpath $name
set curvol $mounts($name)
return
}
error "unknown volume"
}
proc hpwd {} {
getvol vol
return "[join [$vol path] ":"]:"
}
proc hcd {{path ""}} {
getvol vol
set globbed [$vol glob [list $path]]
if {[llength $globbed] != 1} {
error "$path: ambiguous path"
}
set path [lindex $globbed 0]
if {[string length $path] == 0} {
set path "[$vol vname]:"
}
$vol cd $path
}
proc timestr {secs} {
set ctime [ctime $secs]
return "[string range $ctime 4 15][string range $ctime 19 23]"
}
proc ternary {test true false} {
if {[uplevel expr $test]} {
return $true
} else {
return $false
}
}
proc hdir {{path ":"}} {
getvol vol
set globbed [$vol glob [list $path]]
if {[llength $globbed] != 1} {
error "$path: ambiguous path"
}
set path [lindex $globbed 0]
foreach ent [$vol dir $path] {
array set item $ent
if {$item(kind) == "directory"} {
puts stdout [format "d%s %9lu item%s %s %s" \
[ternary {[lsearch $item(flags) "invis"] >= 0} "i" " "] \
$item(size) \
[ternary {$item(size) == 1} " " "s"] \
[timestr $item(mddate)] \
$item(name)]
} else {
puts stdout [format "%s%s %4s/%4s %9lu %9lu %s %s" \
[ternary {[lsearch $item(flags) "locked"] >= 0} "F" "f"] \
[ternary {[lsearch $item(flags) "invis"] >= 0} "i" " "] \
$item(type) \
$item(creator) \
$item(rsize) \
$item(dsize) \
[timestr $item(mddate)] \
$item(name)]
}
}
}
proc hstat {{path ":"}} {
getvol vol
set globbed [$vol glob [list $path]]
if {[llength $globbed] != 1} {
error "$path: ambiguous path"
}
set path [lindex $globbed 0]
array set item [$vol stat $path]
foreach elt [lsort [array names item]] {
if {[regexp {date$} $elt]} {
set value [ctime $item($elt)]
} else {
set value $item($elt)
}
puts stdout [format "%-10s %s" "$elt:" $value]
}
}
proc hmkdir {args} {
getvol vol
foreach arg [$vol glob $args] {
$vol mkdir $arg
}
}
proc hrmdir {args} {
getvol vol
foreach arg [$vol glob $args] {
$vol rmdir $arg
}
}
proc hcreate {path {type "TEXT"} {creator "UNIX"}} {
getvol vol
set file [$vol create $path $type $creator]
$file close
}
proc htouch {args} {
getvol vol
foreach arg [$vol glob $args] {
if [catch {$vol touch $arg}] {
hcreate $arg
}
}
}
proc hdel {args} {
getvol vol
foreach arg [$vol glob $args] {
$vol delete $arg
}
}
proc hrename {src dst} {
getvol vol
set globbed [$vol glob [list $src]]
if {[llength $globbed] != 1} {
error "$src: ambiguous path"
}
set src [lindex $globbed 0]
$vol rename $src $dst
}
proc hbless {path} {
getvol vol
set globbed [$vol glob [list $path]]
if {[llength $globbed] != 1} {
error "$path: ambiguous path"
}
set path [lindex $globbed 0]
$vol bless $path
}
proc hcat {path} {
getvol vol
set globbed [$vol glob [list $path]]
if {[llength $globbed] != 1} {
error "$path: ambiguous path"
}
set path [lindex $globbed 0]
set file [$vol open $path]
while {1} {
set buf [$file read 512]
if {[string length $buf] == 0} {
$file close
break
}
regsub -all "\r" $buf "\n" buf
puts -nonewline stdout $buf
}
}
proc hcopyout {path {dest "."} {mode ""}} {
getvol vol
set globbed [$vol glob [list $path]]
if {[llength $globbed] != 1} {
error "$path: ambiguous path"
}
set path [lindex $globbed 0]
if {[string length $mode] == 0} {
array set item [$vol stat $path]
if {$item(kind) == "directory"} {
error "can't copy whole directories"
} elseif {[regexp {^TEXT|ttro$} $item(type)]} {
set mode text
} else {
set mode macb
}
}
$vol copyout $mode $path $dest
}
proc hcopyin {path {dest ":"} {mode ""}} {
getvol vol
set globbed [$vol glob [list $path]]
if {[llength $globbed] != 1} {
error "$path: ambiguous path"
}
set path [lindex $globbed 0]
if {[string length $mode] == 0} {
if {[regexp {\.bin$} $path]} {
set mode macb
} elseif {[regexp {\.hqx$} $path]} {
set mode binh
} elseif {[regexp {\.(txt|c|h)$} $path]} {
set mode text
} elseif {[regexp {\.(sit|sea|cpt|tar|gz|Z|gif|jpg)$} $path]} {
set mode raw
} elseif {[catch {exec file -L $path} type] == 0 && \
[regexp {text} $type]} {
set mode text
} else {
set mode raw
}
}
$vol copyin $mode $path $dest
}
proc hformat {path {partno 0} {vname "Untitled"} {badblocks {}}} {
global mounts
if {[info exists mounts($path)]} {
humount $path
}
hfs format $path $partno $vname $badblocks
hmount $path $partno
}
###############################################################################
proc help {{what ""}} {
if {[string length $what]} {
if {[catch {info args h$what} msg]} {
puts stdout "Sorry, no help for \"$what\""
} else {
puts stdout "$what $msg"
}
} else {
puts stdout {
info Show current volume information
mount Open a new HFS volume
umount Close an HFS volume
vol Select an open volume
pwd Show the current working directory path
cd Change the current working directory
dir Show a directory listing
stat Show details about a given path
mkdir Create a new directory
rmdir Delete an empty directory
create Create an empty file
touch Update modification date or create a file
del Delete a file
rename Rename a file, directory, or volume
cat Display file's data fork contents
copyout Copy a complete file out into the native filesystem
copyin Copy a MacBinary/BinHex/text/raw file into HFS
format Create an empty HFS volume
}
}
}
proc ? {args} {
eval help $args
}
###############################################################################
proc version {} {
puts stdout "[hfs version] - [hfs copyright]"
}
proc license {} {
puts -nonewline stdout "\n[hfs license]"
}
proc author {} {
puts stdout [hfs author]
}
if {[string compare [lindex $argv 0] "--license"] == 0} {
license
exit
}
version
if {[string compare [lindex $argv 0] "--version"] == 0} {
puts stdout "`$argv0 --license' for licensing information."
exit
}
puts stdout "This is free software but comes with ABSOLUTELY NO WARRANTY."
if {$hfs_interactive} {
puts stdout "Type `license' for details."
}
puts stdout ""
###############################################################################
proc echo {args} {
puts stdout [join $args " "]
}
proc quit {} {
exit
}
###############################################################################
# Apparently some shells don't grok "$@" correctly
if {$argc == 1 && [string length [lindex $argv 0]] == 0} {
incr argc -1
set argv [lreplace $argv 0 0]
}
if {$argc > 0} {
eval hmount $argv
}
while {1} {
if {$hfs_interactive} {
puts -nonewline stdout "hfs> "
flush stdout
}
if {[gets stdin line] == -1} {
exit
}
while {! [info complete $line]} {
if {[gets stdin more] == -1} {
break
} else {
set line "$line$more"
}
}
if {[string length [info procs "h[lindex $line 0]"]] > 0} {
set result [catch {eval h$line} msg]
} else {
set result [catch {eval $line} msg]
}
if {[string length $msg] > 0} {
if {$result == 1} {
puts stdout "Error: $msg"
if {! $hfs_interactive} {
exit 1
}
} else {
puts stdout $msg
}
}
}

107
hfsck/Makefile.in Normal file
View File

@ -0,0 +1,107 @@
#
# hfsck - tool for checking and repairing the integrity of 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.in,v 1.6 1998/04/11 23:40:39 rob Exp $
#
@SET_MAKE@
src = @srcdir@
VPATH = @srcdir@
### USER CUSTOMIZATIONS FOLLOW ################################################
prefix = @prefix@
exec_prefix = @exec_prefix@
MANDEST = @mandir@
INCDEST = @includedir@
LIBDEST = @libdir@
INSTALL = @INSTALL@
LIBINSTALL = @INSTALL_DATA@
CC = @CC@
INCLUDES = @CPPFLAGS@ -I.. -I../libhfs
DEFINES = @DEFS@
LIBOBJS = @LIBOBJS@ ../suid.o ../version.o
LIBS = @LIBS@ -L../libhfs -lhfs
COPTS = @CFLAGS@
LDOPTS = @LDFLAGS@
### END OF USER CUSTOMIZATION #################################################
CFLAGS = $(COPTS) $(INCLUDES) $(DEFINES)
LDFLAGS = $(LDOPTS)
###############################################################################
TARGETS = $(HFSCKTARGET)
HFSCKTARGET = hfsck
HFSCKOBJS = ck_mdb.o ck_volume.o ck_btree.o hfsck.o util.o main.o \
$(LIBOBJS)
###############################################################################
all :: $(TARGETS)
again :: clean all
depend ::
( sed -n '1,/^### DEPEND/p' Makefile.in; \
echo; \
$(CC) -MM $(INCLUDES) $(DEFINES) *.c; \
) > Makefile.in.new
mv -f Makefile.in.new Makefile.in
clean ::
rm -f $(TARGETS) *.o gmon.* core
###############################################################################
$(HFSCKTARGET): $(HFSCKOBJS)
$(CC) $(LDFLAGS) $(HFSCKOBJS) $(LIBS) -o $@
### DEPENDENCIES FOLLOW #######################################################
ck_btree.o: ck_btree.c hfsck.h ../libhfs/libhfs.h ../libhfs/hfs.h \
../libhfs/apple.h ../libhfs/data.h ../libhfs/block.h ../libhfs/low.h \
../libhfs/file.h ../libhfs/btree.h ../libhfs/node.h \
../libhfs/record.h ../libhfs/volume.h util.h ck_btree.h
ck_mdb.o: ck_mdb.c hfsck.h ../libhfs/libhfs.h ../libhfs/hfs.h \
../libhfs/apple.h ../libhfs/data.h ../libhfs/block.h ../libhfs/low.h \
../libhfs/file.h ../libhfs/btree.h ../libhfs/node.h \
../libhfs/record.h ../libhfs/volume.h util.h ck_mdb.h
ck_volume.o: ck_volume.c hfsck.h ../libhfs/libhfs.h ../libhfs/hfs.h \
../libhfs/apple.h ../libhfs/data.h ../libhfs/block.h ../libhfs/low.h \
../libhfs/file.h ../libhfs/btree.h ../libhfs/node.h \
../libhfs/record.h ../libhfs/volume.h ck_volume.h
hfsck.o: hfsck.c hfsck.h ../libhfs/libhfs.h ../libhfs/hfs.h \
../libhfs/apple.h ../libhfs/data.h ../libhfs/block.h ../libhfs/low.h \
../libhfs/file.h ../libhfs/btree.h ../libhfs/node.h \
../libhfs/record.h ../libhfs/volume.h ck_mdb.h ck_volume.h ck_btree.h
main.o: main.c hfsck.h ../libhfs/libhfs.h ../libhfs/hfs.h \
../libhfs/apple.h ../libhfs/data.h ../libhfs/block.h ../libhfs/low.h \
../libhfs/file.h ../libhfs/btree.h ../libhfs/node.h \
../libhfs/record.h ../libhfs/volume.h ../suid.h ../version.h
util.o: util.c hfsck.h ../libhfs/libhfs.h ../libhfs/hfs.h \
../libhfs/apple.h ../libhfs/data.h ../libhfs/block.h ../libhfs/low.h \
../libhfs/file.h ../libhfs/btree.h ../libhfs/node.h \
../libhfs/record.h ../libhfs/volume.h util.h

96
hfsck/ck_btree.c Normal file
View File

@ -0,0 +1,96 @@
/*
* hfsck - tool for checking and repairing the integrity of 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: ck_btree.c,v 1.7 1998/04/11 08:27:07 rob Exp $
*/
# include <stdio.h>
# include "hfsck.h"
# include "util.h"
# include "ck_btree.h"
/*
* NAME: ck->btree()
* DESCRIPTION: verify/repair a b*-tree
*/
int ck_btree(btree *bt)
{
printf("*** Checking %s B*-tree\n", bt->f.name);
if (bt_readhdr(bt) == -1)
return -1;
if (VERBOSE)
{
printf(" bthDepth = %u\n", bt->hdr.bthDepth);
printf(" bthRoot = %lu\n", bt->hdr.bthRoot);
printf(" bthNRecs = %lu\n", bt->hdr.bthNRecs);
printf(" bthFNode = %lu\n", bt->hdr.bthFNode);
printf(" bthLNode = %lu\n", bt->hdr.bthLNode);
printf(" bthNodeSize = %u\n", bt->hdr.bthNodeSize);
printf(" bthKeyLen = %u\n", bt->hdr.bthKeyLen);
printf(" bthNNodes = %lu\n", bt->hdr.bthNNodes);
printf(" bthFree = %lu\n", bt->hdr.bthFree);
}
# if 0
if (VERBOSE)
{
node n;
int i;
n.bt = bt;
n.nnum = bt->hdr.bthFNode;
while (n.nnum)
{
if (bt_getnode(&n) == -1)
return -1;
if (n.nnum == bt->hdr.bthFNode)
printf(" { ");
else
printf("} { ");
for (i = 0; i < n.nd.ndNRecs; ++i)
{
byte *ptr;
ptr = HFS_NODEREC(n, i);
outhex(ptr, 1 + HFS_RECKEYLEN(ptr));
printf(": ");
outhex(HFS_RECDATA(ptr),
HFS_NODEREC(n, i + 1) - HFS_RECDATA(ptr));
printf("\n");
if (i < n.nd.ndNRecs - 1)
printf(" ");
}
n.nnum = n.nd.ndFLink;
}
printf("}\n");
}
# endif
return 0;
}

22
hfsck/ck_btree.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsck - tool for checking and repairing the integrity of 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: ck_btree.h,v 1.6 1998/04/11 08:27:07 rob Exp $
*/
int ck_btree(btree *);

234
hfsck/ck_mdb.c Normal file
View File

@ -0,0 +1,234 @@
/*
* hfsck - tool for checking and repairing the integrity of 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: ck_mdb.c,v 1.8 1998/04/11 08:27:07 rob Exp $
*/
# include <stdio.h>
# include <string.h>
# include <time.h>
# include "hfsck.h"
# include "util.h"
# include "ck_mdb.h"
/*
* NAME: ck->mdb()
* DESCRIPTION: verify/repair the master directory block
*/
int ck_mdb(hfsvol *vol)
{
MDB *mdb = &vol->mdb;
time_t now;
printf("*** Checking volume MDB\n");
if (VERBOSE)
{
int flag;
printf(" drSigWord = 0x%04x\n", mdb->drSigWord);
printf(" drCrDate = %s\n", mctime(mdb->drCrDate));
printf(" drLsMod = %s\n", mctime(mdb->drLsMod));
printf(" drAtrb =");
flag = 0;
if (mdb->drAtrb & HFS_ATRB_BUSY)
{
printf("%s BUSY", flag ? " |" : "");
flag = 1;
}
if (mdb->drAtrb & HFS_ATRB_HLOCKED)
{
printf("%s HLOCKED", flag ? " |" : "");
flag = 1;
}
if (mdb->drAtrb & HFS_ATRB_UMOUNTED)
{
printf("%s UMOUNTED", flag ? " |" : "");
flag = 1;
}
if (mdb->drAtrb & HFS_ATRB_BBSPARED)
{
printf("%s BBSPARED", flag ? " |" : "");
flag = 1;
}
if (mdb->drAtrb & HFS_ATRB_BVINCONSIS)
{
printf("%s BVINCONSIS", flag ? " |" : "");
flag = 1;
}
if (mdb->drAtrb & HFS_ATRB_COPYPROT)
{
printf("%s COPYPROT", flag ? " |" : "");
flag = 1;
}
if (mdb->drAtrb & HFS_ATRB_SLOCKED)
{
printf("%s SLOCKED", flag ? " |" : "");
flag = 1;
}
if (flag == 0)
printf(" 0");
printf("\n");
printf(" drNmFls = %u\n", mdb->drNmFls);
printf(" drVBMSt = %u\n", mdb->drVBMSt);
printf(" drAllocPtr = %u\n", mdb->drAllocPtr);
printf(" drNmAlBlks = %u\n", mdb->drNmAlBlks);
printf(" drAlBlkSiz = %lu\n", mdb->drAlBlkSiz);
printf(" drClpSiz = %lu\n", mdb->drClpSiz);
printf(" drAlBlSt = %u\n", mdb->drAlBlSt);
printf(" drNxtCNID = %lu\n", mdb->drNxtCNID);
printf(" drFreeBks = %u\n", mdb->drFreeBks);
printf(" drVN = \"%s\"\n", mdb->drVN);
printf(" drVolBkUp = %s\n", mctime(mdb->drVolBkUp));
printf(" drVSeqNum = %u\n", mdb->drVSeqNum);
printf(" drWrCnt = %lu\n", mdb->drWrCnt);
printf(" drXTClpSiz = %lu\n", mdb->drXTClpSiz);
printf(" drCTClpSiz = %lu\n", mdb->drCTClpSiz);
printf(" drNmRtDirs = %u\n", mdb->drNmRtDirs);
printf(" drFilCnt = %lu\n", mdb->drFilCnt);
printf(" drDirCnt = %lu\n", mdb->drDirCnt);
/* drFndrInfo */
printf(" drEmbedSigWord = 0x%04x\n", mdb->drEmbedSigWord);
printf(" drEmbedExtent = %s\n", extstr(&mdb->drEmbedExtent));
printf(" drXTFlSize = %lu\n", mdb->drXTFlSize);
printf(" drXTExtRec = %s\n", extrecstr(&mdb->drXTExtRec));
printf(" drCTFlSize = %lu\n", mdb->drCTFlSize);
printf(" drCTExtRec = %s\n", extrecstr(&mdb->drCTExtRec));
}
/* mdb->drSigWord */
if (mdb->drSigWord != HFS_SIGWORD &&
ask("Bad volume signature (0x%04x); should be 0x%04x",
mdb->drSigWord, HFS_SIGWORD))
{
mdb->drSigWord = HFS_SIGWORD;
vol->flags |= HFS_VOL_UPDATE_MDB;
}
/* mdb->drCrDate */
time(&now);
if (mdb->drCrDate == 0 &&
ask("Volume creation date is unset"))
{
mdb->drCrDate = d_mtime(now);
vol->flags |= HFS_VOL_UPDATE_MDB;
}
if (d_ltime(mdb->drCrDate) > now &&
ask("Volume creation date is in the future (%s)", mctime(mdb->drCrDate)))
{
mdb->drCrDate = d_mtime(now);
vol->flags |= HFS_VOL_UPDATE_MDB;
}
/* mdb->drLsMod */
if (mdb->drLsMod == 0 &&
ask("Volume last modify date is unset"))
{
mdb->drLsMod = mdb->drCrDate;
vol->flags |= HFS_VOL_UPDATE_MDB;
}
if (d_ltime(mdb->drLsMod) > now &&
ask("Volume last modify date is in the future (%s)",
mctime(mdb->drLsMod)))
{
mdb->drLsMod = d_mtime(now);
vol->flags |= HFS_VOL_UPDATE_MDB;
}
if (mdb->drLsMod < mdb->drCrDate &&
ask("Volume last modify date is before volume creation"))
{
mdb->drLsMod = mdb->drCrDate;
vol->flags |= HFS_VOL_UPDATE_MDB;
}
/* mdb->drAtrb */
/* mdb->drNmFls */
/* mdb->drVBMSt */
if (mdb->drVBMSt != 3 &&
ask("Volume bitmap starts at unusual location (%u), not 3"))
{
mdb->drVBMSt = 3;
vol->flags |= HFS_VOL_UPDATE_MDB;
}
/* mdb->drAllocPtr */
/* ... */
/* initialize other important fields */
vol->lpa = vol->mdb.drAlBlkSiz >> HFS_BLOCKSZ_BITS;
/* extents pseudo-file structs */
vol->ext.f.cat.u.fil.filStBlk = vol->mdb.drXTExtRec[0].xdrStABN;
vol->ext.f.cat.u.fil.filLgLen = vol->mdb.drXTFlSize;
vol->ext.f.cat.u.fil.filPyLen = vol->mdb.drXTFlSize;
vol->ext.f.cat.u.fil.filCrDat = vol->mdb.drCrDate;
vol->ext.f.cat.u.fil.filMdDat = vol->mdb.drLsMod;
vol->ext.f.cat.u.fil.filClpSize = vol->mdb.drXTClpSiz;
memcpy(&vol->ext.f.cat.u.fil.filExtRec,
&vol->mdb.drXTExtRec, sizeof(ExtDataRec));
f_selectfork(&vol->ext.f, fkData);
/* catalog pseudo-file structs */
vol->cat.f.cat.u.fil.filStBlk = vol->mdb.drCTExtRec[0].xdrStABN;
vol->cat.f.cat.u.fil.filLgLen = vol->mdb.drCTFlSize;
vol->cat.f.cat.u.fil.filPyLen = vol->mdb.drCTFlSize;
vol->cat.f.cat.u.fil.filCrDat = vol->mdb.drCrDate;
vol->cat.f.cat.u.fil.filMdDat = vol->mdb.drLsMod;
vol->cat.f.cat.u.fil.filClpSize = vol->mdb.drCTClpSiz;
memcpy(&vol->cat.f.cat.u.fil.filExtRec,
&vol->mdb.drCTExtRec, sizeof(ExtDataRec));
f_selectfork(&vol->cat.f, fkData);
return 0;
}

22
hfsck/ck_mdb.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsck - tool for checking and repairing the integrity of 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: ck_mdb.h,v 1.6 1998/04/11 08:27:07 rob Exp $
*/
int ck_mdb(hfsvol *);

37
hfsck/ck_volume.c Normal file
View File

@ -0,0 +1,37 @@
/*
* hfsck - tool for checking and repairing the integrity of 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: ck_volume.c,v 1.6 1998/04/11 08:27:08 rob Exp $
*/
# include <stdio.h>
# include "hfsck.h"
# include "ck_volume.h"
/*
* NAME: ck->volume()
* DESCRIPTION: verify/repair general volume structure
*/
int ck_volume(hfsvol *vol)
{
printf("*** Checking volume structure\n");
return 0;
}

22
hfsck/ck_volume.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsck - tool for checking and repairing the integrity of 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: ck_volume.h,v 1.6 1998/04/11 08:27:08 rob Exp $
*/
int ck_volume(hfsvol *);

34
hfsck/hfsck.c Normal file
View File

@ -0,0 +1,34 @@
/*
* hfsck - tool for checking and repairing the integrity of 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: hfsck.c,v 1.7 1998/04/11 08:27:08 rob Exp $
*/
# include <stdio.h>
# include "hfsck.h"
# include "ck_mdb.h"
# include "ck_volume.h"
# include "ck_btree.h"
int hfsck(hfsvol *vol)
{
return ck_mdb(vol) || ck_volume(vol) ||
ck_btree(&vol->ext) || ck_btree(&vol->cat);
}

42
hfsck/hfsck.h Normal file
View File

@ -0,0 +1,42 @@
/*
* hfsck - tool for checking and repairing the integrity of 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: hfsck.h,v 1.6 1998/04/11 08:27:08 rob Exp $
*/
# include "libhfs.h"
# include "data.h"
# include "block.h"
# include "low.h"
# include "file.h"
# include "btree.h"
# include "node.h"
# include "record.h"
# include "volume.h"
# define HFSCK_REPAIR 0x0001
# define HFSCK_VERBOSE 0x0100
# define HFSCK_YES 0x0200
# define REPAIR (options & HFSCK_REPAIR)
# define VERBOSE (options & HFSCK_VERBOSE)
# define YES (options & HFSCK_YES)
extern int options;
int hfsck(hfsvol *);

220
hfsck/main.c Normal file
View File

@ -0,0 +1,220 @@
/*
* hfsck - tool for checking and repairing the integrity of 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: main.c,v 1.8 1998/11/02 22:08:50 rob Exp $
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <errno.h>
# include "hfsck.h"
# include "suid.h"
# include "version.h"
int options;
extern int optind;
/*
* NAME: usage()
* DESCRIPTION: display usage message
*/
static
int usage(char *argv[])
{
fprintf(stderr, "Usage: %s [-v] [-n] [-a] device-path [partition-no]\n",
argv[0]);
return 1;
}
/*
* NAME: main()
* DESCRIPTION: program entry
*/
int main(int argc, char *argv[])
{
char *path;
int nparts, pnum, result;
hfsvol vol;
suid_init();
if (argc == 2)
{
if (strcmp(argv[1], "--version") == 0)
{
printf("%s - %s\n", hfsutils_version, hfsutils_copyright);
printf("`%s --license' for licensing information.\n", argv[0]);
return 0;
}
else if (strcmp(argv[1], "--license") == 0)
{
printf("\n%s", hfsutils_license);
return 0;
}
}
options = HFSCK_REPAIR;
while (1)
{
int opt;
opt = getopt(argc, argv, "vna");
if (opt == EOF)
break;
switch (opt)
{
case '?':
return usage(argv);
case 'v':
options |= HFSCK_VERBOSE;
break;
case 'n':
options &= ~HFSCK_REPAIR;
break;
case 'a':
options |= HFSCK_YES;
break;
}
}
if (argc - optind < 1 ||
argc - optind > 2)
return usage(argv);
path = argv[optind];
suid_enable();
nparts = hfs_nparts(path);
suid_disable();
if (nparts == 0)
{
fprintf(stderr, "%s: partitioned medium contains no HFS partitions\n",
argv[0]);
return 1;
}
if (argc - optind == 2)
{
pnum = atoi(argv[optind + 1]);
if (pnum < 0)
{
fprintf(stderr, "%s: invalid partition number\n", argv[0]);
return 1;
}
if (nparts == -1 && pnum > 0)
{
fprintf(stderr, "%s: warning: ignoring partition number for"
" non-partitioned medium\n", argv[0]);
pnum = 0;
}
else if (nparts > 0 && pnum == 0)
{
fprintf(stderr, "%s: cannot specify whole medium"
" (has %d partition%s)\n", argv[0], nparts,
nparts == 1 ? "" : "s");
return 1;
}
else if (nparts > 0 && pnum > nparts)
{
fprintf(stderr, "%s: invalid partition number (only %d available)\n",
argv[0], nparts);
return 1;
}
}
else
{
if (nparts > 1)
{
fprintf(stderr, "%s: must specify partition number (%d available)\n",
argv[0], nparts);
return 1;
}
else if (nparts == -1)
pnum = 0;
else
pnum = 1;
}
v_init(&vol, HFS_OPT_NOCACHE);
if (REPAIR)
{
suid_enable();
result = v_open(&vol, path, HFS_MODE_RDWR);
suid_disable();
if (result == -1)
{
vol.flags |= HFS_VOL_READONLY;
suid_enable();
result = v_open(&vol, path, HFS_MODE_RDONLY);
suid_disable();
}
}
if (result == -1)
{
perror(path);
return 1;
}
if (REPAIR && (vol.flags & HFS_VOL_READONLY))
{
fprintf(stderr, "%s: warning: %s not writable; cannot repair\n",
argv[0], path);
options &= ~HFSCK_REPAIR;
}
if (v_geometry(&vol, pnum) == -1 ||
l_getmdb(&vol, &vol.mdb, 0) == -1)
{
perror(path);
v_close(&vol);
return 1;
}
result = hfsck(&vol);
vol.flags |= HFS_VOL_MOUNTED;
if (v_close(&vol) == -1)
{
perror("closing volume");
return 1;
}
return result;
}

179
hfsck/util.c Normal file
View File

@ -0,0 +1,179 @@
/*
* hfsck - tool for checking and repairing the integrity of 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: util.c,v 1.7 1998/04/11 08:27:08 rob Exp $
*/
# include <stdio.h>
# include <string.h>
# include <stdarg.h>
# include "hfsck.h"
# include "util.h"
/*
* NAME: mctime()
* DESCRIPTION: convert Macintosh time to an ASCII string
*/
char *mctime(unsigned long secs)
{
time_t date;
static char str[26];
if (secs == 0)
return "(Never)";
date = d_ltime(secs);
strcpy(str, ctime(&date));
str[24] = 0;
return str;
}
/*
* NAME: extstr()
* DESCRIPTION: convert an extent descriptor into a printable string
*/
char *extstr(ExtDescriptor *ext)
{
static char str[20];
switch (ext->xdrNumABlks)
{
case 0:
return "[]";
case 1:
sprintf(str, "1[%u]", ext->xdrStABN);
break;
default:
sprintf(str, "%u[%u..%u]", ext->xdrNumABlks,
ext->xdrStABN, ext->xdrStABN + ext->xdrNumABlks - 1);
}
return str;
}
/*
* NAME: extrecstr()
* DESCRIPTION: convert an extent record into a printable string
*/
char *extrecstr(ExtDataRec *rec)
{
static char str[60];
ExtDescriptor *ext;
int i;
str[0] = 0;
for (i = 0, ext = &(*rec)[0]; i < 3; ++i, ++ext)
{
if (i > 0)
strcat(str, "+");
strcat(str, extstr(ext));
}
return str;
}
/*
* NAME: outhex()
* DESCRIPTION: output a block of data in hex format
*/
void outhex(unsigned char *data, unsigned int len)
{
int toggle = 0;
while (len--)
printf("%02x%s", *data++, toggle++ & 0x01 ? " " : "");
}
/*
* NAME: ask()
* DESCRIPTION: answer question from user
*/
int ask(char *question, ...)
{
int result = -1;
va_list args;
va_start(args, question);
vprintf(question, args);
if (! REPAIR)
{
printf(".\n");
result = 0;
}
else if (YES)
{
printf(": fixing.\n");
result = 1;
}
else
{
while (1)
{
char answer[80];
if (feof(stdin))
{
printf("...\n");
result = 0;
break;
}
printf(". Fix? ");
fflush(stdout);
fgets(answer, sizeof(answer), stdin);
if (feof(stdin))
{
printf("\n");
result = 0;
break;
}
switch (answer[0])
{
case 'y':
case 'Y':
result = 1;
break;
case 'n':
case 'N':
result = 0;
break;
}
if (result == -1)
vprintf(question, args);
else
break;
}
}
va_end(args);
return result;
}

26
hfsck/util.h Normal file
View File

@ -0,0 +1,26 @@
/*
* hfsck - tool for checking and repairing the integrity of 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: util.h,v 1.6 1998/04/11 08:27:08 rob Exp $
*/
char *mctime(unsigned long);
char *extstr(ExtDescriptor *);
char *extrecstr(ExtDataRec *);
void outhex(unsigned char *, unsigned int);
int ask(char *, ...);

64
hfssh.c Normal file
View File

@ -0,0 +1,64 @@
/*
* hfsutils - tools 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: hfssh.c,v 1.8 1998/04/11 08:26:57 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
# include <tcl.h>
# include "tclhfs.h"
# include "suid.h"
/*
* NAME: Tcl->AppInit()
* DESCRIPTION: initialize interpreter
*/
int Tcl_AppInit(Tcl_Interp *interp)
{
Tcl_SetVar(interp, "hfs_interactive",
isatty(STDIN_FILENO) ? "1" : "0", TCL_GLOBAL_ONLY);
if (Tcl_Init(interp) == TCL_ERROR)
return TCL_ERROR;
if (Hfs_Init(interp) == TCL_ERROR)
return TCL_ERROR;
return TCL_OK;
}
/*
* NAME: main()
* DESCRIPTION: program entry
*/
int main(int argc, char *argv[])
{
suid_init();
Tcl_Main(argc, argv, Tcl_AppInit);
return 0; /* not reached */
}

401
hfsutil.c Normal file
View File

@ -0,0 +1,401 @@
/*
* hfsutils - tools 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: hfsutil.c,v 1.9 1998/09/28 23:21:49 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <time.h>
# include <ctype.h>
# include <errno.h>
# include <sys/stat.h>
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# else
char *getcwd(char *buf, size_t size);
# endif
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "suid.h"
# include "glob.h"
# include "version.h"
# include "hattrib.h"
# include "hcd.h"
# include "hcopy.h"
# include "hdel.h"
# include "hformat.h"
# include "hls.h"
# include "hmkdir.h"
# include "hmount.h"
# include "hpwd.h"
# include "hrename.h"
# include "hrmdir.h"
# include "humount.h"
# include "hvol.h"
const char *argv0, *bargv0;
/*
* NAME: main()
* DESCRIPTION: program entry dispatch
*/
int main(int argc, char *argv[])
{
int i, len;
const char *dot;
struct {
const char *name;
int (*func)(int, char *[]);
} list[] = {
{ "hattrib", hattrib_main },
{ "hcd", hcd_main },
{ "hcopy", hcopy_main },
{ "hdel", hdel_main },
{ "hdir", hls_main },
{ "hformat", hformat_main },
{ "hls", hls_main },
{ "hmkdir", hmkdir_main },
{ "hmount", hmount_main },
{ "hpwd", hpwd_main },
{ "hrename", hrename_main },
{ "hrmdir", hrmdir_main },
{ "humount", humount_main },
{ "hvol", hvol_main },
{ 0, 0 }
};
suid_init();
if (argc == 2)
{
if (strcmp(argv[1], "--version") == 0)
{
printf("%s - %s\n", hfsutils_version, hfsutils_copyright);
printf("`%s --license' for licensing information.\n", argv[0]);
return 0;
}
else if (strcmp(argv[1], "--license") == 0)
{
printf("\n%s", hfsutils_license);
return 0;
}
}
argv0 = argv[0];
bargv0 = strrchr(argv0, '/');
if (bargv0 == 0)
bargv0 = argv0;
else
++bargv0;
dot = strchr(bargv0, '.');
len = dot ? dot - bargv0 : strlen(bargv0);
for (i = 0; list[i].name; ++i)
{
if (strncmp(bargv0, list[i].name, len) == 0)
{
int result;
bargv0 = list[i].name;
if (hcwd_init() == -1)
{
perror("Failed to initialize HFS working directories");
return 1;
}
result = list[i].func(argc, argv);
if (hcwd_finish() == -1)
{
perror("Failed to save working directory state");
return 1;
}
return result;
}
}
fprintf(stderr, "%s: Unknown operation `%s'\n", argv0, bargv0);
return 1;
}
/*
* NAME: hfsutil->perror()
* DESCRIPTION: output an HFS error
*/
void hfsutil_perror(const char *msg)
{
const char *str = strerror(errno);
if (hfs_error == 0)
fprintf(stderr, "%s: %s: %c%s\n", argv0, msg, tolower(*str), str + 1);
else
fprintf(stderr, "%s: %s: %s (%s)\n", argv0, msg, hfs_error, str);
}
/*
* NAME: hfsutil->perrorp()
* DESCRIPTION: output an HFS error for a pathname
*/
void hfsutil_perrorp(const char *path)
{
const char *str = strerror(errno);
if (hfs_error == 0)
fprintf(stderr, "%s: \"%s\": %c%s\n", argv0, path, tolower(*str), str + 1);
else
fprintf(stderr, "%s: \"%s\": %s (%s)\n", argv0, path, hfs_error, str);
}
/*
* NAME: hfsutil->remount()
* DESCRIPTION: mount a volume as though it were still mounted
*/
hfsvol *hfsutil_remount(mountent *ment, int flags)
{
hfsvol *vol;
hfsvolent vent;
if (ment == 0)
{
fprintf(stderr, "%s: No volume is current; use `hmount' or `hvol'\n",
argv0);
return 0;
}
suid_enable();
vol = hfs_mount(ment->path, ment->partno, flags);
suid_disable();
if (vol == 0)
{
hfsutil_perror(ment->path);
return 0;
}
hfs_vstat(vol, &vent);
if (strcmp(vent.name, ment->vname) != 0)
{
fprintf(stderr, "%s: Expected volume \"%s\" not found\n",
argv0, ment->vname);
fprintf(stderr, "%s: Replace media on %s or use `hmount'\n",
argv0, ment->path);
hfs_umount(vol);
return 0;
}
if (hfs_chdir(vol, ment->cwd) == -1)
{
fprintf(stderr, "%s: Current HFS directory \"%s%s:\" no longer exists\n",
argv0, ment->vname, ment->cwd);
}
return vol;
}
/*
* NAME: hfsutil->unmount()
* DESCRIPTION: unmount a volume
*/
void hfsutil_unmount(hfsvol *vol, int *result)
{
if (hfs_umount(vol) == -1 && *result == 0)
{
hfsutil_perror("Error closing HFS volume");
*result = 1;
}
}
/*
* NAME: hfsutil->pinfo()
* DESCRIPTION: print information about a volume
*/
void hfsutil_pinfo(hfsvolent *ent)
{
printf("Volume name is \"%s\"%s\n", ent->name,
(ent->flags & HFS_ISLOCKED) ? " (locked)" : "");
printf("Volume was created on %s", ctime(&ent->crdate));
printf("Volume was last modified on %s", ctime(&ent->mddate));
printf("Volume has %lu bytes free\n", ent->freebytes);
}
/*
* NAME: hfsutil->glob()
* DESCRIPTION: perform filename globbing
*/
char **hfsutil_glob(hfsvol *vol, int argc, char *argv[],
int *nelts, int *result)
{
char **fargv;
fargv = hfs_glob(vol, argc, argv, nelts);
if (fargv == 0 && *result == 0)
{
fprintf(stderr, "%s: globbing error\n", argv0);
*result = 1;
}
return fargv;
}
/*
* NAME: hfsutil->getcwd()
* DESCRIPTION: return full path to current directory (must be free()'d)
*/
char *hfsutil_getcwd(hfsvol *vol)
{
char *path, name[HFS_MAX_FLEN + 1 + 1];
long cwd;
int pathlen;
path = malloc(1);
path[0] = 0;
pathlen = 0;
cwd = hfs_getcwd(vol);
while (cwd != HFS_CNID_ROOTPAR)
{
char *new;
int namelen, i;
if (hfs_dirinfo(vol, &cwd, name) == -1)
return 0;
if (pathlen)
strcat(name, ":");
namelen = strlen(name);
new = realloc(path, namelen + pathlen + 1);
if (new == 0)
{
free(path);
ERROR(ENOMEM, 0);
return 0;
}
if (pathlen == 0)
new[0] = 0;
path = new;
/* push string down to make room for path prefix (memmove()-ish) */
i = pathlen + 1;
for (new = path + namelen + pathlen; i--; new--)
*new = *(new - namelen);
memcpy(path, name, namelen);
pathlen += namelen;
}
return path;
}
/*
* NAME: hfsutil->samepath()
* DESCRIPTION: return 1 iff paths refer to same object
*/
int hfsutil_samepath(const char *path1, const char *path2)
{
struct stat sbuf1, sbuf2;
return
stat(path1, &sbuf1) == 0 &&
stat(path2, &sbuf2) == 0 &&
sbuf1.st_dev == sbuf2.st_dev &&
sbuf1.st_ino == sbuf2.st_ino;
}
/*
* NAME: hfsutil->abspath()
* DESCRIPTION: make given UNIX path absolute (must be free()'d)
*/
char *hfsutil_abspath(const char *path)
{
char *cwd, *buf;
size_t len;
if (path[0] == '/')
return strdup(path);
cwd = getenv("PWD");
if (cwd && hfsutil_samepath(cwd, "."))
{
buf = malloc(strlen(cwd) + 1 + strlen(path) + 1);
if (buf == 0)
return 0;
strcpy(buf, cwd);
}
else
{
len = 32;
cwd = malloc(len);
if (cwd == 0)
return 0;
while (getcwd(cwd, len) == 0)
{
if (errno != ERANGE)
{
free(cwd);
return 0;
}
len <<= 1;
buf = realloc(cwd, len);
if (buf == 0)
{
free(cwd);
return 0;
}
cwd = buf;
}
buf = realloc(cwd, strlen(cwd) + 1 + strlen(path) + 1);
if (buf == 0)
{
free(cwd);
return 0;
}
}
strcat(buf, "/");
strcat(buf, path);
return buf;
}

39
hfsutil.h Normal file
View File

@ -0,0 +1,39 @@
/*
* hfsutils - tools 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: hfsutil.h,v 1.8 1998/04/11 08:26:57 rob Exp $
*/
extern int errno;
# define ERROR(code, str) (hfs_error = (str), errno = (code))
extern const char *argv0, *bargv0;
void hfsutil_perror(const char *);
void hfsutil_perrorp(const char *);
hfsvol *hfsutil_remount(mountent *, int);
void hfsutil_unmount(hfsvol *, int *);
void hfsutil_pinfo(hfsvolent *);
char **hfsutil_glob(hfsvol *, int, char *[], int *, int *);
char *hfsutil_getcwd(hfsvol *);
int hfsutil_samepath(const char *, const char *);
char *hfsutil_abspath(const char *);

136
hfswish.c Normal file
View File

@ -0,0 +1,136 @@
/*
* hfsutils - tools 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: hfswish.c,v 1.9 1998/04/11 08:26:57 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <stdlib.h>
# include <tk.h>
# include "tclhfs.h"
# include "xhfs.h"
# include "suid.h"
# include "images.h"
static
char *argv0;
# define DEFBITMAP(interp, name) \
Tk_DefineBitmap(interp, Tk_GetUid(#name), \
(char *) name##_bits, name##_width, name##_height)
/*
* NAME: Tcl->AppInit()
* DESCRIPTION: initialize interpreter and execute main script
*/
int Tcl_AppInit(Tcl_Interp *interp)
{
if (Tcl_Init(interp) == TCL_ERROR ||
Tk_Init(interp) == TCL_ERROR ||
Hfs_Init(interp) == TCL_ERROR)
return TCL_ERROR;
/* initialize bitmaps */
if (DEFBITMAP(interp, macdaemon) == TCL_ERROR ||
DEFBITMAP(interp, macdaemon_mask) == TCL_ERROR ||
DEFBITMAP(interp, stop) == TCL_ERROR ||
DEFBITMAP(interp, caution) == TCL_ERROR ||
DEFBITMAP(interp, note) == TCL_ERROR ||
DEFBITMAP(interp, floppy) == TCL_ERROR ||
DEFBITMAP(interp, harddisk) == TCL_ERROR ||
DEFBITMAP(interp, cdrom) == TCL_ERROR ||
DEFBITMAP(interp, floppy_mask) == TCL_ERROR ||
DEFBITMAP(interp, harddisk_mask) == TCL_ERROR ||
DEFBITMAP(interp, cdrom_mask) == TCL_ERROR ||
DEFBITMAP(interp, sm_floppy) == TCL_ERROR ||
DEFBITMAP(interp, sm_harddisk) == TCL_ERROR ||
DEFBITMAP(interp, sm_cdrom) == TCL_ERROR ||
DEFBITMAP(interp, folder) == TCL_ERROR ||
DEFBITMAP(interp, document) == TCL_ERROR ||
DEFBITMAP(interp, application) == TCL_ERROR ||
DEFBITMAP(interp, folder_mask) == TCL_ERROR ||
DEFBITMAP(interp, document_mask) == TCL_ERROR ||
DEFBITMAP(interp, application_mask) == TCL_ERROR ||
DEFBITMAP(interp, sm_folder) == TCL_ERROR ||
DEFBITMAP(interp, sm_document) == TCL_ERROR ||
DEFBITMAP(interp, sm_application) == TCL_ERROR ||
DEFBITMAP(interp, help) == TCL_ERROR ||
DEFBITMAP(interp, padlock) == TCL_ERROR)
return TCL_ERROR;
/* execute main script */
Tcl_SetVar(interp, "argv0", argv0, TCL_GLOBAL_ONLY);
if (Tcl_Eval(interp, xhfs) == TCL_ERROR)
{
fprintf(stderr, "Error: %s\n", interp->result);
exit(1);
}
return TCL_OK;
}
/*
* NAME: main()
* DESCRIPTION: program entry
*/
int main(int argc, char *argv[])
{
int nargc;
char **nargv;
int i;
suid_init();
argv0 = argv[0];
nargc = argc + 2;
nargv = malloc(sizeof(*nargv) * nargc);
if (nargv == 0)
{
perror(argv[0]);
return 1;
}
nargv[0] = argv0;
nargv[1] = "/dev/null";
nargv[2] = "--";
for (i = 3; i < nargc; ++i)
nargv[i] = argv[i - 2];
Tk_Main(nargc, nargv, Tcl_AppInit);
return 0; /* not reached */
}

1029
hls.c Normal file

File diff suppressed because it is too large Load Diff

22
hls.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: hls.h,v 1.6 1998/04/11 08:26:58 rob Exp $
*/
int hls_main(int, char *[]);

74
hmkdir.c Normal file
View File

@ -0,0 +1,74 @@
/*
* hfsutils - tools 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: hmkdir.c,v 1.6 1998/04/11 08:26:58 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <stdlib.h>
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "hmkdir.h"
/*
* NAME: hmkdir->main()
* DESCRIPTION: implement hmkdir command
*/
int hmkdir_main(int argc, char *argv[])
{
hfsvol *vol;
char **fargv;
int fargc, i, result = 0;
if (argc < 2)
{
fprintf(stderr, "Usage: %s hfs-path [...]\n", argv0);
return 1;
}
vol = hfsutil_remount(hcwd_getvol(-1), HFS_MODE_ANY);
if (vol == 0)
return 1;
fargv = hfsutil_glob(vol, argc - 1, &argv[1], &fargc, &result);
if (result == 0)
{
for (i = 0; i < fargc; ++i)
{
if (hfs_mkdir(vol, fargv[i]) == -1)
{
hfsutil_perrorp(fargv[i]);
result = 1;
}
}
}
hfsutil_unmount(vol, &result);
if (fargv)
free(fargv);
return result;
}

22
hmkdir.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: hmkdir.h,v 1.6 1998/04/11 08:26:58 rob Exp $
*/
int hmkdir_main(int, char *[]);

112
hmount.c Normal file
View File

@ -0,0 +1,112 @@
/*
* hfsutils - tools 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: hmount.c,v 1.8 1998/04/11 08:26:59 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <stdlib.h>
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "suid.h"
# include "hmount.h"
/*
* NAME: hmount->main()
* DESCRIPTION: implement hmount command
*/
int hmount_main(int argc, char *argv[])
{
char *path = 0;
hfsvol *vol;
hfsvolent ent;
int nparts, partno, result = 0;
if (argc < 2 || argc > 3)
{
fprintf(stderr, "Usage: %s source-path [partition-no]\n", argv0);
goto fail;
}
path = hfsutil_abspath(argv[1]);
if (path == 0)
{
fprintf(stderr, "%s: not enough memory\n", argv0);
goto fail;
}
suid_enable();
nparts = hfs_nparts(path);
suid_disable();
if (nparts >= 0)
printf("%s: contains %d HFS partition%s\n", path, nparts,
nparts == 1 ? "" : "s");
if (argc == 3)
partno = atoi(argv[2]);
else
{
if (nparts > 1)
{
fprintf(stderr, "%s: must specify partition number\n", argv0);
goto fail;
}
else if (nparts == -1)
partno = 0;
else
partno = 1;
}
suid_enable();
vol = hfs_mount(path, partno, HFS_MODE_ANY);
suid_disable();
if (vol == 0)
{
hfsutil_perror(path);
goto fail;
}
hfs_vstat(vol, &ent);
hfsutil_pinfo(&ent);
if (hcwd_mounted(ent.name, ent.crdate, path, partno) == -1)
{
perror("Failed to record mount");
result = 1;
}
hfsutil_unmount(vol, &result);
free(path);
return result;
fail:
if (path)
free(path);
return 1;
}

22
hmount.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: hmount.h,v 1.7 1998/04/11 08:26:59 rob Exp $
*/
int hmount_main(int, char *[]);

61
hpwd.c Normal file
View File

@ -0,0 +1,61 @@
/*
* hfsutils - tools 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: hpwd.c,v 1.7 1998/04/11 08:26:59 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "hpwd.h"
/*
* NAME: hpwd->main()
* DESCRIPTION: implement hpwd command
*/
int hpwd_main(int argc, char *argv[])
{
mountent *ent;
if (argc != 1)
{
fprintf(stderr, "Usage: %s\n", argv0);
return 1;
}
ent = hcwd_getvol(-1);
if (ent == 0)
{
fprintf(stderr, "%s: No volume is current; use `hmount' or `hvol'\n",
argv0);
return 1;
}
if (strcmp(ent->cwd, ":") == 0)
printf("%s:\n", ent->vname);
else
printf("%s%s:\n", ent->vname, ent->cwd);
return 0;
}

22
hpwd.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: hpwd.h,v 1.7 1998/04/11 08:26:59 rob Exp $
*/
int hpwd_main(int, char *[]);

119
hrename.c Normal file
View File

@ -0,0 +1,119 @@
/*
* hfsutils - tools 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: hrename.c,v 1.7 1998/04/11 08:26:59 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <stdlib.h>
# include <errno.h>
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "hrename.h"
/*
* NAME: do_rename()
* DESCRIPTION: move/rename files
*/
static
int do_rename(hfsvol *vol, int argc, char *argv[], const char *dest)
{
hfsdirent ent;
int i, result = 0;
if (argc > 1 && (hfs_stat(vol, dest, &ent) == -1 ||
! (ent.flags & HFS_ISDIR)))
{
ERROR(ENOTDIR, 0);
hfsutil_perrorp(dest);
return 1;
}
for (i = 0; i < argc; ++i)
{
if (hfs_rename(vol, argv[i], dest) == -1)
{
hfsutil_perrorp(argv[i]);
result = 1;
}
}
return result;
}
/*
* NAME: hrename->main()
* DESCRIPTION: implement hrename command
*/
int hrename_main(int argc, char *argv[])
{
mountent *ment;
hfsvol *vol;
int fargc;
char **fargv;
int result = 0;
if (argc < 3)
{
fprintf(stderr, "Usage: %s hfs-src-path [...] hfs-target-path\n", argv0);
return 1;
}
vol = hfsutil_remount(ment = hcwd_getvol(-1), HFS_MODE_ANY);
if (vol == 0)
return 1;
fargv = hfsutil_glob(vol, argc - 2, &argv[1], &fargc, &result);
if (result == 0)
result = do_rename(vol, fargc, fargv, argv[argc - 1]);
if (result == 0)
{
char *path;
path = hfsutil_getcwd(vol);
if (path == 0)
{
hfsutil_perror("Can't get current HFS directory path");
result = 1;
}
else if (hcwd_setcwd(ment, path) == -1)
{
perror("Can't set current HFS directory");
result = 1;
}
if (path)
free(path);
}
hfsutil_unmount(vol, &result);
if (fargv)
free(fargv);
return result;
}

22
hrename.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: hrename.h,v 1.6 1998/04/11 08:26:59 rob Exp $
*/
int hrename_main(int, char *[]);

74
hrmdir.c Normal file
View File

@ -0,0 +1,74 @@
/*
* hfsutils - tools 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: hrmdir.c,v 1.6 1998/04/11 08:26:59 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <stdlib.h>
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "hrmdir.h"
/*
* NAME: hrmdir->main()
* DESCRIPTION: implement hrmdir command
*/
int hrmdir_main(int argc, char *argv[])
{
hfsvol *vol;
char **fargv;
int fargc, i, result = 0;
if (argc < 2)
{
fprintf(stderr, "Usage: %s hfs-path [...]\n", argv0);
return 1;
}
vol = hfsutil_remount(hcwd_getvol(-1), HFS_MODE_ANY);
if (vol == 0)
return 1;
fargv = hfsutil_glob(vol, argc - 1, &argv[1], &fargc, &result);
if (result == 0)
{
for (i = 0; i < fargc; ++i)
{
if (hfs_rmdir(vol, fargv[i]) == -1)
{
hfsutil_perrorp(fargv[i]);
result = 1;
}
}
}
hfsutil_unmount(vol, &result);
if (fargv)
free(fargv);
return result;
}

22
hrmdir.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: hrmdir.h,v 1.6 1998/04/11 08:26:59 rob Exp $
*/
int hrmdir_main(int, char *[]);

74
humount.c Normal file
View File

@ -0,0 +1,74 @@
/*
* hfsutils - tools 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: humount.c,v 1.6 1998/04/11 08:26:59 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <string.h>
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "humount.h"
/*
* NAME: humount->main()
* DESCRIPTION: implement humount command
*/
int humount_main(int argc, char *argv[])
{
int vnum;
mountent *ent;
if (argc > 2)
{
fprintf(stderr, "Usage: %s [volume-name-or-path]\n", argv0);
return 1;
}
if (argc == 1)
{
if (hcwd_umounted(-1) == -1 &&
hcwd_getvol(-1) == 0)
{
fprintf(stderr, "%s: No volume is current\n", argv0);
return 1;
}
return 0;
}
for (ent = hcwd_getvol(vnum = 0); ent; ent = hcwd_getvol(++vnum))
{
if (hfsutil_samepath(argv[1], ent->path) ||
strcasecmp(argv[1], ent->vname) == 0)
{
hcwd_umounted(vnum);
return 0;
}
}
fprintf(stderr, "%s: Unknown volume \"%s\"\n", argv0, argv[1]);
return 1;
}

22
humount.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: humount.h,v 1.6 1998/04/11 08:26:59 rob Exp $
*/
int humount_main(int, char *[]);

134
hvol.c Normal file
View File

@ -0,0 +1,134 @@
/*
* hfsutils - tools 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: hvol.c,v 1.7 1998/04/11 08:27:00 rob Exp $
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <string.h>
# include "hfs.h"
# include "hcwd.h"
# include "hfsutil.h"
# include "hvol.h"
/*
* NAME: showvol()
* DESCRIPTION: output information about a mounted volume
*/
static
int showvol(mountent *ment)
{
hfsvol *vol;
hfsvolent vent;
int result = 0;
printf("Current volume is mounted from");
if (ment->partno > 0)
printf(" partition %d of", ment->partno);
printf(":\n %s\n", ment->path);
vol = hfsutil_remount(ment, HFS_MODE_ANY);
if (vol == 0)
return 1;
printf("\n");
hfs_vstat(vol, &vent);
hfsutil_pinfo(&vent);
hfsutil_unmount(vol, &result);
return result;
}
/*
* NAME: hvol->main()
* DESCRIPTION: implement hvol command
*/
int hvol_main(int argc, char *argv[])
{
int vnum;
mountent *ment;
if (argc > 2)
{
fprintf(stderr, "Usage: %s [volume-name-or-path]\n", argv0);
return 1;
}
if (argc == 1)
{
int output = 0, header = 0;
ment = hcwd_getvol(-1);
if (ment)
{
showvol(ment);
output = 1;
}
for (vnum = 0; ; ++vnum)
{
mountent *ent;
ent = hcwd_getvol(vnum);
if (ent == 0)
break;
if (ent == ment)
continue;
if (header == 0)
{
printf("%s volumes:\n", ment ? "\nOther known" : "Known");
header = 1;
}
if (ent->partno <= 0)
printf(" %-35s \"%s\"\n", ent->path, ent->vname);
else
printf(" %-35s %2d \"%s\"\n", ent->path, ent->partno,
ent->vname);
output = 1;
}
if (output == 0)
printf("No known volumes; use `hmount' to introduce new volumes\n");
return 0;
}
for (ment = hcwd_getvol(vnum = 0); ment; ment = hcwd_getvol(++vnum))
{
if (hfsutil_samepath(argv[1], ment->path) ||
strcasecmp(argv[1], ment->vname) == 0)
{
hcwd_setvol(vnum);
return showvol(ment);
}
}
fprintf(stderr, "%s: Unknown volume \"%s\"\n", argv0, argv[1]);
return 1;
}

22
hvol.h Normal file
View File

@ -0,0 +1,22 @@
/*
* hfsutils - tools 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: hvol.h,v 1.7 1998/04/11 08:27:00 rob Exp $
*/
int hvol_main(int, char *[]);

54
images.h Normal file
View File

@ -0,0 +1,54 @@
/*
* hfsutils - tools 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: images.h,v 1.6 1998/04/11 08:27:00 rob Exp $
*/
# include "images/macdaemon.xbm"
# include "images/macdaemon_mask.xbm"
# include "images/stop.xbm"
# include "images/caution.xbm"
# include "images/note.xbm"
# include "images/floppy.xbm"
# include "images/harddisk.xbm"
# include "images/cdrom.xbm"
# include "images/floppy_mask.xbm"
# include "images/harddisk_mask.xbm"
# include "images/cdrom_mask.xbm"
# include "images/sm_floppy.xbm"
# include "images/sm_harddisk.xbm"
# include "images/sm_cdrom.xbm"
# include "images/folder.xbm"
# include "images/document.xbm"
# include "images/application.xbm"
# include "images/folder_mask.xbm"
# include "images/document_mask.xbm"
# include "images/application_mask.xbm"
# include "images/sm_folder.xbm"
# include "images/sm_document.xbm"
# include "images/sm_application.xbm"
# include "images/help.xbm"
# include "images/padlock.xbm"

14
images/application.xbm Normal file
View File

@ -0,0 +1,14 @@
#define application_width 32
#define application_height 32
static unsigned char application_bits[] = {
0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x20, 0x02, 0x00,
0x00, 0x10, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x10, 0x00,
0x00, 0x02, 0x20, 0x00, 0x00, 0x01, 0x40, 0x00, 0x80, 0x00, 0x80, 0x00,
0x40, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x04,
0x08, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x10, 0x02, 0x00, 0xfc, 0x20,
0x01, 0x00, 0x02, 0x41, 0x02, 0x00, 0x01, 0x82, 0x04, 0x80, 0x0c, 0x44,
0x08, 0x80, 0x13, 0x28, 0x10, 0x70, 0xfe, 0xf1, 0x20, 0x40, 0x0c, 0xe0,
0x40, 0x80, 0x00, 0xe0, 0x80, 0x00, 0x01, 0xe0, 0x00, 0x01, 0x06, 0xe0,
0x00, 0x02, 0xf8, 0xe7, 0x00, 0x04, 0x40, 0xf8, 0x00, 0x08, 0x20, 0xe0,
0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x40, 0x04, 0x00,
0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00};

Some files were not shown because too many files have changed in this diff Show More