<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mac OS X Internals &#187; Apple</title>
	<atom:link href="http://osxbook.com/blog/category/apple/feed/" rel="self" type="application/rss+xml" />
	<link>http://osxbook.com/blog</link>
	<description>A Systems Approach</description>
	<lastBuildDate>Fri, 13 Apr 2012 07:35:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>fileXray</title>
		<link>http://osxbook.com/blog/2010/11/01/filexray/</link>
		<comments>http://osxbook.com/blog/2010/11/01/filexray/#comments</comments>
		<pubDate>Mon, 01 Nov 2010 18:19:15 +0000</pubDate>
		<dc:creator>amit</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[fileXray]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Operating Systems]]></category>

		<guid isPermaLink="false">http://www.osxbook.com/blog/?p=583</guid>
		<description><![CDATA[Does the idea of wielding power&#8212;a lot of power&#8212;intrigue you? Check out fileXray. Start with the ebook. If you are one of the target audiences, it will be worth your time.]]></description>
			<content:encoded><![CDATA[<p>Does the idea of wielding power&mdash;<em>a lot of power</em>&mdash;intrigue you?  Check out <a href="http://filexray.com" title="fileXray Web Site">fileXray</a>.</p>
<p>Start with the ebook. If you are one of the target audiences, it will be worth your time.</p>
]]></content:encoded>
			<wfw:commentRss>http://osxbook.com/blog/2010/11/01/filexray/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Is Your Machine Good Enough for Snow Leopard K64?</title>
		<link>http://osxbook.com/blog/2009/08/31/is-your-machine-good-enough-for-snow-leopard-k64/</link>
		<comments>http://osxbook.com/blog/2009/08/31/is-your-machine-good-enough-for-snow-leopard-k64/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 01:45:27 +0000</pubDate>
		<dc:creator>amit</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Mac OS X]]></category>

		<guid isPermaLink="false">http://www.osxbook.com/blog/?p=483</guid>
		<description><![CDATA[&#8220;K64&#8243; is what Apple refers to as the 64-bit version of the kernel beginning with Snow Leopard. As an end user, you really should not worry about the bitness of the kernel. If your Apple computer is not booting into K64 by default, you don&#8217;t need it&#8212;unless, of course, you know that you need it. [...]]]></description>
			<content:encoded><![CDATA[<p>&#8220;K64&#8243; is what Apple refers to as the 64-bit version of the kernel beginning with Snow Leopard. As an end user, you really <em>should not</em> worry about the bitness of the kernel. If your Apple computer is not booting into K64 by default, you don&#8217;t need it&mdash;unless, of course, you <em>know</em> that you need it. (Say, because you are a kernel developer or an otherwise system-level developer and want to test something against a 64-bit kernel.) In particular, the 32-bit kernel, which is the default on most existing x86-based Apple computers, runs 64-bit <em>applications</em> just fine. Therefore, as long as you have a 64-bit processor, your Snow Leopard installation <em>is</em> 64-bit from the typical end-user standpoint.</p>
<p>An easy way to tell if you are running a K64 kernel is to use the <code>uname</code> command-line program. The &quot;x86_64&quot; in the excerpt below means that we are running a 64-bit kernel. If the output showed &quot;i386&quot; instead, that would mean a 32-bit kernel.</p>
<p><code style="font-size: 80%;"></p>
<pre>
$ <strong>uname -a</strong>
Darwin... root:xnu-1456.1.25~1/RELEASE_X86_64 x86_64
</pre>
<p></code></p>
<p>If you are averse to using command-line programs (Do you really care about a K64 kernel in that case?), you could instead launch the System Profiler application, either directly, or by clicking on &quot;More Info&#8230;&quot; in the &quot;About This Mac&quot; panel. In System Profiler, you can click on the &quot;Software&quot; section in the sidebar. There will be something about the presence or absence of 64-bit Kernel and Extensions. You could also launch the Activity Monitor application and look for <code>kernel_task</code>. The &quot;Kind&quot; column will say if the kernel task (and consequently the kernel) is 64-bit.</p>
<p>As alluded to earlier, a 64-bit processor is required to run a K64 kernel. To boot into K64, you could do one of several things:</p>
<ul>
<li>Press the <code>6</code> and the <code>4</code> keys simultaneously at power-on time. This indicates to the EFI boot loader (<code>boot.efi</code>) that you wish to boot a 64-bit kernel.</li>
<li>Set the <code>boot-args</code> firmware variable, say, through the <code>nvram</code> command-line program. To boot K64, the specific command-line would be:<br /> <code style="font-size: 80%;">
<pre>$ <strong>sudo nvram boot-args=&quot;arch=x86_64&quot;</strong></pre>
<p></code></li>
<li>Edit <code>/Library/Preferences/SystemConfiguration/com.apple.Boot.plist</code> and add <code>arch=x86_64</code> to the value of the <code>Kernel Flags</code> key. By default, this value is an empty string.<br />
<code style="font-size: 80%;"></p>
<pre>
$ <strong>cat /Library/Preferences/SystemConfiguration/com.apple.Boot.plist</strong>
...
&lt;dict&gt;
	&lt;key&gt;Kernel&lt;/key&gt;
	&lt;string&gt;mach_kernel&lt;/string&gt;
	&lt;key&gt;Kernel Flags&lt;/key&gt;
	&lt;string&gt;<span style="background-color: #00ff00;">arch=x86_64</span>&lt;/string&gt;
&lt;/dict>
...
</pre>
<p></code>
</li>
</ul>
<p>Another way is to use the <code>-setkernelbootarchitecture</code> argument of the <code>systemsetup(8)</code> command-line program.</p>
<p>Additionally, you could tell the kernel to boot verbosely if you are interested in catching a 64-bit boot early on. Note that one of the early kernel messages is <em>&quot;64 bit mode enabled&quot;</em>. This does <strong>not</strong> mean K64&mdash;it just means the kernel has identified the processor to be 64-bit and is going to use certain 64-bit features. In the case of a K64 boot, the message to look for is <em>&quot;Kernel is LP64&quot;</em>.</p>
<p>Not so fast though.</p>
<p>Unfortunately, a 64-bit processor alone doesn&#8217;t suffice. Out of the box, <code>boot.efi</code> will not boot K64 even if you have a 64-bit processor and explicitly request K64 if at least one of the following is true.</p>
<ol>
<li>The machine has 32-bit EFI.</li>
<li>The machine&#8217;s model is prohibited from booting K64 through a hardcoded list within the boot loader. (A cursory look suggests that the list excludes &quot;non-Pro&quot; machines.)</li>
</ol>
<p>Both of these &quot;limitations&quot; are technically artificial, albeit to different degrees.</p>
<p>The first limitation actually does have merit and is arguably not all that artificial. Although a 32-bit EFI <em>could</em> launch a 64-bit kernel, the kernel, when running, would not be able to use firmware services. In particular, you wouldn&#8217;t have NVRAM. For kernel developers merely wanting to run a 64-bit kernel for testing and debugging, this may not be an issue, but it&#8217;s understandable why the limitation is in place.</p>
<p>The second limitation is annoying. As a developer, if you <em>knowingly</em> wish to boot into K64 to test something, you can&#8217;t on certain machines even though they are technically perfectly capable. I ran into this on a Unibody MacBook, which has 64-bit EFI but is not a &quot;Pro&quot; machine. Also, it&#8217;s ironic that you can, in fact, boot Snow Leopard into K64 on the very same computer when you run it as a guest operating system in a virtual machine.</p>
<p>If you really need to boot into K64 on such a machine with 64-bit EFI, you can&mdash;<strong>at your own peril</strong>&mdash;&quot;fix&quot; things within <code>boot.efi</code> by setting the appropriate bits in the hardcoded list of models. To ensure that we&#8217;re talking about the same multiarchitecture version of <code>boot.efi</code>, compare the SHA-1 checksum of that file.</p>
<p><code style="font-size: 80%;"></p>
<pre>
$ <strong>shasum boot.efi</strong>
2fb9fc10e5b4bb06f62c38b01bd9836a433897f8    boot.efi
</pre>
<p></code></p>
<p>Then, change the 1 byte at the corresponding model-specific position in the following table to the corresponding new value. Rather than overwriting the original <code>boot.efi</code>, we will copy the original to a new file, say, <code>boot-k64.efi</code>, and edit the latter.</p>
<table>
<tr>
<th>Model (with 64-bit EFI)</th>
<th>Byte Position in boot.efi</th>
<th>Old Value</th>
<th>New Value</th>
</tr>
<tr>
<td>Mac mini</td>
<td><code>0x266D8</code></td>
<td><code>0x00</code></td>
<td><code>0x04</code></td>
</tr>
<tr>
<td>MacBook</td>
<td><code>0x266E8</code></td>
<td><code>0x00</code></td>
<td><code>0x04</code></td>
</tr>
<tr>
<td>MacBook Air</td>
<td><code>0x266F8</code></td>
<td><code>0x00</code></td>
<td><code>0x04</code</td>
</tr>
<tr>
<td>iMac</td>
<td><code>0x26718</code></td>
<td><code>0x08</code></td>
<td><code>0x0c</code></td>
</tr>
</table>
<p>For the specific case of the MacBook, <strong>which is the only one I've actually tried</strong>, the before and after bytes will look like the following:</p>
<table>
<tr>
<td><code><strong>0x266E0:</strong></code></td>
<td><code>
<pre>38 47 01 00  00 00 00 00  00 00 00 00  00 00 00 00</pre>
<p></code></td>
</tr>
<tr>
<td><code><strong>0x266E0:</strong></code></td>
<td><code>
<pre>38 47 01 00  00 00 00 00  <span style="background: #00ff00;">04</span> 00 00 00  00 00 00 00</pre>
<p></code></td>
</tr>
</table>
<p>We'll place the <code>boot-k64.efi</code> file somewhere on the root volume&mdash;<code>/System/Library/CoreServices/</code> is fine. Then, we need to reset volume bootability through the <code>bless</code> command-line program. Optionally, we can also set the ownership and user immutable flag on the file to &quot;proper&quot; values.</p>
<p><code style="font-size: 80%;"></p>
<pre>
$ <strong>sudo cp boot-k64.efi /System/Library/CoreServices/</strong>
$ <strong>cd /System/Library/CoreServices/</strong>
$ <strong>sudo chown root:wheel boot-k64.efi</strong>
$ <strong>sudo chflags uchg boot-k64.efi</strong>
$ <strong>sudo bless --folder /System/Library/CoreServices \
  --file /System/Library/CoreServices/boot-k64.efi</strong>
</pre>
<p></code></p>
<p>Your mileage may vary depending on whether your installation has 64-bit versions of all necessary drivers for the model of your specific machine. Since I have not tried any other &quot;excluded&quot; machine besides a 64-bit MacBook, I don't know about other models. (Unavailability or instability of certain 64-bit drivers <em>could</em> be a plausible reason for these models to be excluded in the first place.)</p>
<p>If you do render your system unbootable, you can simply run <code>bless</code> again to restore volume bootability as it was before. That is, you can tell <code>bless</code> to use the original <code>boot.efi</code>. Of course, to do that, you'll need to either boot from a different volume (a system install disc would be fine), or be able to access and write to the unbootable volume from another computer.</p>
<p><code style="font-size: 80%;"></p>
<pre>
$ <strong>sudo bless --folder /Volumes/BrokenMac/System/Library/CoreServices \
  --file /Volumes/BrokenMac/System/Library/CoreServices/boot.efi</strong>
</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://osxbook.com/blog/2009/08/31/is-your-machine-good-enough-for-snow-leopard-k64/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Note on Pathname Processing in HFSDebug</title>
		<link>http://osxbook.com/blog/2008/11/24/a-note-on-pathname-processing-in-hfsdebug/</link>
		<comments>http://osxbook.com/blog/2008/11/24/a-note-on-pathname-processing-in-hfsdebug/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 12:18:43 +0000</pubDate>
		<dc:creator>amit</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Operating Systems]]></category>

		<guid isPermaLink="false">http://www.osxbook.com/blog/?p=193</guid>
		<description><![CDATA[A couple of weeks ago, I released HFSDebug 4. I&#8217;ve updated it to make HFSDebug&#8217;s pathname processing a little more sophisticated. Depending on how (and how seriously) you use HFSDebug, knowing the details could be useful. When you specify a file system object to HFSDebug using a pathname, how HFSDebug will treat the pathname usually [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of weeks ago, I released <a href="http://www.osxbook.com/blog/2008/11/09/hfsdebug-40-and-new-hfs-features/" title="HFSDebug 4 and New HFS+ Features">HFSDebug 4</a>. I&#8217;ve updated it to make HFSDebug&#8217;s pathname processing a little more sophisticated. Depending on how (and how seriously) you use HFSDebug, knowing the details could be useful.</p>
<p>When you specify a file system object to HFSDebug using a pathname, how HFSDebug will treat the pathname usually depends on other arguments, or the lack of other arguments.</p>
<h3>Something to Read and Forget: The &#8220;Legacy&#8221; Mode</h3>
<p>A typical invocation is quite simple: you simply give HFSDebug a path. If the path exists on an HFS+ volume, HFSDebug will use the underlying volume as the one to operate upon.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>sudo hfsdebug /mach_kernel</strong>
...
</pre>
<p></code></p>
<p>In this case, HFSDebug will begin by doing a <code>stat(2)</code> call on the path. <em>(As you will see shortly, this and the entire &#8220;legacy mode&#8221; is optional&mdash;you can make HFSDebug do even this part &#8220;from scratch&#8221; and not use <code>stat(2)</code> or other file system calls on the volume.)</em> Since the goal is to make it possible to examine file system&#8217;s <em>internal</em> structure as opposed to what the user &#8220;sees&#8221; through layers of interfaces, it matters whether the object in question is a file hard link, directory hard link, symbolic link, etc. Specifically, we need to get at the link <em>reference</em> that the pathname represents&mdash;not the <em>target</em> it resolves to. For symbolic links, we can use <code>lstat(2)</code> to give us the node ID of the reference. For file and directory hard links, we have to use something else.</p>
<p>How do we know if something is a hard link? HFSDebug examines the <code>st_nlink</code> (link count) and <code>st_mode</code> fields of the resultant <code>stat</code> structure.</p>
<p>In the case of regular files, a link count of 2 or higher means the object is a &#8220;known&#8221; hard link.</p>
<p>In the case of directories, what &#8220;link count&#8221; means is quite context-sensitive on HFS+. The <code>stat</code> structure&#8217;s <code>st_nlink</code> for a directory normally represents the directory&#8217;s <em>item count</em>. The directory itself (the <code>"." </code> entry) and its parent (the <code>".."</code> entry) together add 2 to the count. Thus, if you have a directory with, say, 4 files and 4 subdirectories in it, a <code>stat(2)</code> call would report an <code>st_nlink</code> value of 10. However, if the <em>folder count</em> bit is enabled on the mount, the meaning of <code>st_nlink</code> changes: it then represents a count of only the subdirectories. In the aforementioned example, the link count would be 6 instead of 10. The folder count bit is currently only enabled for case-sensitive (HFSX) volumes. Besides the <code>stat</code> structure&#8217;s <code>st_nlink</code> field, HFS+ can separately provide the <em>children count</em> and the <em>real hard link count</em> for directories. The <code>getattrlist(2)</code> call can be used to retrieve these: they are the <code>ATTR_DIR_ENTRYCOUNT</code> and <code>ATTR_DIR_LINKCOUNT</code> directory attributes, respectively. Once we do know a directory&#8217;s &#8220;real&#8221; hard link count, again, a value of 2 or higher means it is a &#8220;known&#8221; hard link.</p>
<p>By a &#8220;known&#8221; file or directory hard link, I mean that we know that it <em>currently is</em> a hard link. That means the object we are looking at is a link reference and the &#8220;visible&#8221; node ID isn&#8217;t that of the reference but is that of its target. (See my <a href="http://www.osxbook.com/blog/2008/11/09/hfsdebug-40-and-new-hfs-features/" title="HFSDebug 4 and New HFS+ Features">previous post</a> for more information.) In this case, HFSDebug will retrieve the object&#8217;s parent folder&#8217;s node ID and use it in conjunction with the object&#8217;s name to do a &#8220;from scratch&#8221; lookup of the object&#8217;s node ID. (This is a traditional <code>{ parent_nodeid, name } ==> nodeid</code> lookup.)</p>
<p>However, things are <em>not</em> simpler if the link count of the object is 1. That&#8217;s because it could have <em>had</em> a higher link count in the past and the other links were deleted. Again, as I described <a href="http://www.osxbook.com/blog/2008/11/09/hfsdebug-40-and-new-hfs-features/" title="HFSDebug 4 and New HFS+ Features">earlier</a>, the on-disk object continues to be a reference to the real content that lives in a special hidden HFS+ folder. If that&#8217;s the case though, the hidden folder will have a file or a folder whose name is formed from the object&#8217;s visible node ID: <code>iNode%d</code> or <code>dir_%d</code> for files and folders, respectively. If no such file or folder exists, as HFSDebug can look up from scratch, the object is not a current <em>or past</em> hard link.</p>
<p>If this sounds unnecessarily complex, well, some of it is. Until version 4, HFSDebug did not have the ability to process complete pathnames from scratch. With version 4, you can do things like the following on both mounted and unmounted volumes alike.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>sudo hfsdebug -d /dev/disk0s2 /mach_kernel</strong>
...
</pre>
<p></code></p>
<h3>Simpler, Better</h3>
<p>In the new mode, HFSDebug will no longer do a <code>stat(2)</code>/<code>lstat(2)</code> or involve the file system otherwise. Obviously, if it has to support unmounted volumes, that&#8217;s how it has to be. It will take the pathname and process it component-by-component, which is easier to conceptualize than the &#8220;legacy&#8221; mode I described above. (Well, to be fair to the legacy mode, it became uglier with the advent of directory hard links.)</p>
<p>The following are examples of how HFSDebug will handle things based on some of its arguments.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>sudo hfsdebug /foo/bar/baz</strong>
# legacy mode; will use stat(2)/lstat(2) to kick things off
...
$ <strong>sudo hfsdebug -d /dev/diskN /foo/bar/baz</strong>
# new mode; volume can be mounted or unmounted
...
$ <strong>sudo hfsdebug -P /foo/bar/baz</strong>
# new mode; uses root volume, which is obviously mounted
...
$ <strong>sudo hfsdebug -d /dev/diskN -P /foo/bar/baz</strong>
# new mode; volume can be mounted or unmounted
</pre>
<p></code></p>
<div style="background-color: #eaeaf4; border: 1px solid #c0c0ff; padding: 1em;">
If you are wondering why I haven&#8217;t removed the legacy mode altogether, it&#8217;s because I want to keep it around for some time so that I can compare things while testing.
</div>
<p>Just remember that you can use the <code>-P</code> argument (note that it&#8217;s the capital <code>P</code>) to specify a path and HFSDebug will use the new mode on both mounted and unmounted volumes. The path must be absolute.</p>
<h3>Some Rules</h3>
<p>Now, if HFSDebug is not involving the file system at all, it better be able to handle arbitrarily convoluted pathnames. Using things like <code>realpath(3)</code> is not an option since <code>realpath(3)</code> would want to call <code>stat(2)</code>/<code>lstat(2)</code>. Say, we could have a path like the following.</p>
<p><code>/foo////././bar///../baz/../blah/..//////.././dir/are/you/../crazy/</code></p>
<p>Besides, there could be components in the path that are symbolic or hard links. Symbolic links could point to targets that have equally crazy pathnames. It&#8217;s not just a matter of canonicalizing the dots and the slashes. We have several requirements as illustrated by the following examples. (Some of these are simply HFSDebug conventions.)</p>
<ul style="list-style: square;">
<li>We must ensure that all intermediate components resolve to directories. They can be actual directories, valid symbolic links to directories, or directory hard links. <a href="http://www.osxbook.com/blog/2008/11/09/hfsdebug-40-and-new-hfs-features/">Remember</a> that in the case of symbolic or hard links, the on-disk object will be a &#8220;file&#8221;&mdash;HFSDebug will need to resolve them from scratch too.</li>
<li>If there is a &#8220;..&#8221;, we must not blindly go &#8220;up&#8221; one level: we must ensure that what we are going back from <em>is</em> a directory. <code>realpath(3)</code> actually doesn&#8217;t care about this: it will canonicalize <code>/path/to/file.txt/../file.txt</code> to <code>/path/to/file.txt</code>.</li>
<li>Although we do want to resolve intermediate components that are links, we must not resolve the terminal component if it happens to be a hard link or a symbolic link. That&#8217;s because our goal is to look at what&#8217;s on disk for the given path. Besides, in the case of a link, the details shown by HFSDebug <em>will</em> include the full pathname to the link&#8217;s target. If we wanted further details on the target, we could run HFSDebug on it.</li>
<li>If the path has a terminal slash, HFSDebug will ensure that the component is a directory. If it happens to be a directory hard link or a symbolic link, HFSDebug <em>will</em> resolve it in this case. Consider an example: suppose there is a symbolic link <code>/tmp/somesymlink</code>. The following is what HFSDebug will do depending on the arguments and what the link points to.</li>
</ul>
<p><code></p>
<pre style="font-size: 85%;">
# somesymlink points to a file
#
$ <strong>sudo hfsdebug -P /tmp/somesymlink</strong>
... # will show details of the link itself
$ <strong>sudo hfsdebug -P /tmp/somesymlink/</strong>
... # will complain that the link target is not a directory

# somesymlink points to a directory
#
$ <strong>sudo hfsdebug -P /tmp/somesymlink</strong>
... # will show details of the link itself
$ <strong>sudo hfsdebug -P /tmp/somesymlink/</strong>
... # will show details of the directory somesymlink points to

# somesymlink points to a non-existent target
#
$ <strong>sudo hfsdebug -P /tmp/somesymlink</strong>
... # will show details of the link itself
$ <strong>sudo hfsdebug -P /tmp/somesymlink/</strong>
... # will complain that path /tmp/somesymlink/ was not found on the volume
</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://osxbook.com/blog/2008/11/24/a-note-on-pathname-processing-in-hfsdebug/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HFSDebug 4.0 and New HFS+ Features</title>
		<link>http://osxbook.com/blog/2008/11/09/hfsdebug-40-and-new-hfs-features/</link>
		<comments>http://osxbook.com/blog/2008/11/09/hfsdebug-40-and-new-hfs-features/#comments</comments>
		<pubDate>Mon, 10 Nov 2008 03:00:07 +0000</pubDate>
		<dc:creator>amit</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Operating Systems]]></category>

		<guid isPermaLink="false">http://www.osxbook.com/blog/?p=106</guid>
		<description><![CDATA[I wrote HFSDebug in early 2004. I initially made it available as a software tool to help understand fragmentation in HFS+ volumes, although it could also be used to analyze several implementation details of HFS+. Eventually, I extended HFSDebug to be able to analyze all on-disk aspects of HFS+, along with the ability to compute [...]]]></description>
			<content:encoded><![CDATA[<p>I wrote <a href="http://osxbook.com/software/hfsdebug/" title="HFSDebug">HFSDebug</a> in early 2004. I initially made it available as a software tool to help understand <a href="http://osxbook.com//software/hfsdebug/fragmentation.html" title="Fragmentation in HFS Plus Volumes">fragmentation in HFS+ volumes</a>, although it could also be used to analyze several implementation details of HFS+. Eventually, I extended HFSDebug to be able to analyze <em>all</em> on-disk aspects of HFS+, along with the ability to compute more types of volume statistics and to even retrieve some in-memory details of mounted HFS+ volumes.</p>
<p>HFSDebug has been an extremely useful tool for me. I&#8217;ve used it to help explain the workings of HFS+ in the <a href="http://osxbook.com" title="Mac OS X Internals: The Book">Mac OS X Internals</a> book, to understand occasional mysterious behavior in HFS+ volumes, to <a href="http://www.osxbook.com/blog/2008/07/23/extending-hfsdebug/" title="Extending HFSDebug">search for file system objects</a>, to generate interesting file system statistics (top N largest files, top N fragmented files, resource forks vs data forks, <a href="http://www.osxbook.com/software/hfsdebug/#FREESPACE" title="Determining Free Space Fragmentation with HFSDebug">contiguous free space</a>, and so on), and to create interesting demos. (For example, to show HFS+ mechanisms such as <em>Hot File Clustering</em> and <em>On-the-Fly Defragmentation</em> at work.)</p>
<p>HFS+ is the preferred and default volume format on Mac OS X. Even with exciting new developments such as ZFS support in Mac OS X, I don&#8217;t expect HFS+ to become obsolete any time soon. Today&#8217;s Macintosh computers, iPods, iPhones, and AppleTV&#8217;s all use HFS+.</p>
<p>With most major releases of Mac OS X, HFS+ has gained new capabilities. Features such as metadata journaling, on-the-fly file defragmentation, hot file clustering, extended attributes, access control lists, hard link chains (tracking hard links), and directory hard links have come to HFS+ in recent years. There have been &#8220;<a href="http://arstechnica.com/journals/apple.ars/2008/10/27/new-snow-leopard-build-released-with-partial-cocoa-finder">news</a> <a href="http://www.appleinsider.com/articles/08/10/25/new_snow_leopard_seed_leak_confirms_cocoa_finder_more.html">reports</a>&#8221; of <em>compression</em> being an upcoming feature in HFS+.</p>
<p>The most interesting technical things about HFS+ are not its features, but how several of the newer features are implemented. With the goal of retaining backward compatibility, new features have often been retrofitted, or <em>shoehorned</em>, if you will, into HFS+. Knowing such implementation details evokes different reactions in different people, ranging from <em>&#8220;That&#8217;s a nifty way to implement this!&#8221;</em> to <em>&#8220;Gross!&#8221;</em> This is something you can decide for yourself with the help of HFSDebug, which can show you <em>exactly</em> how the file system works.</p>
<h3>New Features in HFSDebug</h3>
<p>Now, every time a new feature is added to HFS+, HFSDebug likely (but not always) needs to be updated, say, to recognize and parse a new type of on-disk object such as a directory hard link. I&#8217;m releasing a <a href="http://osxbook.com/software/hfsdebug/#DOWNLOAD" title="Download HFSDebug">new version of HFSDebug</a> that has the following improvements.</p>
<ul style="list-style: square;">
<li>Ability to show details of directory hard links.</li>
<li>Ability to show details of hard link chains.</li>
<li>New <a href="http://osxbook.com/software/hfsdebug/#FILTERS" title="HFSDebug Filters">built-in filters</a>: <code>atime</code> (find files by access time), <code>dirhardlink</code> (list directory hard links), <code>hardlink</code> (list file hard links), and <code>sxid</code> (list setuid/setgid files).</li>
<li>Ability to do component-wise path lookup from scratch, allowing you to analyze individual file system objects by <em>path</em> even on unmounted HFS+ volume.</li>
<li>Support for Snow Leopard.</li>
<li>Numerous subtle improvements and some bugfixes.</li>
</ul>
<div style="background-color: #eaeaf4; border: 1px solid #c0c0ff; padding: 1em;">
<h3 style="border-bottom: 1px solid #808080;">Still a PowerPC binary!?</h3>
<p>
It may be surprising (or troubling) to some of you that there is still no x86 version of HFSDebug: it&#8217;s available only as a PowerPC executable. Well, there <em>is</em> some logic to this madness. You see, I wrote HFSDebug in the &#8220;Panther&#8221; (10.3) days. Mac OS X was PowerPC-only then. It was also big endian. That matters because HFS+ uses big endian for its on-disk structures.
</p>
<p>
HFSDebug is a complex program. It essentially reads raw data from an HFS+ disk (say, a partition on a real disk or a disk image) and recreates a read-only HFS+ file system in memory. To simplify matters, I decided to skip structure-by-structure, field-by-field endianness conversion&mdash;after all, I <em>was</em> only targeting the big-endian-only Mac OS X. By contrast, the xnu kernel&#8217;s HFS+ implementation <em>does</em> do byte swapping on x86. So does the <code>fsck_hfs</code> program.
</p>
<p>
As long as Rosetta exists, HFSDebug can get away with being a PowerPC executable, allowing me to defer the grunt work of swapping bytes to a later date.
</p>
</div>
<p>Let us take the new HFSDebug features for a spin.</p>
<h3>Hard Link Chains</h3>
<p>Although support for file hard links has been there in HFS+ before Leopard, the new chaining feature in Leopard can keep track of hard link chains, which are doubly linked list of file IDs connecting hard links together. Hard links to a file on HFS+ are conceptually similar to those on Unix systems: They represent multiple directory entries referring to common file content. Implementation-wise, HFS+ hard links use a special <em>hard-link file</em> for each directory entry. The common file content is stored in a special file: the <em>indirect-node file</em>. All indirect-node files are stored in the <em>private metadata folder</em>, a special directory (<code><nobr>/\xE2\x90\x80\xE2\x90\x80\xE2\x90\x80\xE2\x90\x80HFS+ Private Data</nobr></code>) that&#8217;s both normally invisible to the user and has a name that&#8217;s &#8220;hard&#8221; to type. It&#8217;s much easier to understand this through HFSDebug.</p>
<p>We begin by creating a file called <code>file1</code>. Before we create a hard link to this file, we examine its details using HFSDebug. That way, we can tell if anything about the file changes after link creation.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>mkdir /tmp/test/</strong>
$ <strong>cd /tmp/test</strong>
$ <strong>echo "This is file1" > file1</strong>
$ <strong>sudo hfsdebug file1</strong>
...
  path                 = Leopard HD:/private/tmp/test/file1
# Catalog File Record
  type                 = file
<span style="background-color: #00f000;">  file ID              = 1927091</span>
  flags                = 0000000000000010
...
  # BSD Info
<span style="background-color: #00f000;">  ownerID              = 501 (singh)
  groupID              = 0 (wheel)</span>
  adminFlags           = 00000000
<span style="background-color: #00f000;">  ownerFlags           = 00000000</span>
  fileMode             = -rw-r--r--
  linkCount            = 1
  textEncoding         = 0
  attrBlocks           = 0
  # Finder Info
<span style="background-color: #00f000;">  fdType               = 0
  fdCreator            = 0
  fdFlags              = 0000000000000000</span>
...
</pre>
<p></code></p>
<p>Let us now make a hard link to this file.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>ln file1 file2</strong>
</pre>
<p></code></p>
<p>Let us see if anything has changed about <code>file1</code> now that we made a hard link <em>to</em> it.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>sudo hfsdebug file1</strong>
...
  path                 = Leopard HD:/private/tmp/test/file1
# Catalog File Record
  type                 = file (hard link)
  indirect node file   = Leopard HD:/%0000%0000%0000%0000HFS+ Private Data/iNode1927091
<span style="background-color: #00f000;">  file ID              = 1927094</span>
  flags                = 0000000000100010
                       . File has a thread record in the catalog.
<span style="background-color: #00f000;">                       . File has hardlink chain.</span>
...
  # BSD Info
<span style="background-color: #00f000;">  ownerID              = 1927095 (previous link ID)
  groupID              = 0 (next link ID)</span>
  adminFlags           = 00000000
<span style="background-color: #00f000;">  ownerFlags           = 00000010
                       . UF_IMMUTABLE (file may not be changed)</span>
  fileMode             = -r--r--r--
<span style="background-color: #00f000;">  iNodeNum             = 1927091 (link reference number)</span>
  textEncoding         = 0
  attrBlocks           = 0
  # Finder Info
<span style="background-color: #00f000;">  fdType               = 0x686c6e6b (hlnk)
  fdCreator            = 0x6866732b (hfs+)
  fdFlags              = 0000000100000000
                       . kHasBeenInited</span>
...
  # Data Fork
  logicalSize          = 0 bytes
  # Resource Fork
  logicalSize          = 0 bytes
</pre>
<p></code></p>
<p>We see that a <em>lot</em> has changed! The on-disk nature of <code>file1</code> has completely transformed. The original <code>content</code> has actually &#8220;moved&#8221; to an indirect-node file. What was <code>file1</code> before has been replaced with a new directory entry altogether: one that has a new file ID <em>within the file system</em>. The new directory entry is also a file, but with several special properties. Its &#8220;type&#8221; and &#8220;creator&#8221; (as stored in the Finder Info) are <code>hlnk</code> and <code>hfs+</code>, respectively. It has been marked immutable. It has no content in either its data fork or its resource fork. Moreover, the owner and group ID on-disk fields have been repurposed to act as the previous and next links, respectively, in the hard link chain. We see that the previous link ID is 1927095. Let us use HFSDebug to show us information for that ID.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>sudo hfsdebug -c 1927095</strong>
...
  path                 = Leopard HD:/private/tmp/test/file2
# Catalog File Record
  type                 = file (hard link)
  indirect node file   = Leopard HD:/%0000%0000%0000%0000HFS+ Private Data/iNode1927091
<span style="background-color: #00f000;">  file ID              = 1927095</span>
  flags                = 0000000000100010
                       . File has a thread record in the catalog.
<span style="background-color: #00f000;">                       . File has hardlink chain.</span>
...
  # BSD Info
<span style="background-color: #00f000;">  ownerID              = 0 (previous link ID)
  groupID              = 1927094 (next link ID)</span>
  adminFlags           = 00000000
<span style="background-color: #00f000;">  ownerFlags           = 00000010
                       . UF_IMMUTABLE (file may not be changed)</span>
  fileMode             = -r--r--r--
<span style="background-color: #00f000;">  iNodeNum             = 1927091 (link reference number)</span>
  textEncoding         = 0
  attrBlocks           = 0
  # Finder Info
<span style="background-color: #00f000;">  fdType               = 0x686c6e6b (hlnk)
  fdCreator            = 0x6866732b (hfs+)
  fdFlags              = 0000000100000000
                       . kHasBeenInited</span>
...
  # Data Fork
  logicalSize          = 0 bytes
  # Resource Fork
  logicalSize          = 0 bytes
</pre>
<p></code></p>
<p>We see that ID 1927095 corresponds to the other reference we just created: <code>file2</code>. The properties of this reference are similar to those of the other reference <code>file1</code>. They do differ in their file IDs. (They are indeed two separate on-disk file system objects.) They also differ in their previous and next links in the hard link chain. (We can confirm that <code>file1</code> and <code>file2</code> are connected together.)</p>
<p>The file&#8217;s content is in the indirect node file, which also now is the on-disk object with the original file ID (1927091). Let us use HFSDebug to look at that file.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>sudo hfsdebug -c 1927091</strong>
...
  path                 = Leopard HD:/%0000%0000%0000%0000HFS+ Private Data/iNode1927091
# Catalog File Record
  type                 = file
<span style="background-color: #00f000;">  file ID              = 1927095
  flags                = 0000000000100010
                       . File has a thread record in the catalog.
                       . File has hardlink chain.
  reserved1            = 1927095 (first link ID)</span>
...
  # BSD Info
<span style="background-color: #00f000;">  ownerID              = 501 (singh)
  groupID              = 0 (wheel)</span>
  adminFlags           = 00000000
  ownerFlags           = 00000000
...
  # Finder Info
<span style="background-color: #00f000;">  fdType               = 0x686c6e6b (hlnk)
  fdCreator            = 0x6866732b (hfs+)
  fdFlags              = 0000000100000000
                       . kHasBeenInited</span>
...
  # Data Fork
  logicalSize          = 14 bytes
  totalBlocks          = 1
  fork temperature     = no HFC record in B-Tree
  clumpSize            = 0
  extents              =   startBlock   blockCount      % of file
                             0xbb04b7          0x1       100.00 %
                         1 allocation blocks in 1 extents total.
                         1.00 allocation blocks per extent on an average.
  # Resource Fork
  logicalSize          = 0 bytes
</pre>
<p></code></p>
<p>As we see, the indirect-node file acts as the container for several of the original file&#8217;s properties. In particular, it has the original file&#8217;s content, the owner ID, and the group ID. A reserved field (<code>reserved1</code>) even contains the ID of the head of the hard link chain.</p>
<p>Of course, these are implementation details. HFS+ will show you the expected hard link semantics when you look at these files through the usual file system interfaces.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>ls -las file1 file2</strong>
1927091 8 -rw-r--r--  2 singh  wheel  14 Nov  3 21:55 file1
1927091 8 -rw-r--r--  2 singh  wheel  14 Nov  3 21:55 file2
$ <strong>cat file1 file2</strong>
This is file1
This is file1
</pre>
<p></code></p>
<p>We see that both <code>file1</code> and <code>file2</code> show up with identical metadata, including the same &#8220;inode&#8221; number as you would expect. They also &#8220;have&#8221; the same content.</p>
<p>Note that if you now delete one of the hard links, say, <code>file2</code>, things <em>will not</em> revert back to how they were to begin with. You will have <code>file1</code> as the only hard-link file along with the indirect-node file.</p>
<p>Let us look at directory hard links next.</p>
<h3>Directory Hard Links</h3>
<p>It&#8217;s not straightforward to create a directory hard link on Mac OS X. Well, that shouldn&#8217;t be surprising: directory hard links aren&#8217;t meant for third party developers, let alone users. They are essentially an implementation detail needed to make the Time Machine feature of Leopard work. Since we <em>are</em> talking about implementation details here, we will have to create a directory hard link or two&mdash;for experimentation, of course.</p>
<p>Leopard at the time of this writing requires the following conditions to be met for a directory hard link&#8217;s creation to be allowed. In the following list, &#8220;source&#8221; refers to the existing directory that will be pointed at by the new directory hard link &#8220;destination&#8221; that&#8217;s being created.</p>
<ul style="list-style: square;">
<li>The file system must be journaled HFS+.</li>
<li>The parent directories of the source and destination must be different.</li>
<li>The source&#8217;s parent must not be the root directory.</li>
<li>The destination must not be in the root directory.</li>
<li>The destination must not be a descendent of the source.</li>
<li>The destination must not have any ancestor that&#8217;s a directory hard link.</li>
</ul>
<p>If you meet all these conditions, you could create a directory hard link on an HFS+ volume under Mac OS X 10.5 and above. It&#8217;s then a matter of writing a program that uses the <code>link()</code> system call.</p>
<p><code></p>
<pre style="font-size: 85%;">
/* dirlink.c */

#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;

int
main(int argc, char** argv)
{
    int ret = -1;
    if (argc == 3) {
        ret = link(argv[1], argv[2]);
        if (ret) {
            perror("link");
        }
    }
    return ret;
}
</pre>
<p></code></p>
<p>In our <code>/tmp/test/</code> testing directory, we&#8217;ll create a directory <code>dir1</code> and a subdirectory <code>subdir</code>. It&#8217;s in <code>subdir</code> that we&#8217;ll create a hard link <code>dir2</code> to <code>dir1</code>. This is because <code>dir1</code> and <code>dir2</code> can&#8217;t have the same parent.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>gcc -Wall -o dirlink dirlink.c</strong>
$ <strong>mkdir dir1</strong>
$ <strong>mkdir subdir</strong>
</pre>
<p></code></p>
<p>Before we create the directory hard link, let us use HFSDebug to peek at the current on-disk details of <code>dir1</code>.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>sudo hfsdebug dir1</strong>
...
  path                 = Leopard HD:/private/tmp/test/dir1
# Catalog Folder Record
<span style="background-color: #00f000;">  type                 = folder
  folder ID            = 1927398</span>
  flags                = 0000000000000000
  valence              = 0
...
  # BSD Info
<span style="background-color: #00f000;">  ownerID              = 501 (singh)
  groupID              = 0 (wheel)</span>
  adminFlags           = 00000000
  ownerFlags           = 00000000
<span style="background-color: #00f000;">  fileMode             = drwxr-xr-x</span>
  linkCount            = 1
  textEncoding         = 0
  attrBlocks           = 0
  # Finder Info
  frRect               = (top = 0, left = 0), (bottom = 0, right = 0)
  frFlags              = 0000000000000000
  frLocation           = (v = 0, h = 0)
  opaque               = 0
  # Opaque Finder Info
  scrollPosition       = (v = 0, h = 0)
  reserved1            = 0
  Opaque Finder Flags  = 0000000000000000
  reserved2            = 0
  putAwayFolderID      = 0
</pre>
<p></code></p>
<p>Let us create the link and confirm that our expectations of directory hard link semantics are met.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>./dirlink dir1 subdir/dir2</strong>
$ <strong>ls -lasdi dir1 subdir/dir2</strong>
1927398 0 drwxr-xr-x  2 singh  wheel  68 Nov  3 22:59 dir1
1927398 0 drwxr-xr-x  2 singh  wheel  68 Nov  3 22:59 subdir/dir2
$ <strong>echo Hello > dir1/file</strong>
$ <strong>cat subdir/dir2/file</strong>
Hello
</pre>
<p></code></p>
<p>Everything looks in order. Let us now use HFSDebug to see what <em>actually</em> happened inside the file system. We looked at <code>dir1</code>&#8216;s on-disk details earlier. We can now see what changed after we created a directory hard link to <code>dir1</code>.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>sudo hfsdebug dir1</strong>
...
  path                 = Leopard HD:/private/tmp/test/dir1
# Catalog File Record
<span style="background-color: #00f000;">  type                 = file (alias, directory hard link)
  indirect folder      = Leopard HD:/.HFS+ Private Directory Data%000d/dir_1927398
  file ID              = 1927407
  flags                = 0000000000100010
                       . File has a thread record in the catalog.
                       . File has hardlink chain.</span>
...
  # BSD Info
<span style="background-color: #00f000;">  ownerID              = 1927408 (previous link ID)
  groupID              = 0 (next link ID)
  adminFlags           = 00000000
  ownerFlags           = 00000010
                       . UF_IMMUTABLE (file may not be changed)
  fileMode             = -r--r--r--
  iNodeNum             = 1927398 (link reference number)</span>
  textEncoding         = 0
  attrBlocks           = 0
  # Finder Info
<span style="background-color: #00f000;">  fdType               = 0x66647270 (fdrp)
  fdCreator            = 0x4d414353 (MACS)
  fdFlags              = 1000000000000000
                       . kIsAlias</span>
  fdLocation           = (v = 0, h = 0)
  opaque               = 0
  # Data Fork
  logicalSize          = 0 bytes
<span style="background-color: #00f000;">  # Resource Fork
  logicalSize          = 464 bytes</span>
  totalBlocks          = 1
  fork temperature     = no HFC record in B-Tree
  clumpSize            = 0
  extents              =   startBlock   blockCount      % of file
                             0xbae746          0x1       100.00 %
                         1 allocation blocks in 1 extents total.
                         1.00 allocation blocks per extent on an average.

<span style="background-color: #00f000;">  rsrc contents        = (up to 464 bytes)
       00 00 01 00 00 00 01 9e 00 00 00 9e 00 00 00 32 00 00 00 00 00 00 00 00
                                                     2
...
       00 00 00 00 00 00 00 1c 00 32 00 00 61 6c 69 73 00 00 00 0a 00 00 ff ff
                                   2        a  l  i  s
       00 00 00 00 00 00 00 00</span>
</pre>
<p></code></p>
<p>We see that <code>dir1</code>&#8216;s transformation is more drastic than what we had observed in the case of file hard links. After we created a directory hard link to <code>dir1</code>, it&#8217;s no longer a directory inside the file system. In fact, the &#8220;real&#8221; directory (that is, the link target) has moved to a special folder (<code>/.HFS+ Private Directory Data\xd</code>), just as the link target of a file hard link had moved to a (different) special folder. Its name within the special folder is <code>dir_1927398</code>, where the number represents the original &#8220;inode&#8221; number of <code>dir1</code>. However, <code>dir1</code> hasn&#8217;t been replaced by another directory that points to the link target&mdash;it has been replaced by a <em>file</em>, or specifically, an <em>alias</em>. (Backward compatibility!) The immutable alias file has <code>fdrp</code> and <code>MACS</code> as its type and creator codes, respectively. It also as a resource fork. Moreover, we see that as in the case of file hard links, there exists a hard link chain.</p>
<p>Let us also examine the link target using HFSDebug. The path would be &#8220;hard&#8221; to type because of the characters in the special folder&#8217;s name. We can use the folder ID instead, which would be the original ID of <code>dir1</code>.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>sudo hfsdebug -c 1927398</strong>
...
  path                 = Leopard HD:/.HFS+ Private Directory Data%000d/dir_1928557
# Catalog Folder Record
  type                 = folder
<span style="background-color: #00f000;">  folder ID            = 1927398
  flags                = 0000000000100100
                       . Folder has extended attributes.
                       . Folder has hardlink chain.</span>
  valence              = 0
...
  # BSD Info
<span style="background-color: #00f000;">  ownerID              = 501 (singh)
  groupID              = 0 (wheel)</span>
  adminFlags           = 00000000
  ownerFlags           = 00000000
  fileMode             = drwxr-xr-x
  linkCount            = 2
  textEncoding         = 0
  attrBlocks           = 0
  # Finder Info
  frRect               = (top = 0, left = 0), (bottom = 0, right = 0)
  frFlags              = 0000000000000000
  frLocation           = (v = 0, h = 0)
  opaque               = 0
...
# Attributes
...
  # Attribute Key
  keyLength            = 72
  pad                  = 0
  fileID               = 1927398
  startBlock           = 0
  attrNameLen          = 30
<span style="background-color: #00f000;">  attrName             = com.apple.system.hfs.firstlink</span>
  # Inline Data
  recordType           = 0x10
  reserved[0]          = 0
  reserved[1]          = 0
  attrSize             = 8 bytes
  attrData             = 31 39 32 37 34 30 38 00
<span style="background-color: #00f000;">                          1  9  2  7  4  0  8     </span>
</pre>
<p></code></p>
<p>We see mostly what we would expect given our previous observation of the implementation details of file hard links. There is one more thing in this case though: the folder has an extended attribute whose name is <code>com.apple.system.hfs.firstlink</code> and whose value is an encoding of the &#8220;inode&#8221; number of the head of the directory hard link chain.</p>
<h3>HFSDebug Filters</h3>
<p>At this point, you could use the built-in <code>dirhardlink</code> filter in HFSDebug to enumerate all directory hard links on the volume.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>sudo hfsdebug --filter=builtin:dirhardlink</strong>
2 links -> dir_1927398
Leopard HD:/private/tmp/test/dir1 -> dir_1927398
Leopard HD:/private/tmp/test/subdir/dir2 -> dir_1927398
</pre>
<p></code></p>
<p>The filter prints both link targets and link references. For a link target, the number of references to it is printed before it. For a link reference, the target that it points to is printed after it.</p>
<p>By the way, <a href="http://osxbook.com/software/hfsdebug/#FILTERS" title="HFSDebug Filters">filters</a> are a <em>very</em> useful recent addition to HFSDebug. A fundamental capability of HFSDebug is to go over all the entries in the HFS+ catalog file. It uses this capability to generate many types of statistics. The recently added filter support makes it possible for <em>you</em> to write a program that plugs into HFSDebug and receives a callback for each catalog file entry. That way, you can examine each entry, apply arbitrary criteria, and show (or not show) details about that entry. Say, you wish to list all setuid/setgid files on an HFS+ volume. Sure, you could run a <code>find</code> command to do that. On one of my HFS+ volumes with about a million files and 200K folders, <code>find</code> takes a while to do this.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>time sudo find / -xdev -type f \( -perm -4000 -o -perm -2000 \)</strong>
...
<span style="background-color: #00f000;">6.41s user 94.12s system 34% cpu 4:53.35 total</span>
$
</pre>
<p></code></p>
<p>You could do this <em>much</em> faster with the <code>sxid</code> built-in HFSDebug filter, whose implementation is a mere ten lines of C code. (Of course, the absolute time taken will also depend on the underlying hardware, but we are only interested in the relative time difference.)</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>time sudo hfsdebug --filter=builtin:sxid</strong>
...
<span style="background-color: #00f000;">2.86s user 9.33s system 17% cpu 1:08.04 total</span>
$
</pre>
<p></code></p>
<p>Note that many types of searches on HFS+ can also be done through the <code>searchfs()</code> system call, although it can be quite cumbersome to use. Of course, <code>searchfs()</code> cannot be done on an unmounted volume.</p>
<h3>Specifying File System Objects by Path on Unmounted Volumes</h3>
<p>As we have seen, a common use for HFSDebug is to have it display implementation details of individual file system objects. You could specify the object of interest in several ways: by providing its catalog node ID (CNID), by providing an &#8220;fsspec&#8221; style pair consisting of the parent folder&#8217;s CNID and the object&#8217;s name, or by providing a POSIX-style path to the object. The latter is often the easiest and most convenient to specify. However, until now, HFSDebug did not do component-wise path lookups itself&mdash;it used the operating system to convert the path to an inode number. This results in a few caveats. To begin with, it&#8217;s against the HFSDebug philosophy of <em>not relying</em> on the operating system for any HFS+-related operations. It also means that if the volume in question is not mounted (say, it&#8217;s corrupt and can&#8217;t be mounted or you are investigating something and don&#8217;t want to mount it), you can&#8217;t use paths to look at individual objects. You will have to dump all objects on the file system and then find the node ID of the object of interest. Moreover, even on a mounted volume, the operating system disallows path-based access to several files. (See Chapter 12 of <a href="http://osxbook.com/" title="Mac OS X Internals: The Book">Mac OS X Internals</a>.) In such cases, again you will need to know the node ID of the object of interest, even on a mounted volume.</p>
<p>I&#8217;ve &#8220;fixed this issue&#8221; (or &#8220;added the feature&#8221;, depending on how you look at it) in the new version of HFSDebug. Say, if you have an unmounted volume on <code>/dev/disk5s1</code> and you want to examine <code>/tmp/foo/bar</code> on it. Now you can simply do:</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>sudo hfsdebug -d /dev/disk5s1 /tmp/foo/bar</strong>
...
</pre>
<p></code></p>
<p>The semantics of symbolic link resolution are as follows. If the object (<code>bar</code> in this example) is a symbolic link itself, then HFSDebug will show you properties of <code>bar</code> and not what it points to. This is in line with HFSDebug philosophy and also how things work today on mounted volumes. If, however, a nonterminal component of the path is a symbolic link, HFSDebug <em>will</em> resolve it. Again, this is desirable.</p>
<p>That&#8217;s about it.</p>
<h3>One More Thing</h3>
<p>I can&#8217;t talk about HFSDebug&#8217;s Snow Leopard-specific features since the latter is under NDA. If you do have access to the latest Snow Leopard seed, try HFSDebug on it. For example, examine some standard Mac OS X files using HFSDebug.</p>
<p><code></p>
<pre style="font-size: 85%;">
$ <strong>sudo hfsdebug /bin/ls</strong>
...
$ <strong>sudo hfsdebug /etc/asl.conf</strong>
...
$ <strong>sudo hfsdebug /Applications/Mail.app/Contents/PkgInfo</strong>
...
</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://osxbook.com/blog/2008/11/09/hfsdebug-40-and-new-hfs-features/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>File Systems Are Cool</title>
		<link>http://osxbook.com/blog/2007/01/02/file-systems-are-cool/</link>
		<comments>http://osxbook.com/blog/2007/01/02/file-systems-are-cool/#comments</comments>
		<pubDate>Wed, 03 Jan 2007 06:49:31 +0000</pubDate>
		<dc:creator>amit</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Operating Systems]]></category>
		<category><![CDATA[The Book]]></category>

		<guid isPermaLink="false">http://www.osxbook.com/blog/2007/01/02/file-systems-are-cool/</guid>
		<description><![CDATA[Let us try to make them a little cooler on Mac OS X.]]></description>
			<content:encoded><![CDATA[<p><img src="/images/cool.jpg" width="512" height="384" style="border: none;" /></p>
<p>
<a href="http://www.macworldexpo.com/live/20/events/20SFO07A/conference/tracksessions/Mac%20OS%20X%20Management%20and%20Administration/QMONYA04SWWQ">Let us try to make them a little cooler on Mac OS X</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://osxbook.com/blog/2007/01/02/file-systems-are-cool/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Upcoming Conferences</title>
		<link>http://osxbook.com/blog/2006/11/28/upcoming-conferences/</link>
		<comments>http://osxbook.com/blog/2006/11/28/upcoming-conferences/#comments</comments>
		<pubDate>Tue, 28 Nov 2006 10:13:50 +0000</pubDate>
		<dc:creator>amit</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Operating Systems]]></category>
		<category><![CDATA[The Book]]></category>

		<guid isPermaLink="false">http://www.osxbook.com/blog/2006/11/28/upcoming-conferences/</guid>
		<description><![CDATA[I will be speaking at the following venues in the near future: Chaos Communication Congress, Berlin, Germany (December 29, 2006) Macworld Conference &#038; Expo, San Francisco, USA (January 11, 2007)]]></description>
			<content:encoded><![CDATA[<p>I will be speaking at the following venues in the near future:</p>
<ul style="list-style: square;">
<li><a href="http://events.ccc.de/congress/2006/Home">Chaos Communication Congress</a>, Berlin, Germany (December 29, 2006)</li>
<li><a href="http://www.macworldexpo.com/live/20/events/20SFO07A/conference/tracksessions/Mac%20OS%20X%20Management%20and%20Administration/QMONYA04SWWQ">Macworld Conference &#038; Expo</a>, San Francisco, USA (January 11, 2007)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://osxbook.com/blog/2006/11/28/upcoming-conferences/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>On Mac OS X Viruses</title>
		<link>http://osxbook.com/blog/2006/11/05/on-mac-os-x-viruses/</link>
		<comments>http://osxbook.com/blog/2006/11/05/on-mac-os-x-viruses/#comments</comments>
		<pubDate>Sun, 05 Nov 2006 22:41:15 +0000</pubDate>
		<dc:creator>amit</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Kernelthread.com]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Operating Systems]]></category>

		<guid isPermaLink="false">http://www.osxbook.com/blog/2006/11/05/on-mac-os-x-viruses/</guid>
		<description><![CDATA[I usually find the security-related smugness of Mac users rather jarring. What&#8217;s often even more jarring is the reasoning behind such smugness. That said, I have to say that the recent furor regarding the so called OSX.Macarena &#8220;virus&#8221; amounts to, well, bullshit. If anti-virus companies are pretending to &#8220;recognize the threat&#8221; and therefore attempting to [...]]]></description>
			<content:encoded><![CDATA[<p>
I usually find the security-related smugness of Mac users rather jarring. What&#8217;s often even more jarring is the reasoning behind such smugness. That said, I have to say that the <a href="http://apple.slashdot.org/apple/06/11/03/1724252.shtml">recent furor</a> regarding the so called <code>OSX.Macarena</code> &#8220;virus&#8221; amounts to, well, bullshit. <em>If</em> anti-virus companies are pretending to &#8220;recognize the threat&#8221; and therefore attempting to &#8220;increase awareness&#8221; by supporting the propagation of FUD, that&#8217;s not right, albeit understandable (viruses being relevant to their business and all). Far too many people use computers but far too few understand computers. This imbalance makes the situation quite lucrative for some.
</p>
<p>
According to an official &#8220;Technical Details&#8221; document, when <code>OSX.Macarena</code> is executed, it performs the following actions:
</p>
<ol style="list-style: decimal;">
<li>Infects other files when they are executed in the current directory, regardless of file name or extension.</li>
</ol>
<p>
Let us get some context in here. Let me quote something from one of my old writings on Unix viruses:
</p>
<div style="background-color: #EAEAF4;">
<p>
Unix has the reputation of being &#8220;not so buggy,&#8221; and of being a good maintainer of system sanctity via good protection mechanisms (in particular, a supervisor mode that is supposed to be very hard to attain for a non-super-user).<br />
</em></p>
<p>
You do <em>not</em> need to exploit bugs in an operating system to have viruses. Essentially all operating systems provide prerequisites for supporting a computer virus. Similarly, supervisor mode is not necessary for viral activity, and in any case, supervisor mode may be obtained through virus-unrelated security holes. Moreover, the number of reported viruses on a particular platform is not an indicator of the feasibility (either way) of viruses on that platform.
</p>
<p>
A typical definition of a computer virus might have aspects such as the following:
</p>
<ul style="list-style: square;">
<li>A virus attacks specific file types (or files).</li>
<li>A virus manipulates a program to execute tasks unintentionally.</li>
<li>An infected program produces more viruses.</li>
<li>An infected program may run without error for a long time.</li>
<li>Viruses can modify themselves and may possibly escape detection this way.</li>
</ul>
<p>
Note that none of the above requirements is automatically ruled out on Unix.
</p>
</div>
<p>
Well, Unix viruses are hardly new. Fred Cohen, who pioneered the formal definition and study of computer viruses, implemented a Unix virus in 1983. The virus ran on a VAX 11/750 system. Dennis Ritchie, one of the inventors of UNIX, had the following to say about Unix viruses:
</p>
<div style="background-color: #EAEAF4;">
<cite><br />
&#8220;A few years ago Tom Duff created a very persistent UNIX virus. At that point we had about 10-12 8<sup>th</sup> or 9<sup>th</sup> edition VAX 750s networked together. The virus lived in the slack space at the end of the executable, and changed the entry point to itself. When the program was executed, it searched the current directory, subdirectories, <code>/bin</code>, <code>/usr/bin</code> for writable, uninfected files and then infected them if there was enough space.&#8221;<br />
</cite>
</div>
<p>
Does that sound familiar? This was in the late 1980s.
</p>
<p>
In reaction to a similar controversy as we are talking about now, I wrote a portable &#8220;Unix virus&#8221; as a trivial C program many, many years ago. I called it the <em>Jingle Bell Virus</em> since I wrote it in the Bell Labs cafeteria at Murray Hill, NJ. Jingle Bell attaches itself to the first executable found on the command line. Of course, you can configure the infection scheme to whatever you want. You can read Jingle Bell&#8217;s source code and also &#8220;see it in action&#8221; on the following page:
</p>
<ul style="list-style: square;">
<li><a href="http://www.kernelthread.com/publications/security/vunix.html#JINGLE_BELL" title="Viruses on Unix: Jingle Bell: A Simple Virus in C">Viruses on Unix: Jingle Bell: A Simple Virus in C</a> [kernelthread.com]</li>
</ul>
<p>
Somebody has even trivially ported Jingle Bell to the Plan 9 operating system. You can find it in one of the <code>contrib</code> subdirectories within the Plan 9 source distribution. You can just as easily port it to Mac OS X (by &#8220;easily&#8221;, I mean change the value of the constant <code>V_OFFSET</code> in the code and recompileâ€”that&#8217;s it).
</p>
<p>
What this newborn Mac OS X virus essentially demonstrates is merely a manifestation of how operating systems work. Portraying this as a newly found threat is just not right, at least if you do so without clarifying that this is how operating systems work; you can do this on any operating system in general; you could do this on ancient UNIX; the real threat is not <em>every such individual program</em> but flaws that might allow such malware to spread; and so on. And no, the fact that this particular one does its job by mucking with Mach-O structures doesn&#8217;t justify the terror alarm. What&#8217;s next? Saying that <em>&#8220;Mac OS X allows sensitive information to be leaked (because you can read files on Mac OS X)&#8221;</em>? Wouldn&#8217;t it be far more worthy and worthwhile to point out <em>and</em> address <em>real</em> vulnerabilities in Mac OS X?
</p>
<p>
To be fair, if there indeed is no FUD involved and the parties involved are truly well meaning, now that I&#8217;ve made Jingle Bell public (well, I made it public many years ago and the relevant page has been accessed hundreds of thousands of times), shouldn&#8217;t it also be on the anti-virus lists for all operating systems it can be compiled on? While we are at it, we should also read all relevant academic papers and include any viruses found therein too.
</p>
<p>
It should not be any harder to <em>write</em> a virus for Unix (and Mac OS X) than it would be for any other system. However, <em>spreading</em> a virus would have different logistics on Unix as compared to, say, Windows. Given the default <em>usage scenarios</em> (note that I&#8217;m not saying <em>design</em> or <em>architecture</em>) of Windows and Unix, it is generally harder to spread such things on Unix. That said, Mac OS X <em>does</em> have some potentially <em>very</em> troublesome aspects. (Think about what an admin user on Mac OS X can doâ€”by defaultâ€”in terms of file permissions.) So, I am not saying everything is rosy and wonderful for Mac OS X. <em>Please be wary of that creeping smugness.</em>
</p>
<p>
Rather than repeat many other details here, let me refer those interested in the history and nature of digital life forms to some more things I have written in the past:
</p>
<ul style="list-style: square;">
<li><a href="http://kernelthread.com/publications/security/viruses.html">Digital Life: Viruses</a> [kernelthread.com]</li>
<li><a href="http://kernelthread.com/publications/security/worms.html">Digital Life: Worms</a> [kernelthread.com]</li>
<li><a href="http://kernelthread.com/publications/security/vunix.html">Viruses on Unix</a> [kernelthread.com]</li>
</ul>
<p>
All these are sections within the following bigger document:
</p>
<ul style="list-style: square;">
<li><a href="http://kernelthread.com/publications/security/">A Taste of Computer Security</a> [kernelthread.com]</li>
</ul>
<p>
Besides these, there is an abundance of academic papers and articles on computer viruses and worms. Just search.</p>
]]></content:encoded>
			<wfw:commentRss>http://osxbook.com/blog/2006/11/05/on-mac-os-x-viruses/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>For the Record&#8230;</title>
		<link>http://osxbook.com/blog/2006/11/04/for-the-record/</link>
		<comments>http://osxbook.com/blog/2006/11/04/for-the-record/#comments</comments>
		<pubDate>Sat, 04 Nov 2006 16:14:37 +0000</pubDate>
		<dc:creator>amit</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Mac OS X]]></category>

		<guid isPermaLink="false">http://www.osxbook.com/blog/2006/11/04/for-the-record/</guid>
		<description><![CDATA[After I published Understanding Apple&#8217;s Binary Protection in Mac OS X, eWeek published a story on Apple&#8217;s binary encryption: Apple Places Encrypted Binaries in Mac OS X Although there&#8217;s nothing excessively misleading or incorrect in the story, to me, some parts of the story sounded like I had a conversation with eWeek. I did not. [...]]]></description>
			<content:encoded><![CDATA[<p>After I published <a href="/book/bonus/chapter7/binaryprotection" title="Understanding Apple's Binary Protection in Mac OS X">Understanding Apple&#8217;s Binary Protection in Mac OS X</a>, eWeek published a story on Apple&#8217;s binary encryption:</p>
<p><a href="http://www.eweek.com/article2/0,1759,2050875,00.asp">Apple Places Encrypted Binaries in Mac OS X</a></p>
<p>Although there&#8217;s nothing excessively misleading or incorrect in the story, to me, some parts of the story sounded like I had a conversation with eWeek. I did <em>not</em>. eWeek did contact me for comment but I wasn&#8217;t able to respond to them.</p>
]]></content:encoded>
			<wfw:commentRss>http://osxbook.com/blog/2006/11/04/for-the-record/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trusted Computing for Mac OS X</title>
		<link>http://osxbook.com/blog/2006/10/31/trusted-computing-for-mac-os-x/</link>
		<comments>http://osxbook.com/blog/2006/10/31/trusted-computing-for-mac-os-x/#comments</comments>
		<pubDate>Tue, 31 Oct 2006 19:30:31 +0000</pubDate>
		<dc:creator>amit</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Operating Systems]]></category>

		<guid isPermaLink="false">http://www.osxbook.com/blog/2006/11/01/trusted-computing-for-mac-os-x/</guid>
		<description><![CDATA[Read about how to enable trusted computing on Mac OS X. The document&#8217;s coverage includes: A discussion of the TPM hardware present in certain Macintosh computers Release of an open source TPM driver for Mac OS X Release of a Mac OS X port of an open source trusted computing software stack An overview of [...]]]></description>
			<content:encoded><![CDATA[<p>Read about <a href="/book/bonus/chapter10/tpm" title="Trusted Computing for Mac OS X">how to enable trusted computing on Mac OS X</a>. The document&#8217;s coverage includes:</p>
<ul style="list-style: square;">
<li>A discussion of the TPM hardware present in certain Macintosh computers</li>
<li>Release of an open source TPM driver for Mac OS X</li>
<li>Release of a Mac OS X port of an open source trusted computing software stack</li>
<li>An overview of using the driver and the software stack</li>
<li>Miscellaneous tidbits</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://osxbook.com/blog/2006/10/31/trusted-computing-for-mac-os-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mac OS X Internals Workshop Flyer</title>
		<link>http://osxbook.com/blog/2006/08/08/mac-os-x-internals-workshop-flyer/</link>
		<comments>http://osxbook.com/blog/2006/08/08/mac-os-x-internals-workshop-flyer/#comments</comments>
		<pubDate>Tue, 08 Aug 2006 16:18:40 +0000</pubDate>
		<dc:creator>amit</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[The Book]]></category>

		<guid isPermaLink="false">http://www.osxbook.com/blog/2006/08/08/mac-os-x-internals-workshop-flyer/</guid>
		<description><![CDATA[Something to look at: Mac OS X Internals Flyer]]></description>
			<content:encoded><![CDATA[<p>Something to look at:</p>
<p><a href="http://www.osxbook.com/book/flyer/flyer.html">Mac OS X Internals Flyer</a></p>
]]></content:encoded>
			<wfw:commentRss>http://osxbook.com/blog/2006/08/08/mac-os-x-internals-workshop-flyer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

