Professional Documents
Culture Documents
File Xray
File Xray
FILEXRAY PLUS
1
© 2010 iohead LLC. All Rights Reserved.
The content of this document is furnished for information use only, is subject to change without no-
tice, and should not be construed as a commitment by iohead LLC. iohead LLC assumes no responsi-
bility or liability for any errors or inaccuracies that may appear in the information contained in this
document.
Apple, the Apple logo, Mac, and Mac OS are trademarks of Apple Inc., registered in the U.S. and other
countries. Other product names mentioned herein may be trademarks of Apple Inc. or of other compa-
nies.
2
End User License Agreement for the fileXray Software
PLEASE READ THIS SOFTWARE END USER LICENSE AGREEMENT (“LICENSE”) CAREFULLY BEFORE PURCHASING OR USING THE
fileXray SOFTWARE (DEFINED BELOW). BY USING THE fileXray SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF
THIS LICENSE. IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENSE, DO NOT USE THE fileXray SOFTWARE.
IMPORTANT NOTE: This software may be used to reproduce, modify, publish and distribute materials. It is licensed to you
only for reproduction, modification, publication and distribution of non-copyrighted materials, materials in which you own
the copyright, or materials you are authorized or legally permitted to reproduce, modify, publish and distribute. If you are
uncertain about your right to copy, modify, publish and distribute any material you should contact your legal advisor.
1. General. The software, including any and all of its versions and variations, tools, utilities, sample or example code, docu-
mentation, and other materials accompanying this License, whether on disk, print or electronic documentation, in read only
memory, or any other media (collectively, the “fileXray Software”) are licensed, not sold, to you by iohead LLC (“iohead”)
and/or iohead’s licensors. The rights granted herein are limited to iohead’s and/or iohead’s licensors’ respective intellec-
tual property rights in the fileXray Software and do not include any other patents or intellectual property rights. You own
the media on which the fileXray Software is recorded but iohead and/or iohead’s licensors retain ownership of their respec-
tive portions of the fileXray Software itself. The terms of this License will govern any software upgrades provided by iohead
that replace and/or supplement the original fileXray Software, unless such upgrade is accompanied by a separate license in
which case the terms of that license will govern.
2. License Types. The fileXray Software is made available to you under the terms of one of two license types depending on
which license type you purchased: the Professional-Use License or the Personal-Use License.
A. fileXray Software with the Professional-Use License. If you purchased the Professional-Use License and if you use the
fileXray Software, you are subject to all the terms of this License except the terms in Section 3.B. The Professional-Use
License is a single-user single-installation license. It is valid for a single user using the fileXray Software on a single physi-
cal computer. It permits the use of the fileXray Software by businesses and organizations as long as the single-user single-
installation terms are adhered to. You may use the fileXray Software only in compliance with the permitted use as defined
in this Section 3.A.
B. fileXray Software with the Personal-Use License. If you purchased the Personal-Use License and if you use the fileXray
Software, you are subject to all the terms of this License except the terms in Section 3.A. The Personal-Use License is a
single-user multiple-installation license for individuals. It permits the fileXray Software to be used by a single user on any
number of that user’s personal machines in the same household. It does not permit use by businesses or organizations.
You may use the fileXray Software only in compliance with the permitted use as defined in this Section 3.B.
C. Other Restrictions. Except as and only to the extent expressly permitted by this License or to the extent that the fol-
lowing restrictions are prohibited by applicable law, you may not copy, decompile, reverse engineer, disassemble, attempt
to derive the source code of the fileXray Software, modify, decrypt, create derivative works of, incorporate into or compile
in combination with your own programs, sublicense or otherwise redistribute the fileXray Software.
4. Transfer. You may not rent, lease, lend, redistribute or sublicense the fileXray Software. NFR (Not for Resale) and Evalua-
tion Copies: Notwithstanding other sections of this License, fileXray Software labeled as Not for Resale or Evaluation by
iohead, or otherwise provided to you by iohead on a promotional basis may only be used for demonstration, testing and
evaluation purposes and may not be resold or transferred.
5. Termination. This License is effective until terminated. Your rights under this License will terminate automatically without
notice from iohead if you fail to comply with any term(s) of this License. In some cases, the specific license you receive may
have an expiration date. If so, your rights under this License will terminate automatically on the expiration date without
notice from iohead.
6. Disclaimer of Warranties. YOU EXPRESSLY ACKNOWLEDGE AND AGREE THAT USE OF THE fileXray SOFTWARE IS AT YOUR
SOLE RISK AND THAT THE ENTIRE RISK AS TO SATISFACTORY QUALITY, PERFORMANCE, ACCURACY AND EFFORT IS WITH
YOU. THE fileXray SOFTWARE IS PROVIDED “AS IS,” WITH ALL FAULTS AND WITHOUT WARRANTY OF ANY KIND, AND IOHEAD
LLC AND IOHEAD LLC’S LICENSORS (COLLECTIVELY REFERRED TO AS “IOHEAD” FOR THE PURPOSES OF SECTIONS 6 AND 7)
HEREBY DISCLAIM ALL WARRANTIES AND CONDITIONS WITH RESPECT TO THE fileXray SOFTWARE, EITHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY,
OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NON-
INFRINGEMENT OF THIRD PARTY RIGHTS. IOHEAD DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF
THE fileXray SOFTWARE, THAT THE FUNCTIONS CONTAINED IN THE fileXray SOFTWARE WILL MEET YOUR REQUIREMENTS,
THAT THE OPERATION OF THE fileXray SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT DEFECTS IN THE
fileXray SOFTWARE WILL BE CORRECTED. YOU FURTHER ACKNOWLEDGE THAT THE fileXray SOFTWARE IS NOT INTENDED OR
SUITABLE FOR USE IN SITUATIONS OR ENVIRONMENTS WHERE THE FAILURE OF, OR ERRORS OR INACCURACIES IN THE CON-
TENT, DATA OR INFORMATION PROVIDED BY, THE fileXray SOFTWARE COULD LEAD TO DEATH, PERSONAL INJURY, OR SE-
VERE PHYSICAL OR ENVIRONMENTAL DAMAGE, INCLUDING WITHOUT LIMITATION THE OPERATION OF NUCLEAR FACILITIES,
AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, LIFE SUPPORT OR WEAPONS SYSTEMS. NO
ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY IOHEAD OR AN IOHEAD AUTHORIZED REPRESENTATIVE SHALL CRE-
3
ATE A WARRANTY. SHOULD THE fileXray SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE ENTIRE COST OF ALL NECESSARY
SERVICING, REPAIR OR CORRECTION.
7. Limitation of Liability. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT SHALL IOHEAD BE LIABLE FOR PERSONAL
INJURY, OR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER, INCLUDING, WITHOUT LIMI-
TATION, DAMAGES FOR LOSS OF PROFITS, CORRUPTION OR LOSS OF DATA, BUSINESS INTERRUPTION OR ANY OTHER COM-
MERCIAL DAMAGES OR LOSSES, ARISING OUT OF OR RELATED TO YOUR USE OR INABILITY TO USE THE fileXray SOFTWARE,
HOWEVER CAUSED, REGARDLESS OF THE THEORY OF LIABILITY (CONTRACT, TORT OR OTHERWISE) AND EVEN IF IOHEAD
HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
8. Export Control. You may not use or otherwise export or reexport the fileXray Software except as authorized by United
States law and the laws of the jurisdiction(s) in which the fileXray Software was obtained. In particular, but without limita-
tion, the fileXray Software may not be exported or re-exported (a) into any U.S. embargoed countries or (b) to anyone on
the U.S. Treasury Department’s list of Specially Designated Nationals or the U.S. Department of Commerce Denied Person’s
List or Entity List. By using the fileXray Software, you represent and warrant that you are not located in any such country or
on any such list. You also agree that you will not use the fileXray Software for any purposes prohibited by United States law,
including, without limitation, the development, design, manufacture or production of nuclear, chemical or biological weap-
ons.
9. Third Party Acknowledgements. Portions of the fileXray Software may utilize the following copyrighted material, the use
of which is hereby acknowledged.
Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is
hereby granted, provided that the above copyright notice appears in all copies and that both the copyright notice and this
permission notice appear in supporting documentation.
APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY
SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
OR PROFITS, WHETHER IN ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
This code is derived from software contributed to The NetBSD Foundation by Jason R. Thorpe of the Numerical Aerospace
Simulation Facility, NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following dis-
claimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following dis-
claimer in the documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This
product includes software developed by the NetBSD Foundation, Inc. and its contributors.
4. Neither the name of The NetBSD Foundation nor the names of its contributors may be used to endorse or promote prod-
ucts derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IM-
PLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOW-
EVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLI-
GENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following dis-
claimer.
4
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following dis-
claimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IM-
PLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOW-
EVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLI-
GENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following dis-
claimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following dis-
claimer in the documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software must display the following acknowledgment: “This
product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)”
4. The names “OpenSSL Toolkit” and “OpenSSL Project” must not be used to endorse or promote products derived from this
software without prior written permission. For written permission, please contact openssl-core@openssl.org.
5. Products derived from this software may not be called “OpenSSL” nor may “OpenSSL” appear in their names without prior
written permission of the OpenSSL Project.
6. Redistributions of any form whatsoever must retain the following acknowledgment: “This product includes software de-
veloped by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)”
THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT “AS IS” AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHER-
WISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSE-
QUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CON-
TRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10. Additional Bundled Software. The fileXray Software includes a copy of the NuFS Software, which is also an iohead prod-
uct. By using the fileXray Software, you are also agreeing to be bound by the terms of NuFS Software End User License
Agreement.
11. Online Version of this License. An online version of this License is available at: http://iohead.com/legal/fileXray/ An
online version of the NuFS Software End User License agreement is available at: http://iohead.com/legal/NuFS/
If you agree to the terms of this license, you may use the above version number to run the fileXray Software installer in
non-interactive mode.
5
This page intentionally left blank.
6
User Guide 11
0. Minimum System Requirements 13
1. Installing and Getting Started 14
2. Introduction to fileXray 18
3. Basic Usage 22
4. Analyzing Volume Structure 26
5. Analyzing File System Objects 28
6. Analyzing Volume Usage 29
7. Monitoring File System Changes 30
8. Retrieving Volume Content 31
9. Altering Volume Behavior 32
10. Extending fileXray: Developing and Using Filters 33
11. Advanced Forensics and Content Recovery 34
12. References 35
Reference 37
-‐-‐allocation
39
-‐-‐badblock
41
-‐-‐block
BLOCK
42
-‐-‐btree
BTREE_NAME
44
-‐-‐checksum
COMPONENTS
48
-‐-‐cnid
CNID
50
-‐-‐device
DEVICE
52
-‐-‐disallow_mounting
SECONDS
56
-‐-‐diskusage
59
-‐-‐enable_xattr_extents
61
-‐-‐exhaustive
63
-‐-‐filter
FILTER
65
bmactime 66
compressed 68
creatorcode 68
device 69
7
dirhardlink 69
empty 69
emptyforks 69
fifo 70
hardlink 70
immutable 70
lsR 71
macho 71
name 72
namei 72
nameprefix 72
nameprefixi 72
namesuffix 73
namesuffixi 73
nodename 73
null 74
socket 74
subname 74
subnamei 74
sxid 74
symlink 75
typecode 75
xattrname 76
xattr 76
Implementing Your Own Filters 77
-‐-‐filter_args
STRING
81
-‐-‐force
82
-‐-‐fragmentation
FORK_TYPE
83
-‐-‐freespace
85
-‐-‐fsspec
PARENT_CNID:NAME
86
-‐-‐hotfiles
88
-‐-‐iec
89
introspect
90
Introspecting Files 91
Introspecting Folders 93
8
Introspecting File Hard Links 94
Introspecting Directory Hard Links 98
Introspecting Symbolic Links 102
-‐-‐journal
104
-‐-‐journal_names
107
-‐-‐list
110
-‐-‐list_records
RECORD_TYPE
112
-‐-‐monitor
114
-‐-‐monitor_exclude
VOLUME
116
-‐-‐monitor_include
VOLUME
117
-‐-‐monitor_logfile
LOGFILE
118
-‐-‐mount_data
119
-‐-‐next_allocation
BLOCK
123
-‐-‐node
NODE
126
-‐-‐noidmap
127
-‐-‐output
OUTPUT_FILE
129
-‐-‐partition
START[,SIZE]
130
-‐-‐path
PATH
131
Dot-Dot 131
Link Resolution 132
Terminal Slash 132
Long Node Names and Name Mangling 132
9
-‐-‐userfs_type
USERFS_TYPE
157
Arbitrary File System 157
Free Space File System 160
Structure File System 161
Used Space File System 162
Scavenger File System 163
-‐-‐version
167
-‐-‐volume
VOLUME_PATH
168
-‐-‐volume_header
169
-‐-‐who_owns_byte
BYTE
172
-‐-‐who_owns_block
BLOCK
173
10
User Guide
11
This page intentionally left blank.
12
0. Minimum System Requirements
• Mac OS X 10.5 Leopard
13
1. Installing and Getting Started
The fileXray Software (fileXray) ships as a single Universal Binary called
fileXray-installer (the installer). Both fileXray and the installer are
command-line programs. When you purchased fileXray, you would have re-
ceived a personalized URL to download the installer. Please save this URL as
you can use it to download or re-download the latest version of fileXray that
your license is eligible for. The latest version number string of fileXray and
the SHA-1 checksum of the fileXray-installer binary can be retrieved
from:
http://iohead.com/fileXray/latest.txt
During fileXray installation, the installer copies the fileXray program ex-
ecutable to a folder you specify and populates the /Library/Application
Support/fileXray/ folder. fileXray installation creates no other files or fold-
ers. fileXray also does not create any preference or configuration files at in-
stallation time or at any other time.
• The path to the license data file. This is the ASCII file you would have re-
ceived as an attachment to the email containing the installer download
URL. You can either save the attachment, or save the cut-and-pasted
ASCII content (license blob) to a file.
• The email address associated with the license. This is the email address
you used to purchase fileXray.
• Confirmation that you have read and accepted the fileXray End User
License Agreement (EULA).
• The path to a folder in which to copy the fileXray executable. You will
need superuser privileges to install fileXray. Therefore, run the installer
using the sudo command. By default, if an fileXray executable already
exists in the specified folder, it will not be overwritten. See Section 1.3 on
how to explicitly instruct the installer to overwrite any existing fileXray
executable.
14
$ chmod +x ./fileXray-installer
$ sudo ./fileXray-installer
Please type the path to the license file : /tmp/fileXray-license.txt
You must read and accept the End User License Agreement (EULA) to continue.
The EULA is available at http://filexray.com/eula.txt
Have you read the EULA and do you accept it? (yes/no) yes
$ fileXray --version
fileXray plus 1.0.0
Copyright (c) 2010 iohead LLC. All Rights Reserved.
The installation described in Section 1.1 is interactive in that you are required
to provide certain information to the installer by typing responses to prompts
displayed on the screen. The same information can be provided to the installer
as command-line arguments. This allows for non-interactive installation or up-
grade of the fileXray software, say, by a script in a managed environment.
You can use the --help option of the installer to display the options that the
installer accepts.
15
$ fileXray-installer --help
fileXray-installer 1.0.0
Copyright (c) 2010 iohead LLC. All Rights Reserved.
This is the fileXray installer. Usage:
fileXray-installer [ARGUMENTS]
The --accept option is used to specify to the installer that the installing
authority1 has read and accepted the End User License Agreement (EULA). The
argument to --accept is the version number of the EULA, which can be found
at the end of the EULA document. The most recent version of the EULA will
apply to the latest version of fileXray.
Note that for a fully non-interactive installation, all required arguments must
be specified, otherwise the installer will prompt for the missing information,
rendering the installation interactive.
For a first installation, the required arguments are --accept, --email, --li-
cense, and --installfolder.
1 The installing authority is a user or system administrator who has the legal authority to ac-
cept the fileXray EULA and subsequently install fileXray (either interactively or non-
interactively, say, through a script) in conformance with a valid instance of the fileXray li-
cense.
16
1.4 Uninstalling
fileXray installation creates the following on-disk entities:
• The fileXray executable, which is created in a preexisting user-
specified folder
• The /Library/Application Support/fileXray/ folder and its
contents
• Size and population of the volume on which the operation is being per-
formed.
• Speed of the disk drive or other storage medium on which the volume re-
sides along with the speed of the connecting bus.
• Amount of RAM available on the system.
• Processor speed.
17
2. Introduction to fileXray
Files, and consequently file systems, underlie most of the interactions users
have with the operating system. The HFS+ file system in Mac OS X supports a
rich and interesting set of features. It is eminently useful and rewarding to
learn what these features are, how they work, and how you can use them to
your advantage. Understanding advanced file system techniques will help you
in gaining a fine-grained control of a system, whether it be for administration,
analysis, debugging, investigation1, optimization, or just plain fun.
2.1 HFS+
HFS+, also referred to as “HFS Plus” or the “Mac OS X Extended” volume for-
mat, is the default and the only practically viable volume format for Mac OS X
installations. Historically, it was possible to install Mac OS X on a UFS volume,
albeit at the cost of compatibility issues. However, since Mac OS X 10.5 (Leop-
ard), HFS+ is the only volume format that a Mac OS X installation can reside
on. Moreover, almost all2 of Apple’s devices that use file system storage use
HFS+. In other words, HFS+ is ubiquitous when dealing with Apple’s comput-
ers and devices.
HFS+ was introduced with Mac OS 8.1 in early 1998. It has evolved greatly
since its inception. Especially with the advent and subsequent evolution of Mac
OS X, a large number of features have been retrofitted into HFS+. Conse-
quently, the HFS+ implementation in Mac OS X has grown large 3 and complex
over the years.
1A major portion of digital forensics boils down to analyzing and dissecting a file system vol-
ume.
2 iPods meant for use with Windows and certain iPod models in general use the FAT32 volume
format.
3The HFS+ implementation in Mac OS X 10.6 (Snow Leopard) is nearly 60,000 lines of kernel
code.
18
tion that’s accessing files residing on that volume. The following illustration
shows a high-level overview.
!"#$
B7*7)
G-06'#/)&9'# G-06'#()&)F#$ G-06'#H$)44#$
G-!IC
B)$D7&
B)$D7&+06'#+()&)F#$
=->+06'#+?@2"+AB+C6D$)$<E
!"#$
%#$&#'
8&79#:;0-+')<#$
()*+,-+.+/0-1
/0-1
234'#3#&5)567&
;7'J3#
19
2.2 fileXray
At a very high level, fileXray’s functionality can be classified under the fol-
lowing two categories.
Examples of features in the second category include monitoring live file system
activity, listing directory contents, and rapidly searching for file system objects
by name, type, or other attributes.
A key architectural aspect of fileXray is that it does not rely on the operating
system’s HFS+ implementation—it directly accesses an HFS+ volume and proc-
esses all of the volume’s contents itself. The following is a conceptual view.
=4"/-; @@@
789:
A$-3#""2&6+B-,4'#"
>;?'#;#&/)/2-&
!"#$%&'(
()*+$#),"+-.+/0#+,#123#+-$+.2'#+4&,#$'52&6+/0#+789:+1-'4;#
!"#$
%#$&#'
789:
<-'4;#
20
That is, fileXray essentially contains a custom implementation of the HFS+
file system. It reads from the raw storage underlying an HFS+ volume and
processes all HFS+ data structures itself. This has several implications, for ex-
ample:
The remainder of this User Guide briefly outlines fileXray features. A detailed
discussion of the features along with usage examples follows in the fileXray
Reference.
21
3. Basic Usage
Most fileXray operations are performed on an HFS+ volume, which can be
either online (mounted) or offline 1 (unmounted). A few operations, however, are
meant only for mounted volumes. There also are operations that are not HFS+
specific and do not require an HFS+ volume.
1 fileXray accesses the raw storage underlying an HFS+ volume and itself interprets the file
system structure and contents, without relying on the operating system’s HFS+ implementa-
tion. This is what allows fileXray to handle offline volumes.
22
$ fileXray --volume "/Volumes/Macintosh HD" [other options…]
…
If you use the --device option to specify a device or a file containing a device
image, fileXray will automatically use a volume if one of the following is true:
fileXray can detect and parse GUID Partition Table (GPT), Apple Partition
Map (APM), and Master Boot Record (MBR) partitioning schemes. If the speci-
fied --device argument is such that multiple HFS+ partitions are detected,
fileXray will list all partitions that it found and will prompt you to choose one
through the --partition option. For example:
However, a GUID Partition Table was detected on the given image file with the
following 2 HFS+ partition table entries:
23
3.2 Specifying Folders1 and Files
Numerous types of file system objects can exist on an HFS+ volume: folders,
regular files, hard links, directory hard links, symbolic links, device files,
named pipes, Unix Domain socket files, and so on. From an implementation
detail standpoint, however, HFS+ has only two types of fundamental objects in
the file system hierarchy: folders and files. All user-visible objects are imple-
mented using these two types under the hood. Several fileXray operations are
targeted for folders and files. You can specify a file system object to fileXray
in several ways:
• Explicitly by specifying the object’s parent’s CNID along with the object’s
name through the --fsspec option. For example:
2The CNID is a 32-bit unsigned integer assigned to each file and folder on an HFS+ volume.
Except in the case of file and directory hard links, an object’s CNID is its inode number as ex-
ported by the BSD layer.
24
3.3 Switching Information Display or Processing Modes
Certain fileXray options can be used to change the behavior of other options.
For example:
As noted earlier, certain fileXray features are not specific to HFS+. These fea-
tures include:
25
4. Analyzing Volume Structure
fileXray provides the means to perform a complete analysis of an HFS+ vol-
ume’s internal data structures.
The --volume_header option displays the Volume Header, the Alternate Vol-
ume Header, and if applicable, the HFS Master Directory Block. Besides dis-
playing the contents of these data structures, --volume_header annotates the
output with additional information computed dynamically. The output of
--volume_header can be thought of as a high-level summary of the volume’s
structure.
For each mounted HFS+ volume, the Mac OS X kernel maintains various run-
time data structures in memory. The contents of several of these data struc-
tures are useful in debugging and analysis. The --mount_data option retrieves
this information from kernel memory and displays it.
HFS+ employs several B-Trees in its implementation: the Catalog B-Tree, the
Extents Overflow B-Tree, the Attributes B-Tree, and the Hot File Clustering B-
Tree. The --btree option can be used to introspect each of these B-Trees. In
conjunction with the --node and --list_records options, --btree can also
be used to analyze individual nodes and records in a given B-Tree. These op-
tions can just as well be used to dump the contents of an entire B-Tree.
The --journal option displays the state and structure of the journal on a
journaled2 HFS+ volume. In conjunction with the --exhaustive option,
--journal analyzes each transaction found in the journal and also determines
the ownership of each block recorded within a transaction. fileXray supports
both internal (locally resident) and external3 (resident on another device) jour-
nals.
1Space on an HFS+ volume is allocated to files in units called allocation blocks. The size of an
allocation block for a given volume is fixed at volume creation time.
2 Metadata journaling is enabled by default on modern-day HFS+ volumes.
3By default, HFS+ uses an internal journal on Mac OS X client and typical server installations.
The Mac OS X diskutil command can be used to move a volume’s journal to an external de-
vice.
26
fileXray also includes built-in synthetic file systems to export certain types of
volume information as a “file system,” allowing arbitrary programs to conven-
iently access and operate on that information.
For example, the Structure File System essentially turns an HFS+ volume “in-
side out”: given an HFS+ volume, it “mounts” the volume such that the resul-
tant file system exposes key HFS+ data structures as files that can be normally
read. For example, the Catalog-B Tree and the journal show up as files that
you can analyze with tools such as hex editors, strings, and grep.
As another example, the Free Space File System makes a volume’s free extents
visible as files that can be examined with standard tools. The Used Space File
System does a similar thing for a volume’s used extents.
27
5. Analyzing File System Objects
When targeted at a file system object, say, a folder, regular file, hard link, di-
rectory hard link, etc., fileXray displays all the metadata associated with that
object along with various types of implementation details and dynamically
computed auxiliary information. For example, if a file or directory hard link is
examined, fileXray will enumerate 1 all sibling file or directory hard links.
Object introspection also lists and shows the details of each extended attrib-
ute 2, if any, associated with the object. If an extended attribute happens to be
the one that’s used to implement Access Control Lists (ACLs) on Mac OS X,
fileXray will process the ACL and display the results. Similarly, if an ex-
tended attribute is the one that’s used to implement transparently compressed3
files, fileXray will process that attribute and display details of the compres-
sion scheme as applied to that object.
1This feature is applicable to hard links and directory hard links that were created on Mac OS
X 10.5 (Leopard) or newer.
28
6. Analyzing Volume Usage
fileXray provides several ways to quantify and qualify volume usage.
The --freespace and --usedspace options display lists of free and used ex-
tents, respectively. The lists can be readily sorted to determine the largest and
smallest free and used space chunks on a volume. In particular, the list dis-
played by --freespace represents how discontiguous (fragmented) the avail-
able space on a volume is. fileXray can also expose a volume’s free and used
spaces as synthetic file systems courtesy of the Free Space File System and the
Used Space File System, respectively. In particular, the Free Space File Sys-
tem’s contents are virtual files each representing a contiguous chunk of free
space on the volume. This allows for convenient analysis and searching of a
volume’s free blocks using programs of your choosing.
The --hotfiles option can be used to list the “hottest” files on a volume, as
tracked and determined by the Hot File Clustering scheme that’s built into the
Mac OS X HFS+ implementation. Hot files are tracked in a B-Tree, which can
be introspected through options such as --btree, --node, and --list_re-
cords.
The --diskusage option can be used to compute a given file system object’s
on-disk usage, which includes not only the data and resource forks (for files),
but also the cumulative disk space used by the names and values of any ex-
tended attributes the object might have.
29
7. Monitoring File System Changes
fileXray includes a built-in file system activity monitor that uses Mac OS X’s
fsevents 1 file system event notification mechanism. The monitor is not limited
to HFS+ volumes: it can be used to monitor modifications to any type of vol-
ume. It can be invoked through the --monitor option. While the monitor is
running, it displays file system event notifications effectively in real time as
they arrive from the kernel. A typical use of such functionality is to track which
file system objects are being added, removed, or modified by some activity such
as the launch of a program or during the installation of some software.
Moreover, the monitor’s output can be logged to a file specified by the --moni-
tor_logfile option in such a way that the writes to the log do not generate
their own log messages.
30
8. Retrieving Volume Content
fileXray provides several ways to read content—both metadata and da-
ta—from an HFS+ volume.
The --block option can be used to retrieve individual allocation blocks from a
volume.
The --read option allows retrieving the contents of data forks, resource forks,
and extended attributes. If a file is transparently compressed, it can have com-
pressed content in either its resource fork or an extended attribute. fileXray
can be optionally told through the --uncompress option to uncompress such
content in flight.
Moreover, all of fileXray’s built-in file systems provide seamless ways of re-
trieving various types of volume content.
31
9. Altering Volume Behavior
As a matter of policy, fileXray always opens a volume it is targeted at in read-
only mode. Therefore, fileXray is incapable of directly1 modifying a volume.
There are some fileXray options that can alter the state of a mounted volume,
or intentionally prevent any volume from being mounted at all.
1 You can, however, tell fileXray to save retrieved volume content and save it to a file specified
by the --output option. In this case, technically (if one must split hairs) fileXray is modifying
some volume, perhaps even the volume it is being targeted at if the argument to --output re-
sides on that volume.
32
10. Extending fileXray: Developing and Using Fil-
ters
fileXray can be extended by third parties through the filter mechanism that’s
built into it. (See Implementing Your Own Filters for details.) A filter is a module
that receives callbacks from fileXray as it walks the file system hierarchy on
an HFS+ volume. Each callback invocation provides a filter a chance to exam-
ine the details of a single file system object. The filter is free to apply any crite-
ria to “match” or “reject” the passed object. Typically, a filter would print some
information about objects it matches.
fileXray comes with a large number—over two dozen—of built-in filters. Most
filters search for file system objects with some given properties, say, objects
that are hard links or objects that have the setuid or setgid bits set. There also
exist name-matching filters that look for exact, prefix, suffix, or substring name
matches either case-sensitively or case-sensitively depending on the specific
filter in question. Some filters do rather complex tasks: for example, the macho
filter looks for Mach-O files and computes per-architecture object file sizes. The
--filter section of the Reference describes each built-in filter.
One aspect of built-in fileXray filters is that they are considerably faster than
their usual high-level counterparts. Consider the sxid filter, which searches for
setuid and setgid file system objects on a volume.
The sxid filter took less than 15 seconds to scan the entire volume, which in
this example is rather heavily populated at about 1.5 million files and folders.
One can perform a similar search using the standard find command on the
same volume as shown below.
$ time sudo find / -xdev -type f \( -perm -4000 -o -perm -2000 \) > /dev/null
4.09s user 63.42s system 23% cpu 4:46.04 total
Note that we told find to examine only files and limit itself to the root volume.
find took about 286 seconds.1 We see that the sxid filter is nearly 20x faster
than find.
By default, a filter scans the entire given HFS+ volume. Optionally, it can be
told to limit itself to a given folder and its subfolders.
1The absolute time taken would depend on multiple factors including the underlying hard-
ware. However, we are only interested in relative times here.
33
11. Advanced Forensics and Content Recovery
fileXray has an extensive feature set geared for file system forensics.
The --journal_names option dissects the volume’s journal and harvests file
system object names. When displaying the harvested names, it annotates the
output with the type of file system activity that’s likely to have occurred involv-
ing each name—for example, if an object with that name was deleted, moved,
renamed, and so on. When run with the --exhaustive option, --jour-
nal_names “diffs” the journal and volume copies of the blocks recorded in the
journal and indicates which parts of the metadata, if any, have changed.
The --trawl option scans the volume looking for blocks that match “magic”
patterns (signatures). This option uses the same “magic” mechanism that un-
derlies the file command. The set of signatures is arbitrarily extensible by the
user.
The --scavenge options scans the volume looking for deleted files and folders.
The result of the scavenge operation is a list of potentially recoverable files. It
shows you a list of such files along with their metadata details, including which
of the deleted blocks are likely to have been overwritten. It also allows you to
“undelete” such scavenged files. The Scavenger File System provides a synthetic
file system view of the results of scavenging a volume.
The Free Space File System provides a convenient way to identify and search
through the free extents of a volume. The analog for used extents is the Used
Space File System.
The Arbitrary File System provides a novel way of accessing arbitrary byte
ranges on a given storage device.
fileXray filters can be used to search a volume for objects with specific at-
tributes. In particular, the bmactime family of filters can be used to search for
objects one or more of whose timestamps fall within a given range. The results
of the bmactime filter can provide a “timeline” view of past file system activity.
The --checksum option can be used to compute hashes of one or more on-disk
components of file system objects.
34
12. References
This User Guide has briefly outlined fileXray features. Detailed discussion of
each feature, descriptions of the various ways in which the features can be
used, and usage examples are deferred to the fileXray Reference, which is
contained in the latter part of this document.
• Technical Note TN1150: HFS Plus Volume Format, which describes 1 the
on-disk format for an HFS Plus Volume and is available at:
http://developer.apple.com/mac/library/technotes/tn/tn1150.html
http://www.amazon.com/gp/product/0321278542/
1At the time of this writing, TN1150 is not up-to-date with newer features such as directory
hard links and HFS-compressed files.
35
This page intentionally left blank.
36
Reference
37
This page intentionally left blank.
38
-a --allocation
--allocation
By default, fileXray will print a series of lines, each of which begins with an
allocation block number in hexadecimal. The remainder of the line consists of a
series of byte values in hexadecimal. Each bit in a byte represents the state of a
single allocation block: a used block is represented by a bit whose value is 1
and a free allocation block is represented by a bit whose value is 0. The alloca-
tion block number at the beginning of the line is the first one represented by
the bytes on that line. The following is an example.
Allocation Blocks
6144 through 6151
In the above example, allocation blocks 0 through 255, which are represented
by the first two lines of fileXray output, are marked as used in the Allocation
File. This is represented by all bits being 1 in the 32 bytes representing the
blocks. Allocation blocks 6144 through 6150 are in use, but block 6151 is free,
as represented by the 0xfe byte value on the line that begins with block 6144
(0x1800). Blocks 6152 onwards are free, as represented by the 0x00 byte val-
ues.
To view a more detailed and visual representation of the Allocation File, you
can additionally specify the --exhaustive option, which, for each allocation
block on the volume, shows one of the following characters.
# Block is reserved or used by the Volume Header or the Alternate Volume Header.
_ Block is unused.
39
--allocation
The following is an example of the exhaustive view of the Allocation File.
See Also
• --exhaustive
• --freespace
• --usedspace
• --userfs_type freespace
• --userfs_type structure
• --userfs_type usedspace
• --who_owns_block BLOCK
• --who_owns_byte BYTE
40
-K --badblock
--badblock
List the extent(s) of the HFS+ Bad Allocation Block File, if one is present on the
volume.
The Bad Allocation Block File is neither a regular file nor a special file. It’s not a
regular file in that there’s no record of it in the HFS+ Catalog. It’s not a special
file in that there’s no reference to it in the HFS+ Volume Header. However, there
is a Catalog Node ID (CNID) reserved for the Bad Allocation Block File: 5. HFS+
can mark certain areas on the disk as “bad” (or unusable for some reason) by
assigning the corresponding allocation blocks to this CNID. If so, one or more
extents belonging to the “file” with CNID 5 will be recorded in the HFS+ Extents
Overflow File.
The Bad Allocation Block File is not used in the later versions of Mac OS X.
One of its historical uses was in “wrapper” volumes, wherein an HFS Standard
volume contained an HFS+ volume embedded in it. In those cases, the entire
space corresponding to the embedded HFS+ volume was marked as belonging
to the Bad Allocation File within the HFS Standard wrapper volume.
41
-B BLOCK --block BLOCK
--block BLOCK
† Although listed here for the sake of completeness, modifying the stride size
for any operation involving journal dissection should not be necessary and is
not advised.
When used with --output, --block instructs fileXray to read the contents
of the allocation block number BLOCK and either save them to a file or dump
them to the standard output depending on the argument to --output.
Note that the volume begins at allocation block number 0. The following exam-
ple shows how to read and save that allocation block to a file.
The HFS+ Volume Header resides at an offset of 1024 bytes from the start of
the volume. In this example, the volume’s allocation block size is the default
4096 bytes. Therefore, the block we copied contains the Volume Header. We
can use the hexdump program to examine the first few bytes of the volume
header.
The following shows the case when the destination is the standard output.
42
--block BLOCK
When used with the --trawl option, --block specifies the block size the
trawling operation should use for its “stride.” By default, fileXray trawls the
volume one allocation block at a time. The --block option allows you to specify
a smaller custom smaller size for this operation, which is useful if you want to
match content that’s not at the beginning of a file. The stride size specified
must be no larger than the volume’s allocation block size.
In the following example, we are looking for the remnants of a deleted PDF file
on a volume. The PDF file in question was—for the sake of this example—em-
bedded at an offset of 512 bytes within another file. The volume’s allocation
block size is the default of 4096 bytes. Therefore, the first trawl operation that
uses the default stride size does not find the PDF file’s remnants since it at-
tempts its pattern matching every 4096 bytes and therefore “steps over” the
content we are looking for. The second trawl operation, where we use --block
to specify a custom stride size of 512 bytes, does find the remnants. See the
section on --trawl for more details.
See Also
• --journal_names
• --output OUTPUT_FILE
• --read COMPONENT
• --scavenge
• --trawl QUERY
• --undelete_cookie COOKIE
• --userfs_type arbitrary
• --userfs_type scavenger
43
-b BTREE_NAME --btree BTREE_NAME
--btree BTREE_NAME
When used by itself, this option displays the contents of the given B-Tree’s
header node. The following is an example.
Note that the information displayed includes the header node’s node descriptor,
the B-Tree header record, and the B-Tree user data record. The map record in
44
--btree BTREE_NAME
the header node is not displayed; it can be seen by additionally using the
--node option to view all details of the header node, as described next.
The --btree option can be combined with the --node option to display infor-
mation about a specific node in the given HFS+ B-Tree. The --node option re-
quires a node number as an argument. (The number of the first node in an
HFS+ B-Tree is 0.) The type and amount of information displayed will depend
on the given node’s role in the B-Tree. In the following example, we inspect
node number 3 in the volume’s Catalog B-Tree. The node’s on-disk location is
also displayed, along with the node’s size, the number of free bytes in it, and
the number of records contained in it.
You can add the --exhaustive option which will also dump all free bytes—if
there are any—within the given node. In the following example, most of the
bytes in the node are free, beginning at byte offset 0x68 within the node. The
device offset shown is the corresponding byte offset on the device that the vol-
ume resides on.
45
--btree BTREE_NAME
that B-Tree. The --list_records option requires as an argument the type of
records to list. The type depends on the B-Tree in question, although the type
“any” causes all record types to be listed in any HFS+ B-Tree. See the
--list_records page for details.
The following is an example of listing all leaf records in the Catalog B-Tree.
Note that on a real-life volume with a large number of files, this can generate
rather large amounts of output.
46
--btree BTREE_NAME
See Also
• --exhaustive
• --node NODE
• --list_records RECORD_TYPE
47
-C COMPONENTS --checksum COMPONENTS
--checksum COMPONENTS
The target file system object must be specified through other options such as
--cnid, --fsspec, or --path.
By default, a data or resource fork’s logical byte size will be used for the hash
computation. In particular, if that size is not a multiple of the volume’s alloca-
tion block size, the trailing physical bytes that are beyond the fork’s logical size
will not be included in the computation. If you wish to change this behavior
and have the hash cover entire allocation blocks regardless of the logical fork
sizes, you can additionally specify the --exhaustive option.
48
--checksum COMPONENTS
# Create an empty file and compute checksum.
$ touch /tmp/testfile
$ sudo fileXray --checksum data,xattr_data /tmp/testfile
da39a3ee5e6b4b0d3255bfef95601890afd80709
See Also
• --exhaustive
• --cnid CNID
• --fsspec PARENT_CNID:NAME
• --path PATH
49
-c CNID --cnid CNID
--cnid CNID
Specify a file system object—file or folder—of interest through its Catalog Node
ID (CNID).
This option can be used with other options when fileXray requires a file sys-
tem object to operate upon. The --cnid option is one of the several ways in
which a file system object can be specified to fileXray. It is useful when you
wish to map a CNID to the corresponding file system object.
Let us consider an example. On HFS+, the first fifteen (1 through 15) CNIDs
are reserved for use by the file system itself. For instance, CNID 2 is always the
folder ID of the root folder, CNID 3 is used for the Extents Overflow File, CNID
4 is used for the Catalog B-Tree, and so on. CNID 16 is the first CNID that is
available for “users.” However, in the case of journaled HFS+ volumes, the
journal is implemented as a “regular” file on the volume, even though it is
made invisible to users by the kernel. When a new HFS+ volume is created, the
journal is the first file created under normal circumstances. Therefore, on typi-
cal HFS+ volumes, CNID 16 belongs to the journal. We can use the --cnid op-
tion to inspect the details of the file system object whose CNID is 16. In the ex-
ample on the next page, the volume in question is a root volume. We see that
CNID 16 indeed corresponds to the volume’s journal.
Note that it is possible for the journal file to not have CNID 16. In such a case,
it is still possible to directly inspect the file using the --fsspec option, which
allows specifying a target file system object through its parent’s CNID and the
object’s name.
See Also
• --checksum COMPONENTS
• --fsspec PARENT_CNID:NAME
• --diskusage
• --list
• --scavenge
• --path PATH
• --read COMPONENT
50
--cnid CNID
51
-d DEVICE --device DEVICE
--device DEVICE
The --device option is one of the ways in which an HFS+ volume can be ex-
plicitly specified to fileXray, the other being the --volume option. If no HFS+
volume is explicitly specified through these options, fileXray will attempt to
determine the device to use from other specified information, such as the path
to a file or a folder in case of mounted volumes. If the combination of user-
provided arguments is such that no volume is specified directly or indirectly,
fileXray will use the root volume provided the other arguments are valid.
Often, disks and disk images contain more than one volume, which leads to
the notion of a “whole” device (for example /dev/disk0) and “slices” (for exam-
ple /dev/disk0s1 and /dev/disk0s2). For the purpose of this discussion, a
“slice” is synonymous with a “partition.” Although it is possible for an HFS+ file
system to reside on a whole device, typical HFS+ volumes will reside on slices—
specifically, the beginning of an HFS+ volume usually coincides with the begin-
ning of a slice.
If the DEVICE argument is such that it does contain an HFS+ volume on it (that
is, DEVICE is either a slice or it’s a whole device containing no partitioning and
an HFS+ volume), fileXray will simply use that volume.
# Volume Header
signature = 0x482b (H+)
version = 0x4
lastMountedVersion = 0x4846534a (HFSJ)
attributes = 10000000000000000010000000000000
. kHFSVolumeJournaled (volume has a journal)
journalInfoBlock = 0x746
…
# Volume Header SHA-1
ed54ee3088851cee7113f55f6d1f839003540627
If, however, DEVICE is a whole device with valid partitioning, fileXray will
parse the partition table and attempt to detect all HFS+ volumes that may exist
on the slices of the given device. If one or more HFS+ volumes are found,
52
--device DEVICE
fileXray will display information on them and prompt the user to specify a
particular HFS+ volume using the --partition option. fileXray supports the
following partitioning schemes.
You can then specify the volume of interest using the --partition option.
However, a GUID Partition Table was detected on the given device with the
following 3 HFS+ partition table entries:
# Volume Header
signature = 0x4858 (HX)
version = 0x5
lastMountedVersion = 0x4846534a (HFSJ)
attributes = 10000000000000000010000000000000
. kHFSVolumeJournaled (volume has a journal)
journalInfoBlock = 0x3
…
# Volume Header SHA-1
200d216cedfe9fa7a52c96c8015d9c5b819b679b
53
--device DEVICE
Moreover, as a special case, fileXray allows DEVICE to be a regular file in-
stead of a block or a character device. This is useful when you have a raw
dump of a device that you want to inspect with fileXray without even at-
taching any (virtual) devices. As with a “real” device, a file can contain data for
either a single partition or a whole device.
However, an Apple Partition Map was detected on the given image file with the
following HFS+ partition table entry:
It is important to note that a device dump must be “raw”—that is, it must not
require any additional transformations such as decompression or decryption.
In other words, for a disk image file to be used directly by fileXray, the image
must not be compressed, encrypted, or sparse. fileXray will reject such an
image.
To attach a disk image without mounting any constituent volumes, you can
use hdiutil as follows.
54
--device DEVICE
$ hdiutil attach -nomount /path/to/diskimage.dmg
/dev/disk1 GUID_partition_scheme
/dev/disk1s1 Microsoft Basic Data
/dev/disk1s2 Apple_HFS
/dev/disk1s3 Apple_HFS
/dev/disk1s4 Apple_HFS
In the above example, the disk image contains three HFS+ volumes. The attach
operation results in block and character devices being assigned to the disk im-
age (the whole device /dev/disk1) and also to each of the constituent volumes
(/dev/disk1s1 through /dev/disk1s4). Now you can use any these devices as
an argument to the --device option of fileXray.
See Also
• --disallow_mounting SECONDS
• --partition START[,SIZE]
• --volume VOLUME_PATH
• hdiutil(1)
55
-T SECONDS --disallow_mounting SECONDS
--disallow_mounting SECONDS
With fileXray, you can not only fully analyze an unmounted (offline) volume,
you can use the --disallow_mounting option to prevent the volume of inter-
est from being automatically mounted as you attach the corresponding storage
device to the computer. When this option is used, fileXray will block for SEC-
ONDS seconds, during which time any new volumes that appear will not be al-
lowed to automatically mount. However, the devices underlying these volumes
will be allowed to attach, which in turn means that you can use fileXray on
the devices. As a device attaches, fileXray will print the corresponding block
device name(s) and if possible, the corresponding file system type(s) and vol-
ume name(s).
$ fileXray --disallow_mounting 60
Disallowing mounting through Disk Arbitration for 60 seconds.
…
# Now attach an external device
…
disk1s2 hfs Untitled 2
disk1s4 hfs Untitled 4
disk1s3 hfs Untitled 3
disk1s1 msdos UNTITLED 1
Note that this method disables both automatic mounting by the Disk Arbitra-
tion mechanism and user-initiated mounting through the Mac OS X Disk Util-
ity application. However, you can still mount volumes manually if you use the
mount() system call: either directly using the mount command-line program or
using a custom program that invokes the mount() system call. This way, you
56
--disallow_mounting SECONDS
have flexibility in controlling which volumes can get mounted and which can-
not.
A noteworthy point is regarding the use of this method with disk images. If you
use --disallow_mounting and then attempt to mount a volume residing on a
disk image (say, by double-clicking the disk image or by using the open
command-line program), fileXray will indeed disallow mounting, but the end
result will be undesirable: the image will be detached after the mount attempt.
Therefore, the block device name(s) displayed by fileXray will be stale and
therefore useless. This is because the operating system’s default mode of op-
eration when dealing with disk images is to fail the attach attempt if no file sys-
tems mount. You can handle this case in several ways.
The simplest approach is to use the hdiutil command-line program with the
-nomount option to attach the disk image without mounting any volumes.
fileXray may or may not be running with the --disallow_mounting option.
Alternatively, you can use the Disk Utility application while fileXray is run-
ning with the --disallow_mounting option. Drag and drop the disk image in
question to the Disk Utility sidebar, select the image, and click on the “Open”
button in the Toolbar. fileXray will disallow the mounting of any volumes but
they will remain attached.
X
Z
Y
57
--disallow_mounting SECONDS
See Also
• --device DEVICE
• --partition START[,SIZE]
• --volume VOLUME_PATH
• hdiutil(1)
58
-D --diskusage
--diskusage
The target file system object must have been specified using other options such
as --cnid, --fsspec, or --path.
If the target object is a file, its disk usage is the sum of the sizes of the file’s
data fork, resource fork, and the cumulative disk space used by the names and
values of all its extended attributes.
$ ls -l /Applications/Safari.app/Contents/MacOS/Safari
-rwxr-xr-x 1 root wheel 5096208 Jul 27 23:53 /Applications/…/Safari
The following example shows examining the HFS+ journal’s disk usage using
the --fsspec option to specify the journal file by its parent folder’s Catalog
Node ID (CNID) and its name. (If the journal is local to an HFS+ volume, it re-
sides in the root folder, which has the CNID 2.)
The following example shows examining the Catalog B-Tree’s disk usage using
the --cnid option to specify the Catalog B-Tree’s CNID, which is always 4.
If the target file system object is a folder, its disk usage is the cumulative disk
usage of the folder’s contents, computed recursively. Additionally, if a folder
has any extended attributes, the cumulative disk space used by the names and
values of the extended attributes is included in the folder’s disk usage. The fol-
lowing is an example.
59
--diskusage
$ sudo fileXray --diskusage /bin
3610554 logical bytes (3.6 MB) in 894 allocation blocks (3.7 MB) for the \
resource fork.
493 logical bytes in 29 extended attribute names.
464 logical bytes in 29 extended attribute values.
However, there are differences. For example, the kernel hides certain extended
attributes by filtering them out within the in-kernel HFS+ implementation.
Since fileXray itself parses raw HFS+ data structures, it is not subject to any
such filtering and has a complete view of on-disk information. Therefore, in the
--diskusage case, fileXray can report disk space consumed by all extended
attributes whereas a higher-level program cannot.
See Also
• --cnid CNID
• --fsspec PARENT_CNID:NAME
• --path PATH
60
-A --enable_xattr_extents
--enable_xattr_extents
A mounted volume must also be specified using the --volume option, which
requires either the mount point of the volume or the path to a file system object
on the volume as an argument. When used with this option, --volume has a
special case: if you wish to change the next allocation block on the root volume,
you must explicitly use “/” as the argument to --volume. Since --en-
able_xattr_extents alters fundamental volume behavior, its use on the root
volume requires explicit specification.
To use this option successfully, the HFS+ implementation in the operating sys-
tem version you are running must support extent-based extended attributes.
At the time of this writing, although Mac OS X Leopard (10.5.x) and Mac OS X
Snow Leopard (10.6.x) have experimental implementations of extent-based ex-
tended attributes, by default, only inline extended attributes are allowed.
An inline extended attribute is one that fits within a single Attributes B-Tree
node while maintaining any structural overheads and other requirements for
B-Tree nodes. The default node size for the Attributes B-Tree is 8192 bytes, as
can be seen using the --btree option. As can be shown through some calcu-
lations, this leads to a maximum inline attribute size of 3802 bytes. In other
words, on an HFS+ volume that was created using default settings, the maxi-
mum size for an extended attribute’s value is 3802 bytes. We can verify this on
a test volume as follows.
$ cd /private/tmp
$ hdiutil create -megabytes 32 -fs HFSJ -volname test hfsj.dmg
............................................................................
...
created: /private/tmp/hfsj.dmg
$ hdiutil attach hfsj.dmg
/dev/disk1 GUID_partition_scheme
/dev/disk1s1 Apple_HFS /Volumes/test
$ cd /Volumes/test
$ touch file
$ xattr -w testkey `perl -e 'print "A" x 3802'` file
$ fileXray file
…
# Attribute Data Record (Inline)
# Record 0 in node 1 beginning at 512-byte sector 0x620
recordType = 0x10
reserved[0] = 0
reserved[1] = 0
attrSize = 3802 bytes
attrData = 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
A A A A A A A A A A A A A A A A
…
$ xattr -w testkey `perl -e 'print "A" x 3803'` file
xattr: [Errno 7] Argument list too long: 'file'
61
--enable_xattr_extents
We create and attach a new disk image with an HFS+ volume, create a file on
it, set an extended attribute whose value is 3802 bytes in size, and examine the
file using fileXray. Next, we see that our attempt to set the attribute’s value
to be a byte larger (3803 bytes) fails. We can now use the --enable_xattr_ex-
tents option on this volume to enable extent-based extended attributes, and
retry the failed operation.
# Attribute Key
keyLength = 26
pad = 0
fileID = 24
startBlock = 0
attrNameLen = 7
attrName = testkey
# Attribute Fork Data Record (Extent-Based)
# Record 1 in node 1 beginning at 512-byte sector 0x620
recordType = 0x20
reserved = 0
logicalSize = 3803 bytes
clumpSize = 0 bytes
totalBlocks = 1
extents = startBlock blockCount % of attribute
See Also
• --fsspec PARENT_CNID:NAME
• --mount_data
• --path PATH
• --volume VOLUME_PATH
62
-E --exhaustive
--exhaustive
A meta option that can be used along with several other options to enable “ex-
haustive” or “detailed” behavior.
What constitutes detailed behavior differs from option to option. When used
with an option that does not have such behavior, --exhaustive is a no-op and
is silently discarded by fileXray.
The following table outlines how --exhaustive modifies the behavior of other
fileXray options.
--allocation Enable a more detailed and more visual view of the Alloca-
tion File by displaying an identifying character for each
allocation block on the volume.
--btree BTREE_NAME Dump all free bytes, if any, within a given node in the
given B-Tree.
--journal_names When listing object names found in the journal, also show
differences between the volume and journal copies of me-
tadata whenever applicable and possible.
--userfs_type scavenger When serving scavenged blocks for data or resource forks,
always serve the current on disk content even if a block is
clobbered—do not substitute blocks that are known to
have been reused with zero-filled blocks.
63
--exhaustive
See Also
• --allocation
• --btree BTREE_NAME
• --checksum COMPONENTS
• --fragmentation FORK_TYPE
• --journal
• --journal_names
• --monitor
• --read COMPONENT
• --scavenge
• --userfs_type scavenger
• --volume_header
64
-x FILTER --filter FILTER
--filter FILTER
Load and run the fileXray “filter” implemented in the dynamic library whose
path is FILTER. An fileXray filter can optionally take a string argument
specified through the --filter_args option.
As a special case, FILTER can have the literal prefix builtin: followed by a
built-in filter’s name. fileXray includes the following built-in filters. Those
with highlighted names require filter arguments.
bmactime
The bmactime filter is a family of filters—a meta filter if you will—whose names
all end with the suffix “time”. The prefix can be a permutation of one or more
of the characters ‘b’, ‘m’, ‘a’, and ‘c’. For example, “atime”, “btime” “ctime”,
“mtime”, “bmactime”, and “cmtime” are all valid filter names for the bmactime
meta filter. The prefix characters represent HFS+ timestamps as follows.
66
--filter FILTER
• When specified on the fileXray command line, the eventual string
S1,S2 must be appropriately quoted since the constituent date strings
contain whitespace.
As noted earlier, the conversion specifications (%b, %d, and so on) have the
same meaning as they have in the strftime(3) C library function. The fol-
lowing is a quick reference.
Note that for a file system object to be matched by this filter, all specified times-
tamps must match. For example, if bmctime is the specific filter used, then
fileXray will look for file system objects whose creation times (b), attribute
modification times (m), and content modification times (c) all fall within the
given time range.
In the following example, we look for file system objects that were modified
within the last 60 seconds. We pipe the output through the sort command-line
program to get a timeline view.
Note the timestamp identifiers column in the output. This column will contain
identifiers for the timestamps that the current output line applies to. A dot rep-
resents a timestamp that does not apply to the current line. For example, if the
specified filter is bmactime, then we are looking for four timestamps (b, m, a,
and c). Now, for a given file system object, all of these timestamps could have
the same values, or all of them could be different, or some could be the same,
67
--filter FILTER
etc. The output contains one line per file for each timestamp value that’s differ-
ent, whereas equal timestamps are coalesced into a single line. In the above
example, we are looking for two timestamps (m and c), which happen to be
equal for each matching file. Therefore, there is only one line of output per
matching file. If a matching file had m and c timestamps that were different, it
would have two lines of output: one for m and another for c.
compressed
The compressed filter lists all HFS+ compressed files on the volume. Beginning
with version 10.6 (Snow Leopard), Mac OS X supports transparent file com-
pression at the file system level. Several system components are compressed by
default. Depending on the file’s size and potentially other factors, the com-
pressed data resides either in the file’s resource fork or inline within an ex-
tended attribute that’s set on the file. The following is an example of using the
compressed filter.
creatorcode
The creatorcode filter lists all files with the given creator code. The following
is an example of using this filter to look for files with the creator code TVOD,
which is traditionally assigned to QuickTime movies.
68
--filter FILTER
device
The device filter lists all block and character special files on the volume. Typical
HFS+ volumes, including root volumes, will typically have no such files be-
cause devices on Mac OS X reside in the device file system (devfs), which is a
pseudo file system mounted on /dev at system startup time.
dirhardlink
The dirhardlink filter lists all directory hard links on the volume. For each
directory hard link with a link count of N, there are N + 1 lines in the output,
listed in the order the corresponding records exist in the Catalog B-Tree. There
is one line that displays the link target and the number of links that point to it.
The remaining N lines display the paths for each of the links.
A directory
hard link
Directory hard link targets reside in a hidden system folder that is normally in-
visible to user applications: /.HFS+ Private Directory Data\x000d/. Its
Catalog Node ID can be seen in the output of the --volume_header option.
empty
emptyforks
The empty filter lists files whose data and resource forks are both empty (zero
logical size) and additionally there are no extended attributes associated with
the files. The emptyforks filter lists files whose data and resource forks are
both empty, although there still could be content in extended attributes.
69
--filter FILTER
fifo
The fifo filter lists all named pipes (fifos) on the volume.
hardlink
The hardlink filter lists all hard links on the volume. The output format is
along the same lines as that of the dirhardlink filter.
A directory
hard link
File hard link targets reside in a hidden system folder that is normally invisible
to user applications: /\x0000\x0000\x0000\x0000HFS+ Private Data/. Its
Catalog Node ID can be seen in the output of the --volume_header option.
immutable
The immutable filter lists all immutable files and folders on the volume. Im-
mutability can be set at the system level, at the user level, or both. The filter’s
output indicates this by using the s (system) and u (user) prefixes.
70
--filter FILTER
Note that the implementation of file and directory hard links on HFS+ employs
immutable files. The immutable filter does not list such hard link implementa-
tion files on purpose. (The dirhardlink and hardlink filters, respectively, can
be used to list directory and file hard links.)
lsR
The lsR filter lists all paths on the volume along with the Catalog Node ID of
each file or folder. The filter is named after the command “ls -R”, which, if
executed at the root level of a volume, would recursively list all subdirectories
encountered.
macho
The macho filter lists all Mach-O files on the volume. It differs from most
fileXray filters in that it examines file content along with file metadata. After
identifying a file as a Mach-O file, the filter further examines it to check if it is a
multi-architecture (“fat”) file. If so, the filter calculates the logical size of each
architecture-specific thin subfile contained within the fat file. The macho filter
recognizes the following architectures: i386, x86_64, ppc, ppc64, and arm. Any
other architecture found in a Mach-O file is categorized as “other.” You can op-
tionally specify a comma-separated list of architectures as the filter argument,
in which case it will only show files containing at least one of the specified ar-
chitectures. The following is an example of using the macho filter.
If the on-disk Mach-O file (fat or otherwise) is HFS+ compressed, the macho fil-
ter will indicate compression by displaying the character z before the file’s
path. However, the per architecture sizes computed by this filter are the actual
uncompressed sizes.
71
--filter FILTER
name
namei
The name filter lists all file system objects whose names exactly match the
name specified by the filter argument. The namei filter is the case-insensitive
variant of the name filter. Note that the HFS+ volume in question can be either
case-sensitive or case-insensitive—these filters perform their own matching
and work the same on either type of volumes, as do the other built-in name-
matching filters.
nameprefix
nameprefixi
The nameprefix filter lists all file system objects whose names contain the
prefix specified by the filter argument. The nameprefixi filter is the case-
insensitive variant of the nameprefix filter.
72
--filter FILTER
namesuffix
namesuffixi
The namesuffix filter lists all file system objects whose names contain the
suffix specified by the filter argument. The namesuffixi filter is the case-
insensitive variant of the namesuffix filter. In the following example, we look
for names that have the .app suffix—that is, typical application bundles.
nodename
The nodename filter lists the parent Catalog Node IDs and node names of all
files and folders on the volume. The output will have as many lines as the sum
of the volume’s file and folder counts.
You can use programs such as awk, sort, and uniq on the output of this filter
to identify the most used object names, the longest object names, the folders
with the most children, and other interesting data.
73
--filter FILTER
null
Like most other fileXray filters, the null filter walks the entire file system
hierarchy, examining each file and folder. However, unlike other filters, the
null filter does not do anything with the information it examines. It can be
used as a baseline for the time it takes for fileXray to examine the file system
hierarchy on a given system. The time taken will depend on several factors
such as the number of files and folders on a volume, how fragmented the vol-
ume is, and most importantly, how much I/O bandwidth the system has.
socket
The socket filter lists all Unix Domain sockets on the volume.
subname
subnamei
The subname filter lists all file system objects whose names contain the string
specified by the filter argument. The subnamei filter is the case-insensitive
variant of the subname filter. These filters have the most permissive matching
among all built-in name matching filters.
sxid
The sxid filter lists all setuid and setgid file system objects on the volume. A
setuid or setgid object is one that has its set-user-ID-on-execution or set-group-
ID-on-execution bits, respectively, set.
Note that both files and folders can have these bits set. Consider the setuid bit.
In the case of an executable file, the setuid bit changes how the file executes: if
otherwise permitted, the file will execute with the effective user ID set to the
74
--filter FILTER
user ID of the file’s owner. In the case of a folder, this bit affects ownership of
file system objects created within the folder: if otherwise permitted, newly cre-
ated objects will be owned by the directory owner and not by the user ID of the
creating process.
User ID Group ID
symlink
The symlink filter lists all symbolic links (along with their link targets) on the
volume.
typecode
The typecode filter lists all files with the given file type code. The following is
an example of using this filter to look for files with the type code FFIL, which is
traditionally assigned to a category of font files.
The xattrname filter lists the names of all unique extended attribute keys used
on the volume. For each unique extended attribute name found, the filter also
lists the number of file system objects for which that attribute is set.
xattr
The xattr filter lists all file system objects that have the given extended attrib-
ute name set. The attribute name is specified as the filter argument. For exam-
ple, you can look for objects with attributes such as com.apple.quarantine
(quarantined files and folders), com.apple.decmpfs (transparently compressed
files), and com.apple.system.Security (objects with Access Control Lists).
The following example shows using the xattr filter to list quarantined files.
76
--filter FILTER
$ sudo fileXray --filter builtin:xattr --filter_args com.apple.quarantine
…
MacHD:/Users/johndoe/Library/Safari/WebpageIcons.db
MacHD:/Users/johndoe/Library/Preferences/com.apple.Safari.RSS.plist
MacHD:/Users/johndoe/Library/Caches/Metadata
MacHD:/Users/johndoe/Library/Caches/Metadata/Safari
MacHD:/Users/johndoe/Library/Caches/Metadata/Safari/Bookmarks
MacHD:/Users/johndoe/Library/Caches/com.apple.Safari/Webpage Previews
MacHD:/Users/johndoe/Library/Caches/Metadata/Safari/History
…
As noted at the beginning of this section, fileXray can load third-party filters.
A third-party filter is a dynamic library that implements up to three functions,
one of which is mandatory (fileXray_filter_callback) and two are optional
(fileXray_filter_init and fileXray_filter_fini). When a filter library’s
path is provided to fileXray through the --filter option, fileXray looks up
the library and dynamically loads it.
77
--filter FILTER
#ifndef __FILEXRAY_FILTER_H__
#define __FILEXRAY_FILTER_H__
/*
* A "path computer" function is passed as an argument to your filter's callback
* function. The purpose of this argument is to allow your callback function to
* compute the path to the file or folder record in question IF you need to do
* so--typically because the record in question matches some criteria and you
* want to print its path.
*
* Currently, the purpose of the fobject argument is private. When you call the
* path computer function, you MUST set this argument to NULL.
*/
typedef const char* (*fx_path_computer_t)(const void* fobject);
/*
* A "record swapper" function is passed as an argument to your filter's
* callback function. The record swapper allows your callback to endian-swap
* (if necessary) the entire file system object record. HFS+ is big endian on
* disk. Therefore, on little-endian machines, you will need to swap record
* fields. Note that the record swapper swaps the entire file or folder record.
* If you are only interested in one or few fields, this may be too expensive.
* In that case, you should not call the swapper and should swap fields of
* interest yourself.
*/
typedef void (*fx_record_swapper_t)(void* record);
/*
* Your filter's "init" function is called once before any records are processed
* by fileXray. If any filter argument string was passed on the fileXray command
* line, it will be forwarded to the init function as filter_args. If no filter
* argument string was provided, filter_args will be NULL. The init function is
* optional for your filter to implement. If you don't need to do any initial
* setup in your filter or if your filter does not need any arguments, you can
* choose not to implement this function.
*
* The required name for your filter's init function is:
*
* filexray_filter_init
*
* Your init function must return a 0 on success. If it returns any other value,
* fileXray will terminate further processing.
*/
typedef int (*fx_init_t)(const char* filter_args);
/*
* fileXray will call your filter's callback function once for each file or
* folder record in the HFS+ catalog. The purpose of the computePath and
* swapRecord arguments is described above. The info argument is a pointer to
* to either an HFS+ folder record or an HFS+ file record: that is,
* struct HFSPlusCatalogFolder and struct HFSPlusCatalogFile, respectively,
* both of which are defined in <hfs/hfs_format.h>.
*
* The required name for your filter's callback function is:
*
* filexray_filter_callback
*
* Your callback function must return a 0 value if further record processing
* is to continue. If you wish to terminate processing, perhaps because you
* found what you were looking for, or you ran into some error, you can return
* a non-zero value to cause record processing to terminate.
*/
typedef int (*fx_callback_t)(void* info,
const fx_path_computer_t computePath,
const fx_record_swapper_t swapRecord);
/*
* Your filter's "fini" function is called once after fileXray is done with
* record processing, because either all records have been processed, or your
* callback returned a non-zero value causing fileXray to stop processing.
*
* The required name for your filter's callback function is:
*
* filexray_filter_fini
*/
typedef void (*fx_fini_t)(void);
#endif /* __FILEXRAY_FILTER_H__ */
78
--filter FILTER
Let us use the fileXray_filter.h header file to implement an example filter
that takes a number as its argument and prints the paths to all files and fold-
ers whose Catalog Node IDs are numerically lower than that number. Let us
call it the “low inode” filter. The following is the entire source code for this filter.
/* filexray_filter_lowinode.c */
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/types.h>
#include <stdint.h>
#include <hfs/hfs_format.h>
#include <libkern/OSByteOrder.h>
#include "filexray_filter.h"
int
filexray_filter_init(const char* filter_args)
{
if (!filter_args) {
fprintf(stderr,
"This filter requires an argument: the inode upper limit.\n");
return -1;
}
inodeUpperLimit = (uint32_t)val;
return 0;
}
int
filexray_filter_callback(void* info, fx_path_computer_t computePath,
fx_record_swapper_t swapRecord)
{
u_int32_t inodeNumber;
if (recordType == kHFSPlusFolderRecord) {
inodeNumber =
OSSwapBigToHostInt32(((struct HFSPlusCatalogFolder*)info)->folderID);
inodeNumber =
OSSwapBigToHostInt32(((struct HFSPlusCatalogFile*)info)->fileID);
} else {
return 0;
}
return 0;
}
void
filexray_filter_fini(void)
{
/* Nothing to do here. It would also be fine leave this unimplemented. */
}
79
--filter FILTER
We can compile and try the low inode filter as follows.
$ gcc -arch x86_64 -arch i386 -arch ppc -Wall -dynamiclib -o lowinode.dylib
\
fileXray_filter_lowinode.c
$ fileXray --volume /Volumes/PreciousHD --filter lowinode.dylib \
--filter_args 100
2 PreciousHD:
22 PreciousHD:/.fseventsd
19 PreciousHD:/.HFS+ Private Directory Data\x000d
16 PreciousHD:/.journal
17 PreciousHD:/.journal_info_block
20 PreciousHD:/.Trashes
18 PreciousHD:/\x0000\x0000\x0000\x0000HFS+ Private Data
21 PreciousHD:/.Trashes/501
23 PreciousHD:/.fseventsd/fseventsd-uuid
By default, filters are volume wide. That is, a filter potentially processes all file
system objects on the given volume, although a filter callback function can
choose to terminate processing based on arbitrary criteria. You can usually run
a filter in directory wide mode by specifying a directory either implicitly or
through the --cnid, --fsspec, and --path options. In directory wide mode, a
filter will limit its operation to the specified directory, including (recursively)
any subdirectories it might have. The following is an example.
See Also
• --filter_args STRING
80
-X STRING --filter_args STRING
--filter_args STRING
The contents of STRING are parsed only by the filter. If STRING contains
whitespace or any other characters that may be specially interpreted by the
command shell, you must appropriately quote STRING.
See Also
• --filter FILTER
81
--force
--force
A meta option that can be used along with other options. It enables fileXray
to continue certain operations even when an apparent failure occurs.
See Also
• --userfs_mount MOUNT_POINT
• --userfs_type arbitrary
82
--fragmentation FORK_TYPE
--fragmentation FORK_TYPE
For the purpose of this option, a fragmented fork is one whose content is not
fully contiguous on disk. In other words, a fragmented fork has at least two ex-
tents. Another measure of “high” fragmentation is whether a fork has more
than eight extents, since information about the first eight extents can be stored
“inline” in the Catalog B-Tree record of the file in question.
➊ ➋ ➌ ➍ ➎➏ ➐ ➑
The numerically annotated fields in this example have the following meanings.
83
--fragmentation FORK_TYPE
You can additionally specify the --top option to list details of the volume’s top
N most fragmented forks. The number N is specified as an argument to the
--top option.
The following example (output cropped to fit on this page) shows using --top
to list the top ten most fragmented data forks on the volume. Note that it is
possible that the argument N passed to --top is larger than the number of
fragmented forks that exist on the volume. In such a case, all fragmented forks
of the given type will be listed. In all cases, the forks are listed with the most
fragmented fork at the bottom of the screen. This way, if the screen scrolls,
you’ll still see the most fragmented forks without having to scroll up.
See Also
• --exhaustive
• --hotfiles
• --summary FORK_TYPE
• --top N
84
-f FORK_TYPE --freespace
--freespace
For each free extent, fileXray displays the following information: the number
of allocation blocks in that extent, the starting and ending block numbers in
hexadecimal, and the amount of associated free space.
You can pipe the output through “sort -n” to view a list of contiguous free
space chunks sorted by chunk size. In the following example, we see that the
largest contiguous chunk on the volume has 13,525,354 allocation blocks. The
chunk starts at allocation block number 0x2d3e1b9 and ends at allocation
block number 0x3a24322. Given the allocation block size of 4096 bytes, this
chunk amounts to 55 GB.
See Also
• --usedspace
• --userfs_mount MOUNT_POINT
• --userfs_type freespace
• --userfs_type usedspace
85
-F PARENT_CNID:NAME --fsspec PARENT_CNID:NAME
--fsspec PARENT_CNID:NAME
There are system files and folders that HFS+ intentionally makes it “hard” (by
incorporating “hard to type” characters in the name) or “impossible” (by explic-
itly filtering them in the kernel) to access. fileXray provides several ways to
examine such file system objects. The --fsspec option is also useful in such
cases.
For example, on a journaled volume with a locally resident journal (the de-
fault), the journal resides in the root folder as a file named .journal. The file
cannot be accessed from user space because a Catalog B-Tree lookup function
in the kernel explicitly return an ENOENT error when a user program attempts
to access this file. Given the file’s name and the fact that the root folder’s Cata-
log Node ID is always 2, we can use the --fsspec option to examine the file.
$ ls -las /.journal
ls: /.journal: No such file or directory
86
--fsspec PARENT_CNID:NAME
See Also
• --cnid CNID
• --diskusage
• --list
• --path PATH
• --read COMPONENT
87
-H --hotfiles
--hotfiles
Display the “hottest” files on the volume if the volume uses Hot File Clustering
(HFC).
Hot File Clustering is an HFS+ optimization that aims to improve the perform-
ance of small, frequently accessed files on a volume. It is implemented as a
multi-staged clustering scheme that tracks “hot” files (except journal and quota
files) and dynamically relocates them to a designated “hot space” on the vol-
ume. Mac OS X uses Hot File Clustering only on boot volumes. Under certain
circumstances, such as too little space being free on a boot volume, Mac OS X
can choose to disable Hot File Clustering.
The --hotfiles option requires the --top option to specify a number N, which
will cause fileXray to display the N hottest files.
The following example (screenshot cropped to fit on this page) shows using
--top to list the top ten hottest on the volume.
Hot File Clustering uses a B-Tree to keep track of hot files. You can analyze the
B-Tree using the --btree option.
Live Hot File Clustering parameters—if any—for a mounted HFS+ volume can
be seen in the output of the --mount_data option. In particular, you can de-
termine from that output if Hot File Clustering is enabled or not for the volume.
See Also
• --btree BTREE_NAME
• --fragmentation FORK_TYPE
• --mount_data
• --top N
88
-I --iec
--iec
A global option that tells fileXray to use powers of 2 and IEC 60027-2 pre-
fixes when displaying byte values.
The following example shows the effect --iec has on the output of the --list
option when the latter is used to list the contents of the /bin folder.
89
introspect
introspect
90
introspect
Introspecting Files
The previous page shows an excerpt from the detailed output on a regular file.
The numerically annotated parts of this excerpt mean the following.
The next details that fileXray displays about a file are descriptions of its data
and resource forks. For each fork, fileXray will display all of the fork’s ex-
tents, along with fragmentation statistics.
…
# Data Fork
logicalSize = 0 bytes
# Resource Fork
logicalSize = 7537374 bytes (7.5 MB)
totalBlocks = 1841
fork temperature = no record in Hot File B-Tree
clumpSize = 137
extents = startBlock blockCount % of file
continued…
Next, fileXray will display all extended attributes—if any—that the file has.
This includes any “special” extended attributes that are normally hidden or en-
tirely filtered by the kernel. For example, HFS+ implements access control lists
(ACLs) via extended attributes. If the file in question has an ACL, fileXray will
display the raw contents of the corresponding extended attribute. Moreover,
91
introspect
fileXray will parse the ACL itself and display details of the resultant security
information. In the current example, the file does have an ACL, as shown be-
low.
…
# Attributes
# Attribute Key
keyLength = 62
pad = 0
fileID = 3294534
startBlock = 0
attrNameLen = 25
attrName = com.apple.system.Security
# Attribute Data Record (Inline)
# Record 7 in node 14003 beginning at 512-byte sector 0x4a568
recordType = 0x10
reserved[0] = 0
reserved[1] = 0
attrSize = 68 bytes
attrData = 01 2c c1 6d 00 00 00 00 00 00 00 00 00 00 00 00
, m
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 01 00 00 00 00 d1 d4 2b f9
+
89 3d 4e 9a 95 67 46 12 79 f2 d1 52 00 00 00 01
= N g F y R
00 00 00 04
continued…
92
introspect
compressed size, and so on. In the current example, the file is HFS+ com-
pressed, as shown below.
…
# Attribute Key
keyLength = 46
pad = 0
fileID = 3294534
startBlock = 0
attrNameLen = 17
attrName = com.apple.decmpfs
# Attribute Data Record (Inline)
# Record 11 in node 1209 beginning at 512-byte sector 0x185c8
recordType = 0x10
reserved[0] = 0
reserved[1] = 0
attrSize = 16 bytes
attrData = 66 70 6d 63 04 00 00 00 60 ea 1c 01 00 00 00 00
f p m c `
Introspecting Folders
As in the case of files, introspecting a folder with fileXray will result in a vari-
ety of information being displayed, much of which is similar between files and
folders. The following is an example.
93
introspect
Introspecting File Hard Links
File hard links on HFS+ are conceptually similar to those on typical Unix sys-
tems: they represent multiple directory entries referring to common file con-
tent. Implementation-wise, HFS+ hard links use a special hard-link file for each
directory entry. The common file content is stored in another special file: the
indirect-node file. All indirect-node files are stored in a special directory called
the private metadata folder. The latter, which resides in the root folder of a vol-
ume, is normally invisible to the user. It has a name that begins with four NUL
characters and is therefore “hard” to type.
We begin by creating a file called, say, file1. Before we create a hard link to
this file, we examine its details so that we can determine which file properties
change after link creation.
$ ln file1 file2
Let us see what, if anything, has changed about file1 now that we have cre-
ated a hard link to it.
94
introspect
$ sudo fileXray file1
path = MacHD:/private/tmp/test/file1
…
# Catalog File Record
# Record 88 in node 45652 beginning at 512-byte sector 0x3ee778
type = file (hard link)
indirect node CNID = 3298018
indirect node file = MacBookHD:/\x0000\x0000\x0000\x0000HFS+ Private
Data/iNode3298018
file ID = 3298169
flags = 0000000000100010
. File has a thread record in the catalog.
. File has hardlink chain.
…
# BSD Info
ownerID = 3298170 (previous link ID)
groupID = 0 (next link ID)
adminFlags = 00000000
ownerFlags = 00000010
. UF_IMMUTABLE (file may not be changed)
fileMode = -r--r--r--
iNodeNum = 3298018 (link reference number)
textEncoding = 0
reserved2 = 0
# Finder Info
fdType = 0x686c6e6b (hlnk)
fdCreator = 0x6866732b (hfs+)
fdFlags = 0000000100000000
. kHasBeenInited
…
# Data Fork
logicalSize = 0 bytes
# Resource Fork
logicalSize = 0 bytes
…
We see that a lot has changed—the on-disk nature of file1 has transformed
quite a bit. The original file content has “moved” to an indirect-node file. What
was file1 before in the Catalog B-Tree has been replaced with a new directory
entry altogether: one that has a new Catalog Node ID (CNID) within the file sys-
tem. This new directory entry is also a file, but with several special properties.
Its type and creator (as stored in the Finder Info metadata) are hlnk and hfs+,
respectively. It is marked immutable. Since the content is in the indirect-node
file, this special entry’s data and resource forks are both empty. Moreover, the
on-disk owner and group ID fields have been repurposed to act as the previous
and next links, respectively, in what’s called a hard link chain. The creator and
type codes are set to special values: hfs+ and hlnk, respectively.
Hard link chains is a feature that was introduced in Mac OS X 10.5 (Leopard).
It enables the file system to keep track of hard links via doubly linked lists of
CNIDs connecting hard links together. In the current example, we see that the
previous link ID is 3298170. Let us examine that CNID with fileXray.
95
introspect
$ sudo fileXray -c 3298170
path = MacHD:/private/tmp/test/file2
…
# Catalog File Record
# Record 87 in node 45652 beginning at 512-byte sector 0x3ee778
type = file (hard link)
indirect node CNID = 3298018
indirect node file = MacBookHD:/\x0000\x0000\x0000\x0000HFS+ Private
Data/iNode3298018
file ID = 3298170
flags = 0000000000100010
. File has a thread record in the catalog.
. File has hardlink chain.
…
# BSD Info
ownerID = 0 (previous link ID)
groupID = 3298169 (next link ID)
adminFlags = 00000000
ownerFlags = 00000010
. UF_IMMUTABLE (file may not be changed)
fileMode = -r--r--r--
iNodeNum = 3298018 (link reference number)
textEncoding = 0
reserved2 = 0
# Finder Info
fdType = 0x686c6e6b (hlnk)
fdCreator = 0x6866732b (hfs+)
fdFlags = 0000000100000000
. kHasBeenInited
…
# Data Fork
logicalSize = 0 bytes
# Resource Fork
logicalSize = 0 bytes
…
We see that CNID 3298170 corresponds to the other reference (hard link) we
just created: file2. The properties of this reference are similar to those of the
other reference file1. They do differ in their CNIDs. (Indeed, they are imple-
mented as two separate on-disk files.) They also differ in their previous and
next link IDs—as we can see, file1 and file2 are connected in a hard link
chain.
The file’s content is in an indirect-node file, which is now the on-disk object
with the original CNID (3298018). Let us examine this CNID. As shown on the
following page, the indirect-node file acts as a container for several of the origi-
nal file’s properties. In particular, it has the original file’s content, owner ID,
and group ID. A reserved field (reserved1) contains the CNID of the head of
the hard link chain.
96
introspect
$ sudo fileXray -c 3298018
path = MacBookHD:/\x0000\x0000\x0000\x0000HFS+ Private
Data/iNode3298018
…
# Catalog File Record
# Record 10 in node 45723 beginning at 512-byte sector 0x3eebe8
type = file
file ID = 3298018
flags = 0000000000100010
. File has a thread record in the catalog.
. File has hardlink chain.
reserved1 = 3298170 (first link ID)
…
# BSD Info
ownerID = 501 (johndoe)
groupID = 0 (wheel)
adminFlags = 00000000
ownerFlags = 00000000
fileMode = -rw-r--r--
linkCount = 2
…
# Data Fork
logicalSize = 14 bytes
totalBlocks = 1
fork temperature = no record in Hot File B-Tree
clumpSize = 0
extents = startBlock blockCount % of file
Note that if you now delete one of the hard link files, say, file2, things will not
revert back to how they were to begin with. You will now have file1 as the
only hard-link file along with the indirect-node file still holding the content.
97
introspect
Introspecting Directory Hard Links
Beginning with Mac OS X 10.5 (Leopard), HFS+ also supports directory hard
links, although it is not straightforward for a user to create a directory hard
link. This is because directory hard links are not really meant for third-party
use—they are an implementation detail needed to make the Time Machine fea-
ture of Mac OS X work.
At the time of this writing, the following conditions must be met for a directory
hard link’s creation to be allowed. In the following list, “source” refers to the ex-
isting directory that will be pointed at by the new directory hard link “destina-
tion” that’s being created.
If these conditions are met, you can create a directory hard link on an HFS+
volume under Mac OS X 10.5 and above. The following C program, which uses
the link() system call, can be used to experiment.
/* dirlink.c */
#include <stdio.h>
#include <unistd.h>
int
main(int argc, char** argv)
{
int ret = -1;
if (argc == 3) {
ret = link(argv[1], argv[2]);
if (ret) {
perror("link");
}
}
return ret;
}
Let us create and examine a directory hard link. In the /tmp/test testing di-
rectory we used earlier for file hard links, we will create a directory dir1 and a
subdirectory subdir. In subdir, we will create a hard link dir2 to dir1. (Re-
call that dir1 and dir2 are not allowed to have the same parent.)
98
introspect
$ gcc -Wall -o /tmp/dirhardlink dirhardlink.c
$ cd /tmp/test
$ mkdir dir1 subdir
Before we create the directory hard link, let us examine the current on-disk
details of the dir1 directory.
Let us now create the link and confirm that our expectations of directory hard
link semantics are met.
$ cd /tmp/test
$ /tmp/dirhardlink dir1 subdir/dir2
$ ls -lasdi dir1 subdir/dir2
3298482 0 drwxr-xr-x 2 johndoe wheel 68 Nov 10 10:47 dir1
3298482 0 drwxr-xr-x 2 johndoe wheel 68 Nov 10 10:47 subdir/dir2
$ echo Hello > dir1/file
$ cat subdir/dir2/file
Hello
Everything looks in order. Let us now use fileXray to see what actually hap-
pened inside the file system. We looked at dir1’s on-disk details earlier. We can
now see what has changed after we created a directory hard link to dir1. The
next page shows the result.
We see that dir1’s transformation is even more drastic than what we had ob-
served in the case of file hard links. After we created a directory hard link to
dir1, it is not longer a directory on disk. In fact, the “real” directory—the link
target—has moved to a special folder called .HFS Private Directory Da-
ta\xd, just as the link target of a file hard link had moved to a (different) spe-
cial folder. The link target’s name within the special folder is dir_3298482,
where the number represents the original CNID of dir1. However, dir1 has not
99
introspect
$ sudo fileXray dir1
path = MacHD:/private/tmp/test/dir1
…
# Catalog File Record
# Record 28 in node 63018 beginning at 512-byte sector 0x4324d8
type = file (alias, directory hard link)
indirect node CNID = 3298482
indirect folder = MacHD:/.HFS+ Private Directory Data\x000d/dir_3298482
file ID = 3298603
flags = 0000000000100010
. File has a thread record in the catalog.
. File has hardlink chain.
…
# BSD Info
ownerID = 3298604 (previous link ID)
groupID = 0 (next link ID)
adminFlags = 00000000
ownerFlags = 00000010
. UF_IMMUTABLE (file may not be changed)
fileMode = -r--r--r--
iNodeNum = 3298482 (link reference number)
textEncoding = 0
reserved2 = 0
# Finder Info
fdType = 0x66647270 (fdrp)
fdCreator = 0x4d414353 (MACS)
fdFlags = 1000000000000000
. kIsAlias
…
# Data Fork
logicalSize = 0 bytes
# Resource Fork
logicalSize = 464 bytes
totalBlocks = 1
fork temperature = no record in Hot File B-Tree
clumpSize = 0
extents = startBlock blockCount % of file
been replaced by another directory that “points to” the link target—it has been
replaced by a file, or specifically, an alias file. The immutable alias file has
fdrp and MACS as its type and creator codes, respectively. It also has a re-
source fork. Moreover, we see that as in the case of file hard links, there exists
a hard link chain.
100
introspect
Let us also examine the link target. Its path would be “hard” to type because of
the \xd character in the special folder’s name. We can use the link target’s
CNID instead, which would be the original CNID of dir1. (It also shows up as
the link reference number in dir1’s details.)
…
# BSD Info
ownerID = 501 (johndoe)
groupID = 0 (wheel)
adminFlags = 00000000
ownerFlags = 00000000
fileMode = drwxr-xr-x
linkCount = 2
…
# Attributes
# Attribute Key
keyLength = 72
pad = 0
fileID = 3298482
startBlock = 0
attrNameLen = 30
attrName = com.apple.system.hfs.firstlink
# Attribute Data Record (Inline)
# Record 6 in node 15032 beginning at 512-byte sector 0x4e5b8
recordType = 0x10
reserved[0] = 0
reserved[1] = 0
attrSize = 8 bytes
attrData = 33 32 39 38 36 30 34 00
3 2 9 8 6 0 4
We see mostly what we would expect given our earlier observations on the im-
plementation details of file hard links. Note that the link target folder has an
extended attribute named com.apple.system.hfs.firstlink. The attribute’s
value is an encoding of the CNID of the head of the directory hard link chain.
101
introspect
Introspecting Symbolic Links
Symbolic links on HFS+ are implemented as regular file’s whose data fork con-
tent is the UTF-8-encoded pathname—either relative or absolute, as set at link
creation time—to the link’s target. The file system also sets the creator and
type codes of symbolic links to special values: rhap and slnk, respectively. The
following is an example of examining a symbolic link with fileXray.
102
introspect
Note that the data fork, which contains only the UTF-8 encoded pathname to
the link target, has the expected size. We can verify its contents by using the
--read option to dump the data fork to the standard output.
See Also
• --cnid CNID
• --fsspec PARENT_CNID:NAME
• --path PATH
103
-j --journal
--journal
The summary information includes the contents of the Journal Info Block and
the Journal Header.
104
--journal
$ sudo fileXray --device /dev/disk0s2 --journal --exhaustive
# HFS+ Journal
# Journal Buffer Number of valid blocks
…
# begin transaction
# Block List Header Bytes used in this transaction buffer
max_blocks = 2047
num_blocks = 14
bytes_used = 127488 Block Node
= 0x14c4f323 Owner Type
checksum
flags = 0x3
. check checksums File Allocation B-Tree Node
. first header Block Number Number
binfo[0].sequence_num = 0xb41509
block_info[ 1] { bnum 2c28 A , bsize 4096 bytes, bp 9f3e6db9 }
block_info[ 2] { bnum 48b828 Cl, bsize 8192 bytes, bp 97486d27 }
vabn 91705 , fabn 29ebe (btree node 85855)
block_info[ 3] { bnum 3ee778 Cl, bsize 8192 bytes, bp a14d9276 }
vabn 7dcef , fabn 164a8 (btree node 45652)
block_info[ 4] { bnum 33c238 Ch, bsize 8192 bytes, bp 6fb1adf }
vabn Volume 67847 , fabn 0 (btree node 0)
block_info[ 5] { bnum Allocation 3a7c48 Cl, bsize 8192 bytes, bp 6d9bea0a }
vabn Block 74f89 , fabn d742 (btree node 27553)
block_info[ 6] { bnum Number 373e28 Cl, bsize 8192 bytes, bp 85c76441 }
vabn 6e7c5 , fabn 6f7e (btree node 14271)
block_info[ 7] { bnum 4a628 Xl, bsize 8192 bytes, bp 31f2adb1 }
vabn 94c5 , fabn 385c3 (btree node 115425)
block_info[ 8] { bnum 13a38 Xh, bsize 8192 bytes, bp 924486d2 }
vabn 2747 , fabn 31845 (btree node 101410)
block_info[ 9] { bnum 2 V , bsize 512 bytes, bp c2d81893 }
block_info[ 10] { bnum 489f28 Cl, bsize 8192 bytes, bp 1d6aed5e }
vabn 913e5 , fabn 29b9e (btree node 85455)
block_info[ 11] { bnum 3ef118 Cl, bsize 8192 bytes, bp 72474d1a }
vabn 7de23 , fabn 165dc (btree node 45806)
block_info[ 12] { bnum 363d08 Cl, bsize 8192 bytes, bp 36a0159 }
vabn 6c7a1 , fabn 4f5a (btree node 10157)
block_info[ 13] { bnum 361538 Cl, bsize 8192 bytes, bp 776e4038 }
vabn 6c2a7 , fabn 4a60 (btree node 9520)
# end transaction
…
Summary: 376 blocks using 3311616 bytes in 17 block lists.
The column labeled as “Block Owner” identifies the file system object that owns
the block in question. The identifier is one of the following characters.
A Allocation File.
C Catalog B-Tree.
E Extents B-Tree.
V Volume Header.
105
--journal
If the block owner is a B-Tree, the adjacent column labeled as “Node Type”
identifies the type of the B-Tree node the block belongs to. The identifier is one
of the following characters.
f Free node.
h Header node.
i Index node.
l Leaf node.
m Map node.
In the case of a B-Tree, the line of output following each block_info line will
show the corresponding volume-level allocation block number, the file-level al-
location block number, and the B-Tree node number.
Caveats
For a real-life volume, the output generated in exhaustive mode can be quite
massive.
Moreover, even though you can use this option on a live, mounted volume, but
realize that the journal on a mounted volume—especially the root volume—is
highly volatile and is quite likely to change even as fileXray dissects it.
Moreover, when this option is used on a mounted volume with ongoing file sys-
tem activity, it is possible for fileXray to run into temporal inconsistencies,
and in some cases, even terminate ungracefully.
See Also
• --journal_names
• --scavenge
• --userfs_type scavenger
• --volume_header
106
-J --journal_names
--journal_names
Display file system object names that can be gleaned from dissecting a jour-
naled HFS+ volume’s journal.
Specifically, fileXray will read and analyze the journal, looking for file system
object names and associated metadata contained within the raw blocks found
in the journal. Once done, fileXray will display all types of Catalog records it
can piece together.
The information displayed by this option provides an idea of “recent” file sys-
tem activity that has occurred on the volume. In most non-contrived cases, the
definition of “recent” is the last time the journaled volume experienced file sys-
tem activity when mounted in read-write mode. The amount of historical activ-
ity that fileXray can glean also depends upon the size of the journal.
As is the case with all fileXray options, you can use this option on a live,
mounted volume, but realize that the journal on a mounted volume—especially
the root volume—is highly volatile and is quite likely to change even as
fileXray dissects it. Moreover, when this option is used on a mounted volume
with ongoing file system activity, it is possible for fileXray to run into tempo-
ral inconsistencies, and in some cases, even terminate ungracefully.
Record Difference File system Parent Object Object Literal Computed path of
type tag tags activity tag CNID CNID name colon object on volume
Let us examine the various parts of this output. In general, each line of output
will contain information on one of four types of Catalog records fileXray
found. The type is designated by each line’s first character, which can be one of
the following.
107
--journal_names
An important aspect to realize about the journal’s operation is that a raw jour-
nal block can contain several Catalog records that are there not because the
corresponding file system objects were modified, deleted, etc., but simply be-
cause the file system object resides in the same HFS+ block as one or more
other file system objects that were modified or deleted. When in doubt about
the reason for a name’s existence in the journal, the on-volume timestamps
should also be consulted. fileXray will make a “best effort” attempt at identi-
fying the type of activity that could have caused the record to be present in the
journal. fileXray will tag each line of output with up to four character tags
indicating some key “differences” it found between the journal and volume cop-
ies of a file system object’s metadata.
n Name differs.
Based on these differences, fileXray will also ascribe a high-level file system
activity tag to each line of output. The tag would be one of the following.
exists The object exists both on the volume and in the journal. It is
likely to be present in the journal because it happened to reside
in the same file system block as another object that was modi-
fied or deleted.
moved,renamed The object’s parent folder and its name have both changed.
recreated The object exists on the volume but with a CNID that is differ-
ent from what was found in the journal.
The remainder of each output line includes the parent CNID, the object CNID,
and the object name as it was found in the journal. Whenever possible,
fileXray also compute the path—as it exists, or as it was likely to have ex-
isted in the case of deleted objects—to the file system object in question. When
an object’s parent folder cannot be found, typically because it has been deleted,
fileXray may not compute the path. Often, the node name corresponding to
the deleted parent will also exist in the output of --journal_names.
108
--journal_names
When --journal_names is used along with the --exhaustive option,
fileXray will perform additional analysis on the records found in the journal.
In particular, it will examine the various pieces of metadata in any Catalog file
and folder records found in the journal and compare them with their counter-
parts—if they can be located—on the volume. In other words, fileXray will
create a “diff” between the journal’s view and the volume’s view of the file and
folder metadata that appears in journal transactions. The following excerpt is
an example.
In this excerpt, we see two folder records. The folder named 501 has had its
attribute modification date updated on the volume. The root folder has had 3
file system objects added to it. Its timestamps have also been updated. Note
that for a real-life volume, the output generated by --journal_names in ex-
haustive mode can be quite massive. Moreover, the caveat about using this op-
tion on a mounted volume applies even more strongly to the exhaustive mode.
See Also
• --exhaustive
• --journal
• --scavenge
• --undelete_cookie COOKIE
• --userfs_type scavenger
109
-l --list
--list
List a given folder’s contents. The folder must be specified using another option
such as --cnid, --fsspec, or --path.
The following is an example of listing the contents of the root folder on a stan-
dard boot volume.
The output format is somewhat similar to, but not the same as that of the long
output format of the ls command. Some noteworthy points are as follows.
• All files and folders are shown, including system objects that are fil-
tered out by the kernel.
• For files, both the data and resource fork sizes are shown.
• For hard links, both the link and the link target are shown.
• The third column (labeled “@+SUZ”) has zero or more character tags
with the following meanings.
110
--list
@ File or folder has one or more extended attributes. (Although Access Control Lists
are implemented as extended attributes, this tag does not take Access Control Lists
into account.)
+ File or folder has an Access Control List. That is, the object has an extended attrib-
ute named com.apple.system.Security.
See Also
• --cnid CNID
• --fsspec PARENT_CNID:NAME
• --path PATH
111
-L RECORD_TYPE --list_records RECORD_TYPE
--list_records RECORD_TYPE
Specify a B-Tree record type to be listed from the leaf nodes of an HFS+ B-Tree.
The valid values for RECORD_TYPE depend on the B-Tree in question, which in
turn must be specified using the --btree option. RECORD_TYPE can be one of
the following.
hfcthread Matches Hot File Thread records in the Hot Files B-Tree.
The record type none is a special case. If it is specified, fileXray will display
summary information on each node in the given B-Tree without displaying any
records. The following is an example.
Additionally, the --node option can be used along with this option to specify a
particular node in an HFS+ B-Tree. In this case, RECORD_TYPE must be any.
fileXray will then list all records residing in that particular node. The exam-
ple on the following page shows listing the records in node number 1 of the
Catalog B-Tree of a test volume.
See Also
• --btree BTREE_NAME
• --node NODE
112
--list_records RECORD_TYPE
113
--monitor
--monitor
When you use Mac OS X, you frequently access files and folders. Several of
these accesses result in the file system being modified. Developers, power us-
ers, and even “regular” users who are curious would be interested in observing
and understanding file system changes. The motivation might be for security
reasons, for analyzing software, for troubleshooting, or just out of curiosity.
fileXray has a built-in monitor that uses the operating system’s fsevents
mechanism to report file system modifications in real time. This feature is
available for use on all types of volumes—it is not limited to HFS+ volumes.
While running, the monitor will block, waiting for file system modifications to
occur. As the monitor gets notified by the kernel of file system activity, it dis-
plays a log of the activity on the standard output. To terminate the monitoring,
type control-C in the Terminal window that the monitor is running in.
The following shows an excerpt from the monitor’s output, which has been re-
formatted to fit this page.
114
--monitor
You can additionally specify the --exhaustive option, which will cause the
monitor to produce more verbose output. The verbose output format is the
same as that of the freely available fslogger1 program. The following is an ex-
ample of the monitor running in verbose mode.
Note that although the monitor built into fileXray is similar to fslogger, it
has more features such as:
See Also
• --exhaustive
• --monitor_exclude VOLUME
• --monitor_include VOLUME
• --monitor_logfile LOGFILE
1 http://osxbook.com/software/fslogger/
115
--monitor_exclude VOLUME
--monitor_exclude VOLUME
Exclude (that is, do not monitor) the mounted volume specified by VOLUME,
which can either be the mount point of the volume in question or the path to a
file or folder within it. This option is used along with the --monitor option.
See Also
• --monitor
• --monitor_include VOLUME
• --monitor_logfile LOGFILE
116
--monitor_include VOLUME
--monitor_include VOLUME
Include (that is, do monitor) the mounted volume specified by VOLUME, which
can either be the mount point of the volume in question or the path to a file or
folder within it. This option is used along with the --monitor option.
See Also
• --monitor
• --monitor_exclude VOLUME
• --monitor_logfile LOGFILE
117
--monitor_logfile LOGFILE
--monitor_logfile LOGFILE
Specify the path (LOGFILE) to a file into which the built-in file system modifica-
tion monitor will log its output.
The monitor filters out modifications to the log file itself, which prevents an in-
finite stream of output from being generated. The monitor must be run in suc-
cinct mode for it to log its output to a file—that is, the --exhaustive option
must not be specified.
• The file must not already exist. fileXray will not clobber an existing
file.
• The path must not resolve to a file-backed disk image. fileXray will
not log to a file that resides on such a disk image.
See Also
• --monitor
• --monitor_exclude VOLUME
• --monitor_include VOLUME
118
-m --mount_data
--mount_data
The mount data contains several pieces of information useful for analysis and
debugging. For example:
• The next unused Catalog Node ID (CNID), which gives an indication of
the CNID the kernel is likely to use for the next newly created file sys-
tem object on the volume.
• The allocation block number where the kernel will start its search for
a free block the next time it needs needs a block.
• Information on the states of journaling and Hot File Clustering.
• The maximum size for extended attributes that are stored inline.
• Limits that trigger low disk space notifications.
The following pages show an example of viewing the root volume’s mount data.
# Volume Flags
flags bitmap (32 bits) = 00000000000000000000000010001100
+ HFS_WRITEABLE_MEDIA
+ HFS_CLEANED_ORPHANS
+ HFS_METADATA_ZONE
# Physical Description
logical block size of disk = 512
logical block count on disk = 0x1d121920
alternate volume header location = 0x1d12191e
physical block size of disk = 512
logical blocks per physical block = 1
continued…
119
--mount_data
…
# Journaling
journal for this volume = 0x700af00
vnode for journal device = 0x7003f38
start block of journal = 0x747
journal size = 25165824
journal file ID = 16
journal info block file ID = 17
# Notification Variables
notification conditions bits = 00000000000000000000000000000000
freespace danger limit = 32000
freespace warning limit = 64000
freespace desired limit = 96000
# Metadata Zone
metadata zone start block = 0x1
metadata zone end block = 0xd7fff
hotfile start block = 0xb69c3
hotfile end block = 0xd7fff
minimum allocation start = 0xd8000
freed block count = 0x451a8
hotfile free blocks = 0x1ff75
hotfile maximum blocks = 0x2163d
overflow maximum blocks = 0
catalog maximum blocks = 0x2c7b
# Sparse device
root vnode for backing fs = 0 (not applicable)
sparse disk image band size = 0 (not applicable)
backing fs last statfs = 0 (not applicable)
backing fs max blocks = 0 (not applicable)
# Syncing/Freezing/Downgrading
sync scheduled = 0
sync incomplete = 0
last sync request time = 0
last sync time = 1256963668634704
active threads = 0
maximum pending I/O = 0
freezing process = 0
downgrading process = 0
continued…
120
--mount_data
…
# Default Values for HFS Standard / Non-Init Access
default owner = { uid=99, gid=99 }
directory protection bits mask = 755
file protection bits mask = 755
default encoding for non-HFS+ volumes = 0
# Miscellaneous
disk block where HFS+ starts = 0
volume bitmap I/O size = 4096
free block reserve = 64000
blocks on loan for delayed allocations = 0
cache of largest known free extents = 10 extents
# Times
last mounted time = 2009 Nov 10 14:57:49
last mounted modification time = 2009 Nov 10 14:56:26
last modification time = 2009 Nov 14 21:34:28
file system creation time = 2009 Nov 2 18:56:59
file system creaation time (local) = 2009 Nov 2 11:56:59
metadata create time = 2009 Nov 2 18:56:59
file system last backup time =
continued…
121
--mount_data
…
# Resize Variables
resize files moved = 0
resize total files = 0
# Other
maximum inline attribute size = 3802
Retrieving the mount data from the kernel requires superuser privileges.
Therefore, to use this option for any mounted HFS+ volume, fileXray must be
run with superuser privileges.
See Also
• --enable_xattr_extents
• --next_allocation BLOCK
• --volume VOLUME_PATH
122
-N BLOCK --next_allocation BLOCK
--next_allocation BLOCK
Given a mounted HFS+ volume, suggest to the kernel to begin its next search
for a free allocation block at allocation block number BLOCK.
A mounted volume must also be specified using the --volume option, which
requires either the mount point of the volume or the path to a file system object
on the volume as an argument. When used with this option, --volume has a
special case: if you wish to change the next allocation block on the root volume,
you must explicitly use “/” as the argument to --volume. Since --next_allo-
cation alters block allocation, its use on the root volume requires explicit
specification.
#! /usr/bin/perl -w
# mkfragmented.pl: Create a file with N fragments (extents) on a given volume.
my $volume = $ARGV[0];
my @sb = stat($volume);
((-d $volume) && @sb) or usage();
my $needextents = int($ARGV[1]);
my $file = "$volume/fragmented.$$";
(! -e $file) or die "$0: file $file already exists\n";
`/bin/echo -n $FOUR_KB > "$file"`; # create a file
(-e "$file") or die "$0: failed to create file ($file)\n";
WHILE_LOOP:
while (1) {
`/bin/sync`;
my @out = `$FILEXRAY "$file" | grep -B 2 'allocation blocks'`;
$out[0] =~ /^\s+([^\s]+)\s+([^\s]+)..*$/;
my $lastStartBlock = $1; # starting block of the file's last extent
my $lastBlockCount = $2; # number of blocks in the last extent
$out[2] =~ /[\s*\d+] allocation blocks in (\d+) extents total.*/;
my $curextents = int($1); # number of extents the file currently has
if ($curextents >= $needextents) { # do we already have the needed extents?
print "\ncreated $file with $curextents extents\n";
last WHILE_LOOP;
}
# set volume's next allocation pointer to the block right after our file
my $conflict = sprintf("0x%x", hex($lastStartBlock) + hex($lastBlockCount));
`sudo $FILEXRAY --next_allocation $conflict --volume $volume`;
exit(0);
123
--next_allocation BLOCK
The following is an example of using the mkfragmented.pl script to create a
file with 9 fragments. Since we are merely experimenting, we will use a test
volume (say, as opposed to the root volume) for this. Note that the script as-
sumes that fileXray is in your shell’s PATH.
$ fileXray /Volumes/test/fragmented.13171
…
extents = startBlock blockCount % of file
$ fileXray /Volumes/test/fragmented.13171
…
extents = startBlock blockCount % of file
124
--next_allocation BLOCK
Caveats
The --next_allocation option works by setting the value of the roving next-
allocation pointer in the kernel through a system call. The pointer is maintained
by the kernel as a hint for itself—the kernel is likely to use the hint as a start-
ing point while searching for a free allocation block in most cases, but in some
cases it might not. Therefore, the success of the --next_allocation operation
ultimately depends upon whether the kernel honors the hint or not.
See Also
• --mount_data
• --volume VOLUME_PATH
125
-n NODE --node NODE
--node NODE
Specify a node in an HFS+ B-Tree. NODE is a node number. The number of the
first node in an HFS+ B-Tree is 0.
This option is used along with the --btree option to examine a specific node in
an HFS+ B-Tree. Additionally, the --exhaustive and --list_records options
allow you to introspect a node more deeply by displaying its constituent re-
cords, free space, and other bookkeeping information.
The --btree and --list_records sections provide examples that involve us-
ing the --node option.
See Also
• --btree BTREE_NAME
• --list_records RECORD_TYPE
126
--noidmap
--noidmap
A global option that tells fileXray not to map user and group identifiers to
user and group names, respectively. Moreover, user and group UUIDs will also
not be mapped to their respective user and group identifiers, respectively, and
will be displayed as is.
$ touch /tmp/testfile.txt
$ chmod +a 'johndoe allow write' /tmp/testfile.txt
$ chmod +a 'everyone allow read' /tmp/testfile.txt
1 Even when the mapping is enabled, fileXray displays numerical identifiers in addition to
resolved names.
127
--noidmap
In this example, we create a file and set two access control entries on it: one
applies to a specific username and the other applies to “everyone.” We see that
fileXray maps the well-known UUIDs to “everyone” and displays it as $eve-
ryone. fileXray will display special or well-known mappings with a $ prefix.
It maps the user UUID in the second access control entry to a username and
user ID, both of which are valid in the context of the current environment.
(Note that the user, or in other cases a group, could be hosted on a Primary
Domain Controller or an Active Directory Server.) Specifying the --noidmap
option in this case will cause the user UUID to not be mapped as shown below.
128
-o OUTPUT_FILE --output OUTPUT_FILE
--output OUTPUT_FILE
The --output option is used along with other options that read data from a
given volume and save it. This includes the following options.
--read Read the given component from the given file system object.
Note that as a matter of policy, fileXray will not overwrite an existing file.
Therefore, OUTPUT_FILE must not already exist. There is a special case, how-
ever. If OUTPUT_FILE is one of the strings -, /dev/stdout, or /dev/fd/1, the
retrieved data is sent to the standard output instead of being saved to a file.
See Also
• --block BLOCK
• --read COMPONENT
• --scavenge
• --uncompress
• --undelete_cookie COOKIE
129
-e START[,SIZE] --partition START[,SIZE]
--partition START[,SIZE]
Specify the start offset in bytes (START) and optionally the size in bytes (SIZE)
of the target HFS+ volume. The start offset is relative to the beginning of the
device fileXray is targeted at. The device is specified through the --device
option.
However, a GUID Partition Table was detected on the given device with the
following HFS+ partition table entries:
See Also
• --device DEVICE
130
-p PATH --path PATH
--path PATH
Specify a file system object through its absolute POSIX path (PATH), which
must be provided as a UTF-8 string. The --path option is the canonical way to
specify a file system object to fileXray.
It is necessary to use this option when you wish to examine file system objects
by path on offline (that is, not mounted) volumes. On mounted volumes, it suf-
fices to simply point fileXray to the file system object of interest, which im-
plicitly specifies both the path of the object of interest and the volume it resides
on. For example:
$ cd
$ pwd
/Users/johndoe
$ sudo fileXray Library/Safari/Bookmarks.plist
…
The explicit way to specify the same file to fileXray would be to use the
--path option with the file’s absolute path as the argument as follows.
The explicit --path form is “purer” because in this mode, fileXray itself
parses and looks up each path component on the volume—whether the volume
is mounted or not. Besides being purer, this form is also more sophisticated
and gives you more control over how any symbolic links, hard links, and direc-
tory hard links in the given path are resolved.
There are some important points to note about how fileXray processes the
argument to --path.
Dot-Dot
If a “..” appears in the path, fileXray will ensure that the component that it
is “going back” from is indeed a folder.
131
--path PATH
Link Resolution
Terminal Slash
If the specified path has a terminal slash, fileXray will verify that the file
system object is a folder. If the object happens to be a directory hard link or a
symbolic link, fileXray will resolve it in this case. The following examples il-
lustrate this rule.
HFS+ supports file system object names up to 255 “characters” in length. More
specifically, a file or folder name can be up to 255 Unicode characters, each of
which consumes 16 bits on disk. The Unicode string representing a name is
stored in fully decomposed form on disk, with composing characters stored in
canonical order. When an HFS+ node name is transferred between the kernel
and user spaces, it is encoded as ASCII-compatible UTF-8 bytes. Now, the
Unix-style file system layers in Mac OS X—both within the BSD portion of the
132
--path PATH
kernel and the user-space C library—place a limit of 255 bytes for file and
folder names. In other words, the UTF-8 representation must also fit in 255
bytes. This easily leads to a problem because there are Unicode characters that
require multiple bytes when encoded as UTF-8. Consider a valid HFS+ name
that consists of the Unicode character ‰ (U+2030) repeated 255 times. The
UTF-8 representation requires 765 bytes. Mac OS X handles the problem by
“mangling” or shortening such names and encoding the Catalog Node ID (CNID)
within the shortened name. fileXray performs the same shortening/encoding
within itself when dealing with such names.
In the following example, the 765 byte UTF-8 string is shortened to a 255 byte
UTF-8 string. The shortened version incorporates the hexadecimal representa-
tion of the file’s CNID.
$ cd /tmp
$ touch `perl -e 'print "‰"x255;'`
$ ls -li
3288816 -rw-r--r-- 1 singh staff 0 Nov 10 01:33 ‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰\
‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰‰#322EF0
See Also
• --cnid CNID
• --fsspec PARENT_CNID:NAME
133
-r COMPONENT --read COMPONENT
--read COMPONENT
Read and save all bytes of the given component of a given file system object.
The file system object of interest must be specified through other options such
as --cnid, --fsspec, and --path. The data read needs to be saved to a desti-
nation file, which must be specified through the --output option.
By default, the --read option will copy only the logical bytes of a data or re-
source fork. That is, if the fork’s size is not a multiple of the volume’s allocation
block size, the last allocation block used by the file system object will be par-
tially copied. To copy the last allocation block in its entirety, you can addition-
ally specify the --exhaustive option.
See Also
• --cnid CNID
• --exhaustive
• --fsspec PARENT_CNID:NAME
• --output OUTPUT_FILE
• --path PATH
• --uncompress
134
-R --readonly
--readonly
Unless you know exactly what you are doing, it is not advisable to use this op-
tion on the root volume or on a volume that has files open for writing.
See Also
• --device DEVICE
• --volume VOLUME_NAME
135
-k --scavenge
--scavenge
Analyze a journaled HFS+ volume and scavenge for deleted files and folders.
Optionally, examine a specific deleted file in detail and if possible, recover it.
By itself, the --scavenge option will display a “succinct” list of any file, folder,
and thread records of deleted objects that fileXray finds on the volume. Each
line of the output contains comma-separated values whose meanings are la-
beled in the following example.
In general, each line of output will contain information on one of four types of
Catalog records fileXray found. The type is designated by each line’s first
comma-separated value: a single character whose value can be one of the fol-
lowing.
The next comma-separated value is a pair of Catalog Node IDs (CNIDs): the
parent folder’s CNID and the object’s own CNID. The two CNIDs are separated
by a literal slash.
The next three comma-separated values apply only to file records—no values
are shown for other record types.
136
--scavenge
The third comma-separated value is an “undelete cookie.” fileXray will often
find multiple remnant records for a single deleted object. This is a side effect of
how HFS+ is implemented and how the journaling mechanism works. For all
file records, an opaque value—the undelete cookie—will be displayed for each
record. The undelete cookie, which uniquely identifies an instance of a deleted
file, is required if you wish to use --scavenge to further examine that specific
deleted instance or to recover it. Note that the undelete cookie is a volatile en-
tity. If the volume undergoes file system activity, a previously displayed cookie
may no longer be valid.
The fifth and sixth comma-separated values are triplets of block number values
in the case of file records. The individual blocks numbers are separated by lit-
eral slashes. The triplets apply to the data fork and the resource fork, respec-
tively. The first value in the triplet is the total number of allocation blocks the
fork had—that is, the logical size of the fork. The second value is the number of
allocation blocks that can be determined from the file record itself without go-
ing to the Overflow Extents B-Tree. (Since the --scavenge option does not cur-
rently scavenge overflow extents, this second value is the maximum number of
blocks that could be recovered from a deleted file.) The third value, which is
less than or equal to the second value, represents the number of fork blocks
that are currently known to be free and not be in use by another file. Therefore,
the best case for recovery is when all three values in a triplet are identical.
However, it is important to realize that even if a file’s erstwhile blocks are cur-
rently free, they could have been reused and freed any number of times be-
tween now and the time the file was deleted.
The sixth comma-separated value contains the name and possibly the path of
the file system object. The name, which will always be displayed, is followed by
a literal colon. (An on-disk HFS+ node name cannot contain a colon.) The re-
mainder of the line after the colon is the full path—as much as fileXray can
compute—of the file system object. (It may not be possible to compute the path
in several cases.) In some cases, as in the example being discussed here, a
path component, such as a parent folder of a deleted object, may also have
been deleted. Such objects are represented as [CNID=<cnid>] in the path. The
deleted parent may or may not be present in the --scavenge output depending
on the journal’s state. In the above example, the parent folder of the three de-
leted files is represented as [CNID=24]. We see that there is a deleted folder
with CNID 24: /Pictures.
137
--scavenge
$ fileXray --device /dev/disk1s2 --scavenge --exhaustive
…
# Scavenging a Catalog File Record.
path (synthesized) = [CNID=24]/Water
name = Water.jpg
parentID = 24
fileID = 148
undelete cookie = 0x51eb4
scavengability (data)= 146/146/146
scavengability (rsrc)= 0/0/0
# Catalog File Record Details
type = file
file ID = 148
flags = 0000000000000010
. File has a thread record in the catalog.
reserved1 = 0
createDate = Sun Nov 8 20:53:22 2009
contentModDate = Sun Nov 8 20:53:22 2009
attributeModDate = Sun Nov 8 20:53:22 2009
accessDate = Sun Nov 8 20:53:22 2009
backupDate = 0
# BSD Info
ownerID = 501 (johndoe)
groupID = 20 (staff)
adminFlags = 00000000
ownerFlags = 00000000
fileMode = -rw-r--r--
linkCount = 1
textEncoding = 0
reserved2 = 0
# Finder Info
fdType = 0x4a504547 (JPEG)
fdCreator = 0x3842494d (8BIM)
fdFlags = 0000000001000000
. kIsShared
fdLocation = (v = 0, h = 0)
opaque = 0
# Data Fork
logicalSize = 597757 bytes
totalBlocks = 146
extents = startBlock blockCount % of file
0x1525b 0x92 100.00 %
# Resource Fork
logicalSize = 0 bytes
…
Note that on an active volume—one that is mounted, and especially the root
volume—the journal is very volatile can wrap around rather quickly, overwrit-
ing data that this option operates upon. Therefore, on a mounted volume, the
information displayed by any option that processes the journal is volatile too,
both with and without the --exhaustive option.
From amongst the deleted file instances that are listed by --scavenge, you can
introspect a particular instance by specifying the file’s CNID through the
138
--scavenge
--cnid option and the associated undelete cookie through the --undele-
te_cookie option.
*** None of the deleted file's data fork blocks are CURRENTLY in use by
other files, although they could have been reused and freed in the past.
# Resource Fork
logicalSize = 0 bytes
In the above example, we see that none of the deleted file’s data fork blocks are
currently in use by other files. This is highly desirable if we wish to recover the
deleted content. However, as noted earlier, the blocks could have been reused
and freed—perhaps even multiple times. Therefore, although desirable, this
still does not guarantee us that we will, in fact, be able to recover the deleted
content.
139
--scavenge
Moreover, depending on a multitude of factors such as the size of the volume,
the amount of free space it has, the amount and the type of file system activity
that occurred on the volume after the file in question was deleted, and so on,
we may find that some or perhaps even all of the original blocks are currently
in use by other files, and therefore, almost certainly “lost.” The following exam-
ple shows a case where almost all of a deleted file’s blocks have been clobbered.
Note that fileXray identifies the clobbered blocks.
*** AT LEAST 252 of the deleted file's 258 data fork blocks have been
reused since the file was deleted.
# Resource Fork
logicalSize = 0 bytes
140
--scavenge
By default, fileXray deals with known clobbered blocks by substituting them
with zero-filled blocks. That is, if a block that once belonged to the deleted file
is known to currently be in use, fileXray will replace that block’s contents
with zeros in the output file. You can override this behavior using the --ex-
haustive option, in which case fileXray will recover all blocks, including
clobbered ones, as is.
We will use two volumes for this example: a non-root volume mounted at
/Volumes/PreciousHD and the root volume. It is not recommended to recover
from and to the same volume because we would want to perturb the “from”
volume as little as possible—ideally not perturb it at all. Consider the following
sequence of operations.
# Use the --scavenge option and see if our deleted file shows up in its output.
$ fileXray --volume /Volumes/PreciousHD --scavenge
…
f,2/217,0xe0164,4559/4559/4559,0/0/0,mach_kernel:TestHD:/mach_kernel
t,2/217,,,,mach_kernel:TestHD:/mach_kernel
…
We create a new file on the PreciousHD volume and then “accidentally” delete
it. We immediately use fileXray to examine the volume using --scavenge. In
this case, the recently deleted file is locatable—both a file record and a file
thread record are listed. We also see that all of the file’s 4559 data blocks are
addressable. Moreover, none of those blocks are currently allocated to other
files.
Let us now examine the deleted record in more detail. To do so, we will add the
--cnid and --undelete_cookie options to the previous command line we
used.
141
--scavenge
# Examine the killed record for the file of interest in more detail.
$ fileXray --volume /Volumes/PreciousHD --scavenge --cnid 217 \
--undelete_cookie 0xe0164
path (synthesized) = TestHD:/mach_kernel
name = mach_kernel
parentID = 2
fileID = 217
undelete cookie = 0xe0164
# Catalog File Record Details
type = file
file ID = 217
flags = 0000000000000010
. File has a thread record in the catalog.
reserved1 = 0
createDate = Mon Nov 9 14:51:49 2009
contentModDate = Mon Nov 9 14:51:50 2009
attributeModDate = Mon Nov 9 14:51:50 2009
accessDate = Mon Nov 9 14:51:49 2009
backupDate = 0
# BSD Info
ownerID = 501 (johndoe)
groupID = 20 (staff)
adminFlags = 00000000
ownerFlags = 00000000
fileMode = -rw-r--r--
linkCount = 1
textEncoding = 0
reserved2 = 0
# Finder Info
fdType = 0
fdCreator = 0
fdFlags = 0100000000000000
. kIsInvisible
fdLocation = (v = 0, h = 0)
opaque = 0
# Data Fork
logicalSize = 18672224 bytes
totalBlocks = 4559
extents = startBlock blockCount % of file
0x18764 0x11cf 100.00 %
*** None of the deleted file's data fork blocks are CURRENTLY in use by
other files, although they could have been reused and freed in the past.
# Resource Fork
logicalSize = 0 bytes
The situation looks promising. Let us now add the --output option to recover
the deleted blocks from PreciousHD and copy them to the root volume.
# Compare the recovered content with the original content we started with.
$ shasum /mach_kernel /tmp/mach_kernel
c8a709cf54f5847974c09a376f592950193f0540 /mach_kernel
c8a709cf54f5847974c09a376f592950193f0540 /tmp/mach_kernel
142
--scavenge
Caveats
The volume from which you are attempting to recover should be kept as dor-
mant as possible in terms of file system activity. Ideally, no file system activity
should occur on the volume after the file in question is deleted.
See Also
• --cnid CNID
• --exhaustive
• --journal_names
• --trawl QUERY
• --undelete_cookie COOKIE
143
-s FORK_TYPE --summary FORK_TYPE
--summary FORK_TYPE
any Summary will have information on the largest (data + resource) forks.
The FORK_TYPE specification comes into play when the --top option is used to
specify the number of the largest fork sizes that the --summary computation
will remember. If the --top option is not specified, FORK_TYPE has no user-
visible effect.
If a number N is specified through the --top option, then the summary infor-
mation displayed will include a list of the top N largest fork sizes found on the
volume. In other words, you can use the --summary and --top options to-
gether to display the N largest files (by data fork size, resource fork size, or
combined fork sizes) on the volume.
The following excerpt shows the use of the --summary option to identify the
largest data and resource forks on a volume.
The example on the following page shows the entire output of --summary on a
root volume. We have also specified --top to list the top 10 largest files on the
volume. The paths in the illustration have been shortened to fit the page.
See Also
• --fragmentation FORK_TYPE
• --top N
144
--summary FORK_TYPE
47154 files have content in both their data and resource forks.
# The 10 largest files (sum of data and resource forks) on the Volume
rank size cnid path
10 2.1 GB 1743913 MacHD:/…Mac OS X 10.6 Server-s004.vmdk
9 2.1 GB 674452 MacHD:/…Virtual Disk-s002.vmdk
8 2.1 GB 1743911 MacHD:/…Mac OS X 10.6 Server-s002.vmdk
7 2.1 GB 674019 MacHD:/…Mac OS X 10.5-s008.vmdk
6 3.2 GB 684630 MacHD:/OPENSTEP-flat.vmdk
5 4.3 GB 205545 MacHD:/private/var/vm/sleepimage
4 4.5 GB 2614539 MacHD:/private/tmp/2009-11-02-www.tar.bz2
3 4.6 GB 2616395 MacHD:/private/tmp/2009-11-14-www.tar.bz2
2 8.6 GB 702033 MacHD:/…Windows 2000 Professional-flat.vmdk
1 12 GB 650957 MacHD:/…Mac OS X 10.4-flat.dmg
145
-t N --top N
--top N
When used with another fileXray option, specifies the number N to be used
for the top N files to be displayed in the context-specific categories.
--fragmentation Shows the top N most fragmented files by virtue of the fragmentation
of their data forks and/or resource forks. Whether only forks of one
type are considered depends on the argument to --fragmentation.
--hotfiles Shows the top N “hottest” files on the volume provided the volume
uses Hot File Clustering.
--summary Shows the top N largest files by virtue of the sizes of their data forks,
resource forks, or the sums of both forks depending on the argument
to --summary.
See Also
• --fragmentation FORK_TYPE
• --hotfiles
• --summary FORK_TYPE
146
-q QUERY --trawl QUERY
--trawl QUERY
Trawl the volume looking for blocks that match “magic” patterns (signatures)
contained in the query file QUERY.
This option uses the same “magic” mechanism that underlies the file com-
mand. (See magic(5) for an introduction. The /usr/share/file/magic/ di-
rectory on Mac OS X contains numerous magic pattern files.)
By default, when this option is specified, fileXray will scan the free extents of
the given volume one allocation block at a time. It will use the magic pattern(s)
from the QUERY file to match against each block. If the pattern matches a
block, fileXray will print the block’s byte offset on the volume along with a
description of the specific pattern it matched.
This way, you can trawl the volume looking for, say, PDF documents or JPEG
images. You can use any of the pattern files found in /usr/share/file/
magic/, which cumulatively contain patterns to identify a very large number of
file types. You can also concatenate two or more pattern files to provide a larger
pattern set. Moreover, you can create your own patterns as long as they use
the format described in magic(5). In the following example, the match indi-
cates that byte offset 0x3ad000 on the volume marks the beginning of a PDF
document.
The most convenient way to make use of trawling results is through the built-
in Arbitrary File System, which allows you to access arbitrary byte ranges on
the volume as on-the-fly files.
By default, fileXray will trawl only the free blocks on the volume. That is, the
--trawl operation searches free space, some or all of which may have been oc-
cupied by files now deleted, for patterns. To make --trawl search the entire
volume, including currently used blocks, additionally specify the --exhaus-
tive option.
147
--trawl QUERY
tent within a file, you can use the --block option to specify a smaller “stride”
size, which will cause fileXray to attempt pattern matching against smaller
blocks. Consider a contrived example. Suppose you are looking for a PDF file
embedded at a 512-byte offset within some container document. That is, the
PDF file starts at an offset of 512 bytes within the on-disk file. In this case,
--trawl would not find such a PDF because by default, it would attempt pat-
tern matching with a stride size that’s the same as the volume’s allocation
block size, which in turn is 4096 bytes by default. We can use the --block op-
tion to specify a stride size of 512 bytes, which would cause --trawl to exam-
ine the volume in units of 512 bytes 1.
Let us consider another example. Suppose we wish to look for pictures in some
common image file formats—GIF, JPEG, PNG, TIFF, etc.—within the free blocks
of a volume. The standard pattern file /usr/share/file/magic/images con-
tains several predefined patterns to suit our need. We can combine that pattern
file with another standard file /usr/share/file/magic/jpeg to get a bigger
pattern set. The following example shows how to use --trawl to perform the
appropriate search.
We see several matches in the output. (Note that it is entirely possible to get
false positives if some random content simply happens to match a pattern.) As
noted earlier, the easiest and nicest way of accessing these results is to use the
Arbitrary File System. Once mounted, the Arbitrary File System allows you to
create virtual file names on the fly wherein the file’s byte offset and size are en-
coded in the name itself. Moreover, these virtual file names can have arbitrary
file extensions. For example, when a file called 0x1000,65536.gif is accessed
in an Arbitrary File System mount, the file’s content will start at byte offset
1This means the trawling operation would examine 8 times more data than the default case.
Naturally, the operation would be slower.
148
--trawl QUERY
0x1000 on the volume, the content’s size will be 65536 bytes, and the .gif
extension will allow it to be conveniently opened in an image viewer.
# Now access trawling results “directly” using the Arbitrary File System.
Caveats
149
--trawl QUERY
See Also
• --block BLOCK
• --scavenge
• --userfs_type arbitrary
150
-z --uncompress
--uncompress
Used along with the --read option to tell fileXray to transparently uncom-
press the output when reading a component that is compressed on disk.
$ ls -las /etc/smb.conf.template
0 -rw-r--r-- 1 root wheel 2955 May 21 22:06 /etc/smb.conf.template
151
--uncompress
We see that even though the operating system reports the file as being 2955
bytes in size, the file actually has zero-sized data and resource forks on disk.
The file’s real content, which is compressed, is stored inline within an extended
attributed named com.apple.decmpfs. fileXray displays the details of the
extended attribute. Using the --read option, we can retrieve the content of this
extended attribute and save it to a file.
We see that the retrieved content’s size does not match the file’s advertised size.
We can now tell fileXray to also uncompress the content as it retrieves it.
Again, we can use --uncompressed along with --read to retrieve the com-
pressed content—this time from the resource fork—and save it uncompressed
to a file.
See Also
• --read COMPONENT
152
-u COOKIE --undelete_cookie COOKIE
--undelete_cookie COOKIE
The --scavenge option, which can be used to search for deleted file system
objects on a volume, will often find multiple remnants for a single deleted ob-
ject. This is a side effect of how HFS+ is implemented and how the journaling
mechanism works. When such objects are listed by --scavenge (in either suc-
cinct mode or exhaustive mode of output), an opaque value, which fileXray
refers to as an “undelete cookie,” will also be displayed alongside each object.
The following excerpts give examples of these output formats.
Subsequently, you can use the --scavenge option to further examine a given
deleted file in more detail by specifying the object’s Catalog Node ID (CNID).
Moreover, you can use --scavenge to “undelete” a deleted file if its blocks are
recoverable. Both of these operations (further examination and block recovery)
require the target file system object to be specified through the --cnid option.
Given that multiple instances of a deleted CNID can be found, fileXray must
somehow choose an instance. This is where the undelete cookie comes in—
each instance will have a unique undelete cookie.
Depending on the file system activity that occurred, the various instances may
or may not differ in ways that are relevant to scavenging—some instances may
be more recoverable than the others. If you wish to have fine control over the
scavenging operation, you can use --undelete_cookie to address a particular
instance of a deleted file system object.
153
--undelete_cookie COOKIE
If no instance is explicitly specified through --undelete_cookie, fileXray
will automatically choose an instance. fileXray’s choice may not always be a
good one.
*** None of the deleted file's data fork blocks are CURRENTLY in use by
other files, although they could have been reused and freed in the past.
# Resource Fork
logicalSize = 0 bytes
See Also
• --scavenge
154
-1 --usedspace
--usedspace
For each used extent, fileXray displays the following information: the number
of allocation blocks in that extent, the starting and ending block numbers in
hexadecimal, and the amount of associated used space.
You can pipe the output through “sort -n” to view a list of contiguous used
space chunks sorted by chunk size. In the following example, we see that the
largest contiguous chunk on the volume has 1,550,870 allocation blocks. The
chunk starts at allocation block number 0x85518a and ends at allocation block
number 0x9cfb9f. Given the allocation block size of 4096 bytes, this chunk
amounts to 6.4 GB.
Another way to visualize used extents on a volume is to use the built-in used-
space virtual file system, which can be accessed through the --userfs_type
option.
See Also
• --freespace
• --userfs_mount MOUNT_POINT
• --userfs_type freespace
• --userfs_type usedspace
155
-M MOUNT_POINT --userfs_mount MOUNT_POINT
--userfs_mount MOUNT_POINT
This option is used along with the --userfs_type option to make certain types
of volume information accessible as user-space virtual file systems. The volume
of interest must also be specified through other valid options.
The --userfs_type section of this document provides more details and exam-
ples.
See Also
• --userfs_type USERFS_TYPE
156
-U USERFS_TYPE --userfs_type USERFS_TYPE
--userfs_type USERFS_TYPE
This option is used along with the --userfs_mount option to make certain
types of volume information accessible as user-space virtual file systems. The
volume of interest must also be specified through other valid options.
freespace Free space (extents) on the volume can be accessed through files.
usedspace Used space (extents) on the volume can be accessed through files.
The Arbitrary File System contains no visible files by default. However, when
you attempt to access a file whose name encodes a starting offset and a size,
the corresponding content will be transparently made available through that
file. The specific naming format is as follows.
[-]START_BYTE,SIZE_IN_BYTES[.extension]
For example, if you attempt to open a file called 0x5000,4096.txt, you will
“see” a file whose contents come from the HFS+ volume’s on-disk byte range
that starts at byte offset 0x5000 and is 4096 bytes in size. Optionally,
START_BYTE can be negative, in which case the starting offset is relative to the
end of the volume. For example, -0x5000,4096.txt would read 4096 bytes
starting at an offset that’s 0x5000 bytes before the end of the volume. You can
also specify multiple extents using the colon character as the separator. For
example: 0x5000,4096:0x9000,4096:0xc000,4096.txt.
The Arbitrary File System is particularly useful for accessing the results of the
--trawl operation.
Consider the following example. We can use the Arbitrary File System to mount
an HFS+ volume on, say, /tmp/arbitrary. We know that the Volume Header,
which is 512 bytes in size, resides at an offset of 1024 bytes from the beginning
of the volume. The Alternate Volume Header, which is a reasonably-in-sync
copy of the Volume Header, resides at an offset of 1024 bytes from the end of
the volume. Given that the Arbitrary File System lets us access arbitrary byte
ranges with either positive or negative offsets, we can read a few bytes from
157
--userfs_type USERFS_TYPE
these two data structures and see if we get expected values for the volume sig-
nature and the last mounted version signature.
# Look at the first 12 bytes of the Volume Header, which is 512 bytes in size
# and resides at an offset of 1024 bytes from the beginning of the volume.
$ hexdump -n 12 -xc /tmp/arbitrary/1024,512
0000000 2b48 0400 0080 0020 4648 4a53
0000000 H + \0 004 200 \0 \0 H F S J
000000c
# Look at the first 12 bytes of the Alternate Volume Header, which resides
# at an offset of 1024 bytes from the end of the volume.
$ hexdump -n 12 -xc /tmp/arbitrary/-1024,512
0000000 2b48 0400 0080 0020 4648 4a53
0000000 H + \0 004 200 \0 \0 H F S J
000000c HFS+ Volume Last Mounted
Signature Version
Next, we can create a file with some content, look up the newly created file’s ex-
tents, and try to access the content through the Arbitrary File System. The fol-
lowing example illustrates this.
# Allocation block size for this volume is 4096 bytes. Therefore, block
# number 0x2e9ccbc amounts to byte offset 0x2e9ccbc000. We can use the
# Arbitrary File System to read 19 bytes from this offset.
$ cat /tmp/arbitrary/0x2e9ccbc000,19.txt
This is some text.
158
--userfs_type USERFS_TYPE
Given the general utility of the Arbitrary File System, fileXray allows you to
mount non-HFS+ entities such as other types of volumes and even regular
files. To do so, you must additionally specify the --force option. This mecha-
nism provides a convenient way to access, introspect, and analyze arbitrary
parts of volumes and files.
The following example shows mounting a Mach-O executable using the Arbi-
trary File System. Once mounted, the well defined constituents of the file can
be “directly” accessed by addressing them through file names consisting of the
constituents’ offsets and sizes.
# Use the Arbitrary File System to mount a file instead of an HFS+ volume.
# The --force option will enable such mounting despite the warning.
$ sudo fileXray --userfs_type arbitrary --userfs_mount /tmp/arbitrary \
--device /mach_kernel --force
No flavor of HFS+ found.
$
$ ls -l /mach_kernel
-rw-r--r--@ 1 root wheel 18672224 Jul 31 22:49 /mach_kernel
$ df -h /tmp/arbitrary
Filesystem Size Used Avail Capacity Mounted on
fileXray@fuse0 18Mi 18Mi 0Bi 100% /private/tmp/arbitrary
$
# Look for something interesting in the file. For example, the __cstring
# section in the text segment of this Mach-O file.
$ otool -l /mach_kernel
…
sectname __cstring
segname __TEXT
addr 0x005832c8
size 0x00057def
offset 3683016
…
Note that the Arbitrary File System does not cache on-disk content. Therefore,
reading its virtual files will retrieve the “latest” data.
159
--userfs_type USERFS_TYPE
Free Space File System
The Free Space File System contains files representing free extents on a given
volume. The idea is to isolate free space in easy-to-read contiguous chunks,
which makes searching through free space much more convenient and faster
in most cases.
The top-level freespace directory in the file system contains one or more vir-
tual subdirectories whose names are of the format X_Y. X is simply a mono-
tonically increasing decimal number starting at 0. Y represents a block number
in hexadecimal, which is the starting block number of the first extent within
the directory.
# Use the Free Space File System to mount the root volume.
$ sudo fileXray --userfs_type freespace --userfs_mount /tmp/freespace
$ ls -las /tmp/freespace/freespace/
total 0
0 drwxr-xr-x 38 root wheel 0 Nov 2 20:58 .
0 drwxr-xr-x 3 root wheel 0 Nov 2 20:58 ..
0 dr-xr-xr-x 1026 root wheel 0 Nov 2 20:58 00000000_00014d87
0 dr-xr-xr-x 1026 root wheel 0 Nov 2 20:58 00000001_003e4772
0 dr-xr-xr-x 1026 root wheel 0 Nov 2 20:58 00000002_004e8ae8
0 dr-xr-xr-x 1026 root wheel 0 Nov 2 20:58 00000003_00550783
0 dr-xr-xr-x 1026 root wheel 0 Nov 2 20:58 00000004_005b8023
0 dr-xr-xr-x 1026 root wheel 0 Nov 2 20:58 00000005_00bda9bd
…
0 dr-xr-xr-x 1026 root wheel 0 Nov 2 20:58 00000034_02d66310
0 dr-xr-xr-x 389 root wheel 0 Nov 2 20:58 00000035_02ec061a
Inside each such directory named X_Y, there are at most 1024 virtual files —a
new directory is created after the previous one is populated with 1024 files.
Each file represents a free extent—that is, a range of contiguous free blocks.
Each file’s name is of the form U_V. U is the extent’s starting block number and
V is the number of blocks in the extent. Both U and V are represented in hexa-
decimal. As noted earlier, the value of U for the first extent contained within the
X_Y directory is the same as the value of Y.
Reading from such a file will return data from the on-disk blocks the file repre-
sents. Note that the free extents are calculated at the time the Free Space File
System is mounted. If the volume in question is mounted and the set of free ex-
tent changes while the Free Space File System is mounted, the directory tree
representing free extents will not update.
160
--userfs_type USERFS_TYPE
However, the Free Space File System does not cache on-disk content. There-
fore, reading its virtual files will in fact retrieve the “latest” data. The following
shows the last few contents of the last X_Y directory.
$ ls -asl /tmp/freespace/freespace/00000035_02ec061a
…
848 -rw-r--r-- 1 root wheel 424K Nov 2 21:18 02f0db4e-02f0dbb7
88 -rw-r--r-- 1 root wheel 44K Nov 2 21:18 02f0dc69-02f0dc73
2272 -rw-r--r-- 1 root wheel 1.1M Nov 2 21:18 02f0dc77-02f0dd92
114176 -rw-r--r-- 1 root wheel 56M Nov 2 21:18 02f0dd94-02f11553
530184 -rw-r--r-- 1 root wheel 259M Nov 2 21:18 02f11556-02f21836
16608 -rw-r--r-- 1 root wheel 8.1M Nov 2 21:18 02f21840-02f2205b
92345904 -rw-r--r-- 1 root wheel 44G Nov 2 21:18 02f2205d-03a24322
$
The Structure File System exposes the low-level structure of an HFS+ volume
through a set of contiguous virtual files. Depending on the structure of the spe-
cific volume mounted through this file system, fileXray will make available
the following “files,” not all of which may be present on all volumes.
Some of these entities, such as the Volume Headers, will have constant sizes,
whereas the sizes of others will vary from volume to volume. Although the vir-
tual files are conveniently contiguous, which is one of the primary benefits of
this file system, the corresponding on-disk content for several of the entities is
not contiguous.
Note that the Structure File System does not cache on-disk content. Therefore,
reading its virtual files will retrieve the “latest” data for the files’ on-disk ex-
tents. However, these on-disk extents are established at the time the Structure
File System is mounted. Therefore, if the volume in question is live (mounted)
and the extents change while the Structure File System is mounted, the
changes will not be reflected in the latter.
161
--userfs_type USERFS_TYPE
The following example shows the contents of a volume mounted through the
Structure File System.
The Structure File System can be put to several uses. It allows you to visualize
the storage space consumed purely by a volume’s “metadata.” It also allows
you to conveniently introspect and search specific well-defined components of
an HFS+ volume. For example, using a version of the strings command with
support for 16-bit big endian encoding (the GNU strings program from the
binutils package has such support), you can search for HFS+ node and at-
tribute names within the Catalog and Attributes files, respectively.
$ /usr/local/bin/strings --version
GNU strings (GNU Binutils) 2.19.1
…
The Used Space File System contains files representing used extents on a given
volume. Its purpose and contents are similar to that of the Free Space File Sys-
tem, except that we are dealing with used extents instead of free extents.
162
--userfs_type USERFS_TYPE
Scavenger File System
While scavenging, fileXray will usually find multiple instances of the meta-
data remnants of files and folders. Depending on the file system activity that
occurred on the volume, these remnants may or may not differ in ways that are
relevant to scavenging. For example, remnants could differ only in one times-
tamp, or they may differ in file size or extents. The --scavenge option displays
all remnants it finds—it associates an “undelete cookie” with each instance to
differentiate between the remnants and to allow you to select a particular in-
stance to analyze or “undelete.” The Scavenger File System also shows all file
remnants by placing distinct remnants in parent folders that are named after
the respective files’ undelete cookies. The file system layout is as follows.
The Scavenger File System’s root level contains only synthetic subfolders whose
names adhere to one of the following formats. (The italicized part of the format
is literal, whereas the bold part is a parameter.)
COOKIE_CNID This format is used when the scavenged file’s parent folder
is the root folder. COOKIE will be replaced by the hexadeci-
mal undelete cookie of a scavenged file instance. CNID will
be replaced by the file’s decimal CNID. If no scavenged file
resided (before it was deleted) in the volume’s root folder,
there will be no entries with this format at the root level of
the Scavenger File System.
163
--userfs_type USERFS_TYPE
each block of a fork, the Scavenger File System will serve the actual on-disk
block only if that block is currently free in the volume. If the block is currently
allocated, some or all of its original content may have been clobbered. By de-
fault, the Scavenger File System will substitute a clobbered block with a zero-
filled block. However, depending on the file type and your scavenging goal, even
partial information might be useful. To override the zero-filled substitution be-
havior, you can additionally specify the --exhaustive option, in which case
the Scavenger File System will serve on-disk blocks without checking if they
are free or not.
Let us look at an example of using the Scavenger File System through a some-
what contrived experiment. We begin by creating an HFS+ volume and copying
some pictures to it. Then we delete the newly created folder by “mistake.” In the
following example, we unmount the volume as well. In real life, the unmount-
ing may or may not occur—there are pros and cons both ways. Keeping it
mounted is fine if the volume is really quiescent. Unmounting it means there
will be no further file system activity, but the very act of unmounting causes
more file system activity—in particular, it flushes the journal. The Scavenger
File System’s abilities are most appropriately thought of as “best effort,”, and
so are the --scavenge operation’s. Let us see what can be done.
164
--userfs_type USERFS_TYPE
# Use fileXray to display a list of scavengable content.
$ fileXray --device /tmp/test.dmg --scavenge
…
f,24/84,0x34f30,2957/2957/2957,11/11/11,apple.tif:[CNID=24]/apple.tif
…
f,24/172,0x35a48,942/942/942,19/19/19,fileXray.tif:[CNID=24]/fileXray.tif
…
f,24/374,0x66656,144/144/144,0/0/0,vista.jpg:[CNID=24]/vista.jpg
…
Since content of interest does show up in the output of --scavenge, let us use
the Scavenger File System on this volume. Note that two of the files shown in
the excerpt have content in both forks. Moreover, the blocks belonging to all
these files are currently free.
Note that the time taken to “prepare” the Scavenger File System will be longer
for larger volumes.
165
--userfs_type USERFS_TYPE
Note that the Scavenger File System snapshots the scavengable metadata as it
populates itself. Once mounted, the Scavenger File System view will not change
even if the underlying volume is normally mounted and file system activity is
occurring.
Caveats
Although the Scavenger File System can be used on a live, mounted volume, it
is not advisable to do so, especially if that volume is the root volume. The usual
volatility of a root volume does not lend itself to scavenging very well. Therefore,
it is best to use this file system (or in general, perform any type of scavenging
operation) on an unmounted or at least quiescent non-root volume. Moreover,
do not copy from the Scavenger File System to the volume that is currently be-
ing scavenged.
See Also
• --force
• --freespace
• --journal_names
• --scavenge
• --trawl QUERY
• --usedspace
• --userfs_mount MOUNT_POINT
166
--version
--version
Print software version and license information. If applicable, fileXray will also
display the type of the product, such as “personal” or “pro.”
$ fileXray --version
fileXray plus 1.0.0
Copyright (c) 2010 iohead LLC. All Rights Reserved.
167
-V VOLUME_PATH --volume VOLUME_PATH
--volume VOLUME_PATH
Specify an HFS+ volume through a path (VOLUME_PATH) that’s either the vol-
ume’s mount point or is a file system object within a mounted volume.
The --volume option is one of the ways you can explicitly specify a volume for
fileXray to operate upon. For this option to be used, the volume must be
mounted.
See Also
• --device DEVICE
168
-v --volume_header
--volume_header
# Volume Header
signature = 0x482b (H+)
version = 0x4
lastMountedVersion = 0x4846534a (HFSJ)
attributes = 10000000000000000010000000000000
. kHFSVolumeJournaled (volume has a journal)
journalInfoBlock = 0x746
createDate = Mon Nov 2 18:56:59 2009
modifyDate = Mon Nov 14 17:41:10 2009
backupDate = 0
checkedDate = Mon Nov 2 18:56:59 2009
fileCount = 1422188
folderCount = 267513 /* not including the root folder */
blockSize = 4096
totalBlocks = 60965668
freeBlocks = 20533351
nextAllocation = 48966050
rsrcClumpSize = 65536
dataClumpSize = 65536
nextCatalogID = 3200347
writeCount = 122156696
encodingsBitmap = 00000000000000000000000000000000
00000010000000000000000011001111
. MacRoman
. MacJapanese
. MacChineseTrad
. MacKorean
. MacGreek
. MacCyrillic
. MacChineseSimp
continued…
169
--volume_header
…
# Finder Info
# Bootable system blessed folder ID
finderInfo[0] = 0x88 (MacHD:/System/Library/CoreServices)
# Parent folder ID of the startup application
finderInfo[1] = 0x11714d (MacHD:/System/Library/CoreServices/boot.efi)
# Open folder ID
finderInfo[2] = 0
# Mac OS 9 blessed folder ID
finderInfo[3] = 0
# Reserved
finderInfo[4] = 0
# Mac OS X blessed folder ID
finderInfo[5] = 0x88 (MacHD:/System/Library/CoreServices)
# VSDB volume identifier (64-bit)
finderInfo[6] = 0x18df290
finderInfo[7] = 0xcc72ad0e
# File System Boot UUID
UUID = C91FC7AA-AC77-3D04-AB95-A55111B435EE
continued…
170
--volume_header
…
# Startup File (CNID 7)
logicalSize = 0 bytes
Note that fileXray also displays the Catalog Node IDs of two special folders
used internally by the file system.
The Private Metadata Folder is used to house two types of objects: the files that
hold the content of file hard links (that is, the link targets of file hard links) and
files that were unlinked while they were still open or otherwise busy. When an
open file is unlinked, it is renamed and moved to the Private Metadata Folder,
where it lives at least until it is closed.
The Directory Metadata Folder is used to house the directories that are the link
targets of directory hard links.
See Also
• --exhaustive
• --mount_data
• --userfs_type structure
171
-w BYTE --who_owns_byte BYTE
--who_owns_byte BYTE
Determine which file system object, if any, “owns” the byte at offset BYTE on
the given HFS+ volume. Note that byte offset 0 represents the beginning of the
volume.
The following examples show how to use --who_owns_byte. Note that in the
case of /mach_kernel, we look at the file’s extents to know where the file be-
gins on the volume. Since its first block is number 0x1b71e6 and the allocation
block size for this volume is 4096 bytes, the file’s first byte is byte number
0x1b71e6000 (that is, 0x1b71e6 × 4096) on the volume.
See Also
• --who_owns_block BLOCK
172
-W BLOCK --who_owns_block BLOCK
--who_owns_block BLOCK
Determine which file system object, if any, “owns” the allocation block number
BLOCK on the given HFS+ volume. Note that block number 0 represents the be-
ginning of the volume.
The volume’s allocation block size can be seen in the Volume Header, which
can be displayed using the --volume_header option.
See Also
• --volume_header
• --who_owns_byte BYTE
173