<?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>64k &#187; installation</title>
	<atom:link href="http://www.64k-tec.de/tag/installation/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.64k-tec.de</link>
	<description>Software development and more ...</description>
	<lastBuildDate>Tue, 10 Jan 2012 21:58:41 +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>FRITZ!Box tuning part 4: Cross-building and installing additional applications</title>
		<link>http://www.64k-tec.de/2011/07/fritzbox-tuning-part-4-cross-building-and-installing-additional-applications/</link>
		<comments>http://www.64k-tec.de/2011/07/fritzbox-tuning-part-4-cross-building-and-installing-additional-applications/#comments</comments>
		<pubDate>Tue, 26 Jul 2011 20:14:36 +0000</pubDate>
		<dc:creator>cp</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Root]]></category>
		<category><![CDATA[administration]]></category>
		<category><![CDATA[boot]]></category>
		<category><![CDATA[Buildroot]]></category>
		<category><![CDATA[Console]]></category>
		<category><![CDATA[cross-building]]></category>
		<category><![CDATA[cross-compiling]]></category>
		<category><![CDATA[dropbear]]></category>
		<category><![CDATA[firmware]]></category>
		<category><![CDATA[FritzBox]]></category>
		<category><![CDATA[gcc]]></category>
		<category><![CDATA[glibc]]></category>
		<category><![CDATA[installation]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MIPS]]></category>
		<category><![CDATA[OpenSSH]]></category>
		<category><![CDATA[overlay]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[tmpfs]]></category>
		<category><![CDATA[Toolchain]]></category>

		<guid isPermaLink="false">http://www.64k-tec.de/?p=2338</guid>
		<description><![CDATA[The articles I wrote about the FRITZ!Box are pretty popular. They are creating the most traffic on my website. I understand this, cause the FRITZ!Box is a really great piece of hardware and AVM is also a company which knows how to make their users happy by serving regular updates to the firmware. Although I [...]]]></description>
			<content:encoded><![CDATA[<p>The articles I wrote about the <a href="/tag/fritzbox/" target="_blank">FRITZ!Box</a> are pretty popular. They are creating the most traffic on my website. I understand this, cause the FRITZ!Box is a really great piece of hardware and AVM is also a company which knows how to make their users happy by serving regular updates to the firmware. Although I didn't tuned my FRITZ!Box any further, I updated it with the latest <a href="http://www.avm.de/de/Service/Service-Portale/Labor/index.php" target="_blank">Labor</a> firmware version regularly. At some point the sshd setup (with dropbear) doesn't worked anymore and I decided it is the time to update my software as well. Beside that it didn't work anymore it is always a good idea to update software which allow access to a host from everywhere very regularly. Anyway, it turned out this isn't as simple as I initial thought. Therefore here is the next post in the FRITZ!Box tuning series, which shows how to cross-build software for the MIPS32 architecture used in the FRITZ!Box and in particular get the sshd software to life again. I use a FRITZ!Box Fon WLAN 7270 v2 and the firmware is 54.05.05. Please make sure you read the other <a href="/tag/fritzbox/" target="_blank">FRITZ!Box articles</a> as well, cause some of the information given there still applies.</p>
<span class="sb_alert">As already mentioned in the other articles, there is no warranty that this will work on your side and I am not responsible for any damage which may happen. You have been warned!</span>
<h2>Cross-building for the MIPS32 architecture</h2>
<p>The FRITZ!Box itself doesn't include any build tools. Why should it! It's an end-consumer product which is usually never changed, beside the user is updating it with an official firmware update. So we have to do it ourself. Creating a build chain for another architecture is usually <a href="http://www.landley.net/writing/docs/cross-compiling.html" target="_blank">hard</a>. There are several things you have to consider. This includes problems with the configuration, endianess differences between the host and the target, bit depths and depending shared libraries which have to be available in the target format. Fortunately this is a common problem, especially for embedded systems, which means there is a proper solution called <a href="http://buildroot.uclibc.org/" target="_blank">Buildroot</a> (look at the first line in <code class="cmd">dmsg</code>, when the FRITZ!Box has booted and you know what I mean). Buildroot is a build system which allows, similar to the Linux kernel, configuring and generating complete embedded Linux systems. Regardless how configured, Buildroot builds a complete Linux system, always. This is of course a little bit overhead for us, but we just pick out the relevant files. First we need to know which architecture we target. You have to login into the FRITZ!Box either using <a href="http://www.64k-tec.de/2010/01/fritzbox-tuning-part-1-enable-remote-access-over-ssh/" target="_blank">telnet or a working ssh daemon</a>. To get some information about the hardware used in your FRITZ!Box execute <code class="cmd">cat /proc/cpuinfo</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># cat /proc/cpuinfo
system type             : TI UR8 (7270)
processor               : 0
cpu model               : MIPS 4KEc V6.8
BogoMIPS                : 359.62
wait instruction        : yes
microsecond timers      : yes
tlb_entries             : 16
extra interrupt vector  : yes
hardware watchpoint     : no
ASEs implemented        :
shadow register sets    : 1
core                    : 0
VCED exceptions         : not available
VCEI exceptions         : not available</pre></div></div>

<p>Here we learn that the FRITZ!Box is using a <a href="http://www.mips.com/products/cores/hard-ip-cores/4kec-hard-ip-cores/" target="_blank">MIPS</a> processor. In this case it uses the <a href="http://en.wikipedia.org/wiki/Endianness" target="_blank">little-endian</a> format. Next you need some information about the system C library. On normal Linux (desktop) systems the GNU C Library is used. This library is heavyweight and therefore the <a href="http://uclibc.org/" target="_blank">uClibc</a> was invented for embedded systems. By executing <code class="cmd">ls /lib/libuClibc*</code> you get the version installed. In my case it is 0.9.31. Now we have all information needed to configure Buildroot. <a href="http://buildroot.uclibc.org/download.html" target="_blank">Download</a> and extract the source of Buildroot.</p>
<span class="sb_tip">If you are working on a Mac like me (where Buildroot doesn't work), <a href="http://www.virtualbox.org/" target="_blank">VirtualBox</a> with a Linux system as a guest is a good alternative <img src='http://www.64k-tec.de/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</span>
<p>By executing <code class="cmd">make menuconfig</code> in the root directory of Buildroot you are able to configure it. The most important options are <strong>Target Architecture</strong>, set this to <code>mipsel</code> and <strong>Target Architecture Variant</strong>, set this to <code>mips 32r2</code>. In <strong>Toolchain -&gt; uClibc C library Version</strong> select a version which is close to the one on your FRITZ!Box. Next you have to select which packages should be build in <strong>Package Selection for the target</strong>. Choose whatever you want but for the beginning <strong>Networking applications -&gt; openssh</strong> might be enough. If you prefer a more lightweight ssh implementation <strong>dropbear</strong> may also an option. In the following we use OpenSSH. You can also tweak the build options, like the <code class="cmd">gcc</code> version to use or set the gcc optimization level to <code>-O3</code> in favor of size. After saving the configuration and executing <code class="cmd">make</code>, it is time for a coffee. When the build has been finished all relevant files are in <code class="path">output/target/</code>. We only pack the directories and files which are necessary. For example the <code>libuClibc</code> was built by Buildroot, but we will use the one from the FRITZ!Box. The following create a zip archive of the files for OpenSSH.<a name="zip"></a></p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">zip -r ../../local.zip &quot;lib/libutil* lib/libnsl* lib/libresolv* \
 lib/libcrypt* usr/lib usr/share usr/sbin usr/bin etc/ssh_config \
 etc/sshd_config&quot;</pre></div></div>

<h2>Creating overlay directories on the root filesystem</h2>
<p>The following is based on ideas invented by the guys at <a href="http://www.spblinux.de/fbox.new/" target="_blank">http://www.spblinux.de/</a>. Our aim is it to have as little persistent changes on the FRITZ!Box as possible. This allows us to go back to the original state with a simple reboot. Therefore all writeable directories will be on a <a href="http://en.wikipedia.org/wiki/Tmpfs" target="_blank">tmpfs</a> filesystem. tmpfs filesystems are created in RAM and the content will be removed when the filesystem is unmounted. Because the FRITZ!Box has only limited RAM, we will not copy our applications into the tmpfs filesystem, but just create symbolic links to the files on the USB stick (where usually much more space is available). Because we want the applications from the FRITZ!Box and our own one be accessible from the root filesystem, we need to merge both into the tmpfs directory. Therefore first symbolic links into the original filesystem and second symbolic links to the USB stick are created. The second step is only performed when there isn't a file already. This makes sure the original files are always preferred over our own one. The last step is binding the directories to the root filesystem. Summarized the following will be done:</p>
<ol>
<li>remount <code class="path">/</code> readonly</li>
<li>mount <code class="path">/</code> into <code class="path">/var/_ro_</code></li>
<li>create tmpfs in <code class="path">/var/_overlay_</code></li>
<li>symlink the files from <code class="path">/var/_ro_</code> into <code class="path">/var/_overlay_</code></li>
<li>symlink the files from the USB stick into <code class="path">/var/_overlay_</code></li>
<li>bind the directories in <code class="path">/var/_overlay_</code> to <code class="path">/</code></li>
</ol>
<p>This script does the previous steps. It uses helper methods which are defined in <code class="path">common.sh</code>. You will find all the necessary files in the package you can download at the end of this article.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/sh</span>
&nbsp;
. common.sh
&nbsp;
<span style="color: #007800;">MNT</span>=<span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>_overlay_
<span style="color: #007800;">BASE_RO</span>=<span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>_ro_
<span style="color: #007800;">BASE_OVL</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${BASE}</span>/local&quot;</span>
&nbsp;
<span style="color: #007800;">DIRS</span>=<span style="color: #ff0000;">&quot;lib etc usr/bin usr/sbin usr/lib usr/share&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># remount root readonly</span>
<span style="color: #ff0000;">&quot;<span style="color: #007800;">${MOUNT}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${GREP}</span>&quot;</span> <span style="color: #ff0000;">&quot;/dev/root&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${GREP}</span>&quot;</span> <span style="color: #660033;">-q</span> ro
<span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$?</span> <span style="color: #660033;">-eq</span> <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> _lmt <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>root <span style="color: #000000; font-weight: bold;">/</span> <span style="color: #ff0000;">&quot;-o remount -r&quot;</span>
<span style="color: #666666; font-style: italic;"># bind root into var</span>
_lchkmnt <span style="color: #ff0000;">&quot;<span style="color: #007800;">${BASE_RO}</span>&quot;</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$?</span> <span style="color: #660033;">-eq</span> <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
  _lmkdir <span style="color: #ff0000;">&quot;<span style="color: #007800;">${BASE_RO}</span>&quot;</span>
  _lmnt <span style="color: #000000; font-weight: bold;">/</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${BASE_RO}</span>&quot;</span> <span style="color: #ff0000;">&quot;-o bind&quot;</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># create our overlay dir</span>
_lchkmnt <span style="color: #ff0000;">&quot;<span style="color: #007800;">${MNT}</span>&quot;</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$?</span> <span style="color: #660033;">-eq</span> <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
  _lmkdir <span style="color: #ff0000;">&quot;<span style="color: #007800;">${MNT}</span>&quot;</span>
  _lmnt tmpfs <span style="color: #ff0000;">&quot;<span style="color: #007800;">${MNT}</span>&quot;</span> <span style="color: #ff0000;">&quot;-t tmpfs&quot;</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># link/copy the base stuff</span>
<span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${DIRS}</span>; <span style="color: #000000; font-weight: bold;">do</span>
  _lsymlnk_dir <span style="color: #ff0000;">&quot;<span style="color: #007800;">${BASE_RO}</span>&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${i}</span>&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${MNT}</span>&quot;</span>
<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># link/copy our own stuff</span>
<span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${DIRS}</span>; <span style="color: #000000; font-weight: bold;">do</span>
  _lsymlnk_dir <span style="color: #ff0000;">&quot;<span style="color: #007800;">${BASE_OVL}</span>&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${i}</span>&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${MNT}</span>&quot;</span>
<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># now bind all overlay dirs to root</span>
<span style="color: #666666; font-style: italic;"># (this is critical don't interupt)</span>
<span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${DIRS}</span>; <span style="color: #000000; font-weight: bold;">do</span>
  _lmnt <span style="color: #ff0000;">&quot;<span style="color: #007800;">${MNT}</span>/<span style="color: #007800;">${i}</span>&quot;</span> <span style="color: #ff0000;">&quot;/<span style="color: #007800;">${i}</span>&quot;</span> <span style="color: #ff0000;">&quot;-o bind&quot;</span>
<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">0</span></pre></div></div>

<p>Now copy the zip archive you have created <a href="#zip">above</a> to the FRITZ!Box and unpack it on the USB stick in <code class="path">addons/local/</code>. The scripts have to be placed into <code class="path">addons/</code>. You need to configure the following in <code class="path">common.sh</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># the base of the usb stick goes here:
BASE=&quot;/var/media/ftp/FLASH-DISK-01/addons&quot;
# add the encrypted root password here:
PASS=&quot;&quot;</pre></div></div>

<p>Point to the base directory within the USB stick in <code>BASE</code>. Also add your encrypted root password into <code>PASS</code>. This will create a root user in <code class="path">/etc/passwd</code> automatically.</p>
<p>If you believe all is correct, you can start the installation by executing <code class="cmd">./install.sh</code>. If no errors are shown, you can try ssh. <code class="cmd">ssh -v</code> should output something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># ssh -v
OpenSSH_5.8p2, OpenSSL 1.0.0d 8 Feb 2011
...</pre></div></div>

<p>Additional to the standard filesystems mounted, you should see the following when executing <code class="cmd">mount</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"># mount
...
/dev/root on /var/_ro_ type squashfs (ro,relatime)
tmpfs on /var/_overlay_ type tmpfs (rw,relatime)
tmpfs on /lib type tmpfs (rw,relatime)
tmpfs on /etc type tmpfs (rw,relatime)
tmpfs on /usr/bin type tmpfs (rw,relatime)
tmpfs on /usr/sbin type tmpfs (rw,relatime)
tmpfs on /usr/lib type tmpfs (rw,relatime)
tmpfs on /usr/share type tmpfs (rw,relatime)</pre></div></div>

<h2>Configure and start the OpenSSH daemon</h2>
<p>Now that we have our brand new OpenSSH on the FRITZ!Box working, we need some last steps to let the daemon running correctly. First create a private/public RSA host key pair for the server process by executing:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">ssh-keygen -t rsa -f addons/config/ssh_host_rsa_key</pre></div></div>

<p><code class="path">addons/config/</code> have to be an existing directory below the USB stick base. Next create a file <code class="path">addons/config/sshd_config</code> in the same directory with the following content:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">Protocol               2
UsePrivilegeSeparation no
Subsystem              sftp /usr/lib/sftp-server</pre></div></div>

<p>The following script could be use to start the <code class="cmd">sshd</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/sh</span>
&nbsp;
. common.sh
&nbsp;
<span style="color: #007800;">SSHD</span>=<span style="color: #ff0000;">&quot;/usr/sbin/sshd&quot;</span>
<span style="color: #007800;">SSH_SPKEY</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${BASE}</span>/config/ssh_host_rsa_key&quot;</span>
<span style="color: #007800;">SSH_CFG</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${BASE}</span>/config/sshd_config&quot;</span>
<span style="color: #007800;">SSH_TPKEY</span>=<span style="color: #ff0000;">&quot;/var/tmp/ssh_host_rsa_key&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># sanity check</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${SSHD}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> _lce <span style="color: #007800;">$?</span> <span style="color: #ff0000;">&quot;sshd not installed&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># start in tmp</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>tmp   
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">mount</span> <span style="color: #660033;">-o</span> remount devpts <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>pts <span style="color: #660033;">-t</span> devpts
&nbsp;
<span style="color: #666666; font-style: italic;"># cp key and make them user readable only</span>
_lcp_file <span style="color: #ff0000;">&quot;<span style="color: #007800;">${SSH_SPKEY}</span>&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${SSH_TPKEY}</span>&quot;</span>
_lchmod <span style="color: #000000;">400</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${SSH_TPKEY}</span>&quot;</span>             
&nbsp;
<span style="color: #666666; font-style: italic;"># start sshd</span>
<span style="color: #ff0000;">&quot;<span style="color: #007800;">${SSHD}</span>&quot;</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${SSH_CFG}</span>&quot;</span> <span style="color: #660033;">-h</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${SSH_TPKEY}</span>&quot;</span></pre></div></div>

<p>Please note that you have to set up the root user first and maybe adjust your port forwarding rules to allow access from the Internet as described in this <a href="http://www.64k-tec.de/2010/01/fritzbox-tuning-part-1-enable-remote-access-over-ssh/" target="_blank">post</a>. The package will contain a script <code class="cmd">startup.sh</code> which will add the root user automatically.</p>
<p>Here is the obligatory screenshot which shows <code class="cmd">htop</code> with color terminal support. You see OpenSSH and OpenVPN in the list of the running processes.</p>
<p style="text-align: center;"><a href="/wordpress/wp-content/uploads/htop-e1311594537898.png"><img class="aligncenter size-medium wp-image-2427" title="htop" src="/wordpress/wp-content/uploads/htop-e1311594537898-300x176.png" alt="" width="300" height="176" /></a></p>
<h2>Conclusion</h2>
<p>Thanks to Buildroot it is pretty easy to cross-build for embedded machines these days. With some tricky directory rebinding new applications could be injected into the FRITZ!Box root filesystem without overwriting the existing firmware. Now you should be able to build any software already bundled with Buildroot or even <a href="http://buildroot.uclibc.org/buildroot.html#add_packages" target="_blank">add new one to the build process</a>. Happy cross-building!</p>
<span class="sb_download">You can download the scripts and binaries discussed in this post:<br />
<a href="/downloads/FRITZBox/FRITZBox_OpenSSH_5.8p2.tar.gz">FRITZBox_OpenSSH_5.8p2.tar.gz</a> (3.8MB, <a href="/downloads/FRITZBox/FRITZBox_OpenSSH_5.8p2.tar.gz-sha1.txt">SHA1</a>)</span>
]]></content:encoded>
			<wfw:commentRss>http://www.64k-tec.de/2011/07/fritzbox-tuning-part-4-cross-building-and-installing-additional-applications/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Kernel driver code signing with the VeriSign Class 3 Primary CA &#8211; G5 certificate</title>
		<link>http://www.64k-tec.de/2011/02/kernel-driver-code-signing-with-the-verisign-class-3-primary-ca-g5-certificate/</link>
		<comments>http://www.64k-tec.de/2011/02/kernel-driver-code-signing-with-the-verisign-class-3-primary-ca-g5-certificate/#comments</comments>
		<pubDate>Fri, 11 Feb 2011 20:58:11 +0000</pubDate>
		<dc:creator>cp</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[64-bit]]></category>
		<category><![CDATA[Applications]]></category>
		<category><![CDATA[CA]]></category>
		<category><![CDATA[Certificate]]></category>
		<category><![CDATA[Certificate Authority]]></category>
		<category><![CDATA[chain of trust]]></category>
		<category><![CDATA[code signing]]></category>
		<category><![CDATA[cross certificate]]></category>
		<category><![CDATA[installation]]></category>
		<category><![CDATA[installer]]></category>
		<category><![CDATA[intermediate certificate]]></category>
		<category><![CDATA[kernel driver module]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Signature]]></category>
		<category><![CDATA[signtool]]></category>
		<category><![CDATA[trustworthy]]></category>
		<category><![CDATA[VeriSign]]></category>
		<category><![CDATA[VirtualBox]]></category>
		<category><![CDATA[WDK]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.64k-tec.de/?p=2101</guid>
		<description><![CDATA[Since the first 64-bit version of Windows Vista it is necessary to digital sign any kernel mode driver. Without a proper code signing the driver isn't loaded by the system. Although it is also possible to sign drivers and applications for the 32-bit versions of Windows (as far as I know starting with Windows XP) [...]]]></description>
			<content:encoded><![CDATA[<p>Since the first <a href="http://msdn.microsoft.com/en-us/library/bb530195.aspx" target="_blank">64-bit version of Windows Vista</a> it is necessary to digital sign any kernel mode driver. Without a proper <a href="http://en.wikipedia.org/wiki/Code_signing" target="_blank">code signing</a> the driver isn't loaded by the system. Although it is also possible to sign drivers and applications for the 32-bit versions of Windows (as far as I know starting with Windows XP) it became mandatory in the 64-bit versions for any kernel mode driver. A serious software provider always sign its own software to make sure the user can rely on the authenticity of the package he e.g. downloaded from the Internet. It also prevent a question about installing a driver from an untrusted source which could be denied by the user and therefore makes the own software unusable. In any case the user has to confirm an installation of a driver, even if this driver is correctly signed, if the driver isn't <em><a href="http://en.wikipedia.org/wiki/WHQL_Testing" target="_blank">Windows Hardware Quality Labs</a></em> (WHQL) certificated. In the following post I will not explain the basics of how to sign Windows drivers, there are many articles out there like the one from Microsoft itself, but I will look at changes which have to be made to correctly code sign drivers with a certificate signed by the <a href="http://www.verisign.com/support/roots.html" target="_blank">VeriSign Class 3 Primary CA - G5</a> root certificate, which is in use by the end of 2010.</p>
<h2>Chain of trust</h2>
<p>To ensure the validity of every component in a computer system (hardware or software) a <a href="http://en.wikipedia.org/wiki/Chain_of_trust" target="_blank">chain of trust</a> is build. This basically means there is some root institution (in computer cryptography this is called <em><a href="http://en.wikipedia.org/wiki/Certificate_Authority" target="_blank">Certificate Authority</a></em> (CA)) which is trusted per se. Any following part in this hierarchy is signed by the parent authority. This allows a flexible mechanism where only the connected parties have to make sure they trust each other to make the full chain trustworthy. This concept is also used for code signing, cause it allows to be trustworthy in the eyes of Microsoft without ever being in touch with them. As Microsoft don't trust (for code signing) every root CA they have in their certificate store, they explicit allow only a handful of root CA's to be in this trust of chain. They archive this by cross signing root CA's with their own CA. The full concept is described in this <a href="http://www.microsoft.com/whdc/driver/install/drvsign/crosscert.mspx" target="_blank">article</a>. It basically means the software maker certificate has to be trusted by an official CA included in every Windows version and this root CA has to be cross signed by Microsoft for code signing. This is the point where the problems start with the new VeriSign Primary CA.</p>
<h2>Finding the little differences</h2>
<p>The old code signing CA is the VeriSign Class 3 Public Primary CA, available since 1996. This certificate uses an 1024 bit key, which isn't considered save anymore in the future. Therefor VeriSign decided to replace this root CA with a stronger one, which uses an 2048 bit key. If you simply replace an old software maker certificate (signed with the old root CA) with one which is signed by the new CA you get a surprise. Installing a kernel mode driver signed with the new certificate ends up with a message like this:</p>
<p style="text-align: center;"><a href="/wordpress/wp-content/uploads/unsigned_driver.png"><img class="aligncenter size-medium wp-image-2126" title="Error, because an unsigned driver." src="/wordpress/wp-content/uploads/unsigned_driver-300x284.png" alt="" width="201" height="190" /></a></p>
<p>A look into the security log of the event viewer shows this error message:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">Code integrity determined that the image hash of a file is not valid. The
file could be corrupt due to unauthorized modification or the invalid hash
could indicate a potential disk device error.</pre></div></div>

<p>To be honest: This information doesn't contain any useful hint. If you compare the old signed driver with the new signed driver you will not see any difference. Both could be successful verified as shown next:</p>
<p style="text-align: center;"><a href="/wordpress/wp-content/uploads/certs_both.png"><img class="aligncenter size-medium wp-image-2142" title="Old and new driver verification." src="/wordpress/wp-content/uploads/certs_both-300x172.png" alt="" width="300" height="172" /></a></p>
<p>Even if you compare all the sub-dialogs side by side you will not find any difference, beside the different root CA of course. So whats the difference? Well, you can't rely on the graphical representation of this trust of chain. When you invoke the <code>signtool</code> of the <a href="http://en.wikipedia.org/wiki/Windows_Driver_Kit" target="_blank"><em>Windows Driver Kit</em></a> (WDK) with the <code>verify</code> option, you will see the difference:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">C:\Program Files\Oracle\VirtualBox_Sun&gt;signtool.exe verify /v /kp drivers/vboxdrv/VBoxDrv.sys
&nbsp;
Verifying: drivers/vboxdrv/VBoxDrv.sys
SHA1 hash of file: 9E58611C764D5AE04140E4CC7782B3229D1BCB8A
Signing Certificate Chain:
    Issued to: Microsoft Code Verification Root
    Issued by: Microsoft Code Verification Root
    Expires:   01.11.2025 14:54:03
    SHA1 hash: 8FBE4D070EF8AB1BCCAF2A9D5CCAE7282A2C66B3
&nbsp;
        Issued to: Class 3 Public Primary Certification Authority
        Issued by: Microsoft Code Verification Root
        Expires:   23.05.2016 18:11:29
        SHA1 hash: 58455389CF1D0CD6A08E3CE216F65ADFF7A86408
&nbsp;
            Issued to: VeriSign Class 3 Code Signing 2004 CA
            Issued by: Class 3 Public Primary Certification Authority
            Expires:   16.07.2014 00:59:59
            SHA1 hash: 197A4AEBDB25F0170079BB8C73CB2D655E0018A4
&nbsp;
                Issued to: Sun Microsystems, Inc.
                Issued by: VeriSign Class 3 Code Signing 2004 CA
                Expires:   12.06.2011 00:59:59
                SHA1 hash: 1D4458051589B47A06260125F6EC6BBB6C24472E
&nbsp;
The signature is timestamped: 08.02.2011 00:23:54
Timestamp Verified by:
    Issued to: Thawte Timestamping CA
    Issued by: Thawte Timestamping CA
    Expires:   01.01.2021 00:59:59
    SHA1 hash: BE36A4562FB2EE05DBB3D32323ADF445084ED656
&nbsp;
        Issued to: VeriSign Time Stamping Services CA
        Issued by: Thawte Timestamping CA
        Expires:   04.12.2013 00:59:59
        SHA1 hash: F46AC0C6EFBB8C6A14F55F09E2D37DF4C0DE012D
&nbsp;
            Issued to: VeriSign Time Stamping Services Signer - G2
            Issued by: VeriSign Time Stamping Services CA
            Expires:   15.06.2012 00:59:59
            SHA1 hash: ADA8AAA643FF7DC38DD40FA4C97AD559FF4846DE
&nbsp;
Successfully verified: drivers/vboxdrv/VBoxDrv.sys
&nbsp;
Number of files successfully Verified: 1
Number of warnings: 0
Number of errors: 0
&nbsp;
C:\Program Files\Oracle\VirtualBox_Sun&gt;</pre></div></div>

<p>and</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">C:\Program Files\Oracle\VirtualBox_Oracle_Wrong\&gt;signtool.exe verify /v /kp drivers/vboxdrv/VBoxDrv.sys
&nbsp;
Verifying: drivers/vboxdrv/VBoxDrv.sys
SHA1 hash of file: F398B7124B0A8C32DBFB262343AC1180807505D0
Signing Certificate Chain:
    Issued to: VeriSign Class 3 Public Primary Certification Authority - G5
    Issued by: VeriSign Class 3 Public Primary Certification Authority - G5
    Expires:   17.07.2036 00:59:59
    SHA1 hash: 4EB6D578499B1CCF5F581EAD56BE3D9B6744A5E5
&nbsp;
        Issued to: VeriSign Class 3 Code Signing 2010 CA
        Issued by: VeriSign Class 3 Public Primary Certification Authority - G5
        Expires:   08.02.2020 00:59:59
        SHA1 hash: 495847A93187CFB8C71F840CB7B41497AD95C64F
&nbsp;
            Issued to: Oracle Corporation
            Issued by: VeriSign Class 3 Code Signing 2010 CA
            Expires:   08.02.2014 00:59:59
            SHA1 hash: A88FD9BDAA06BC0F3C491BA51E231BE35F8D1AD5
&nbsp;
The signature is timestamped: 10.02.2011 09:30:08
Timestamp Verified by:
    Issued to: Thawte Timestamping CA
    Issued by: Thawte Timestamping CA
    Expires:   01.01.2021 00:59:59
    SHA1 hash: BE36A4562FB2EE05DBB3D32323ADF445084ED656
&nbsp;
        Issued to: VeriSign Time Stamping Services CA
        Issued by: Thawte Timestamping CA
        Expires:   04.12.2013 00:59:59
        SHA1 hash: F46AC0C6EFBB8C6A14F55F09E2D37DF4C0DE012D
&nbsp;
            Issued to: VeriSign Time Stamping Services Signer - G2
            Issued by: VeriSign Time Stamping Services CA
            Expires:   15.06.2012 00:59:59
            SHA1 hash: ADA8AAA643FF7DC38DD40FA4C97AD559FF4846DE
&nbsp;
Successfully verified: drivers/vboxdrv/VBoxDrv.sys
&nbsp;
Number of files successfully Verified: 1
Number of warnings: 0
Number of errors: 0
&nbsp;
C:\Program Files\Oracle\VirtualBox_Oracle_Wrong&gt;</pre></div></div>

<p>As you can see, the chain of trust of the old certificate contains the Microsoft Code Verification Root, the new signed driver not. As Microsoft released the cross certificate somewhere in 2006, it makes sense that the new VeriSign certificate isn't signed by them. So first of all, we have to blame the <code>signtool</code> for <strong>silently</strong> ignoring a cross certificate which, obviously, doesn't trust the root certificate. When you have this information you can search for additional information and probably find an <a href="https://knowledge.verisign.com/support/code-signing-support/index?page=content&amp;actp=CROSSLINK&amp;id=AD220" target="_blank">advisory of VeriSign</a>. There you learn you need <a href="http://www.verisign.com/support/verisign-intermediate-ca/code-signing-intermediate/index.html" target="_blank">intermediate certificates</a> for the new root CA.</p>
<h2>Installing the right certificates on the build machine</h2>
<p>The rest is easy. The certificate store of any Windows installation contains the new VeriSign Root CA as shown here:</p>
<p style="text-align: left;"><a href="/wordpress/wp-content/uploads/g5_root_ca.png"><img class="aligncenter size-medium wp-image-2168" title="VeriSign Class 3 Primary CA - G5 in the Windows certificate store." src="/wordpress/wp-content/uploads/g5_root_ca-300x164.png" alt="" width="300" height="164" /></a>Delete this root CA and replace it by the intermediate certificates you fetched from the website shown above. Just place the certificate in a text file, add the extension <code>.der</code> and double-click to install it. Make sure to replace really all versions of this certificate, even the one in the global store. When you now sign your driver with your new certificate the Microsoft Code Verification Root is in the trust of chain, as shown in the following:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">C:\Program Files\Oracle\VirtualBox_Oracle_Correct&gt;signtool.exe verify /v /kp drivers/vboxdrv/VBoxDrv.sys
&nbsp;
Verifying: drivers/vboxdrv/VBoxDrv.sys
SHA1 hash of file: 201B7F97473D7F015A104D7841371C5AE4F22FF2
Signing Certificate Chain:
    Issued to: Microsoft Code Verification Root
    Issued by: Microsoft Code Verification Root
    Expires:   01.11.2025 14:54:03
    SHA1 hash: 8FBE4D070EF8AB1BCCAF2A9D5CCAE7282A2C66B3
&nbsp;
        Issued to: Class 3 Public Primary Certification Authority
        Issued by: Microsoft Code Verification Root
        Expires:   23.05.2016 18:11:29
        SHA1 hash: 58455389CF1D0CD6A08E3CE216F65ADFF7A86408
&nbsp;
            Issued to: VeriSign Class 3 Public Primary Certification Authority - G5
            Issued by: Class 3 Public Primary Certification Authority
            Expires:   08.11.2021 00:59:59
            SHA1 hash: 32F30882622B87CF8856C63DB873DF0853B4DD27
&nbsp;
                Issued to: VeriSign Class 3 Code Signing 2010 CA
                Issued by: VeriSign Class 3 Public Primary Certification Authority - G5
                Expires:   08.02.2020 00:59:59
                SHA1 hash: 495847A93187CFB8C71F840CB7B41497AD95C64F
&nbsp;
                    Issued to: Oracle Corporation
                    Issued by: VeriSign Class 3 Code Signing 2010 CA
                    Expires:   08.02.2014 00:59:59
                    SHA1 hash: A88FD9BDAA06BC0F3C491BA51E231BE35F8D1AD5
&nbsp;
The signature is timestamped: 10.02.2011 15:03:30
Timestamp Verified by:
    Issued to: Thawte Timestamping CA
    Issued by: Thawte Timestamping CA
    Expires:   01.01.2021 00:59:59
    SHA1 hash: BE36A4562FB2EE05DBB3D32323ADF445084ED656
&nbsp;
        Issued to: VeriSign Time Stamping Services CA
        Issued by: Thawte Timestamping CA
        Expires:   04.12.2013 00:59:59
        SHA1 hash: F46AC0C6EFBB8C6A14F55F09E2D37DF4C0DE012D
&nbsp;
            Issued to: VeriSign Time Stamping Services Signer - G2
            Issued by: VeriSign Time Stamping Services CA
            Expires:   15.06.2012 00:59:59
            SHA1 hash: ADA8AAA643FF7DC38DD40FA4C97AD559FF4846DE
&nbsp;
Successfully verified: drivers/vboxdrv/VBoxDrv.sys
&nbsp;
Number of files successfully Verified: 1
Number of warnings: 0
Number of errors: 0
&nbsp;
C:\Program Files\Oracle\VirtualBox_Oracle_Correct&gt;</pre></div></div>

<p>You see the old certificate (which is trusted by Microsoft) is the parent of the new certificate, which completes the trust of chain again. I guess this is only some temporary solution as long as Microsoft doesn't release a new cross certificate (that's why it is called intermediate). Luckily, you only need the intermediate certificates on the build machine. For your end users nothing has to be changed.</p>
<h2>Conclusion</h2>
<p>This article shows how a service provider make an easy task hard to do. Signing a kernel mode driver with the new certificate isn't hard, but finding the right information is. Although there is an advisory from VeriSign, it doesn't really explain what to do. As I believe in the future many other people will be in the same situation, I hope this article will save them from some sleepless nights.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.64k-tec.de/2011/02/kernel-driver-code-signing-with-the-verisign-class-3-primary-ca-g5-certificate/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Creating file shortcuts on three different operation systems</title>
		<link>http://www.64k-tec.de/2010/11/creating-file-shortcuts-on-three-different-operation-systems/</link>
		<comments>http://www.64k-tec.de/2010/11/creating-file-shortcuts-on-three-different-operation-systems/#comments</comments>
		<pubDate>Sun, 28 Nov 2010 13:44:50 +0000</pubDate>
		<dc:creator>cp</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[AESend]]></category>
		<category><![CDATA[Alias]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[desktop]]></category>
		<category><![CDATA[Desktop Entry Specification]]></category>
		<category><![CDATA[file shortcuts]]></category>
		<category><![CDATA[freeedesktop.org]]></category>
		<category><![CDATA[gcc]]></category>
		<category><![CDATA[hard link]]></category>
		<category><![CDATA[installation]]></category>
		<category><![CDATA[IPersistFile]]></category>
		<category><![CDATA[IShellLink]]></category>
		<category><![CDATA[link]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[objc]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[platform]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[VirtualBox]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[X11]]></category>
		<category><![CDATA[Xorg]]></category>

		<guid isPermaLink="false">http://www.64k-tec.de/?p=1838</guid>
		<description><![CDATA[As you may know, developing for multiple platforms is one of my strengths. Strictly speaking, it's a basic requirement if you are involved in such a product like VirtualBox, which runs on every major (and several minor) platform available today. Beside the GUI, which uses Qt and therewith is portable without any additional cost (which [...]]]></description>
			<content:encoded><![CDATA[<p>As you may know, developing for multiple platforms is one of my strengths. Strictly speaking, it's a basic requirement if you are involved in such a product like VirtualBox, which runs on every major (and several minor) platform available today. Beside the GUI, which uses <a href="http://qt.nokia.com/" target="_blank">Qt</a> and therewith is portable without any additional cost (which isn't fully true if you want <a href="http://www.64k-tec.de/2009/12/integrating-native-cocoa-controls-into-qt/" target="_blank">real native look and feel on every platform, especially on Mac OS X</a>), all the rest of VirtualBox is written in a portable way. This is done by using only C/C++ and Assembler when necessary. Everything which needs a different approach, because of the design of the OS (and the API's which are available there), is implemented in a platform dependent way. In the history of VirtualBox, several <a href="http://www.virtualbox.org/browser/trunk/src/VBox/Runtime" target="_blank">modules</a> are created and grown by the time, which makes it really easy to deal with this differences. For stuff like file handling, paths, strings, semaphores or any other basic functionality, you can just use the modules which are available. On the other side it might be necessary, for a new feature we implement, to write it from the ground. In the following post I will show how to create a <a href="http://en.wikipedia.org/wiki/File_shortcut" target="_blank">file shortcut</a> for the three major operation systems available today.</p>
<h2>Why do you want to use file shortcuts</h2>
<p>On the classical UNIX systems you have <a href="http://en.wikipedia.org/wiki/Hard_link" target="_blank">hard</a> and <a href="http://en.wikipedia.org/wiki/Soft_link" target="_blank">soft</a> links. These are implemented by the filesystem and make it possible to link to another file or folder without any trouble. Most of the time soft links are used, but it really depends on the use case. Unfortunately these kind of links are not available on Windows (yes, I know there are also hard links and junctions on NTFS, but they are not common and difficult to handle), these links doesn't allow any additional attributes. For example one like to add a different icon to the link or provide more information through a comment field. Beside on Mac OS X, shortcuts can also be work as an application launcher, where the link contain the information what application should be started and how. In contrast to filesystem links which are handled by the operation system, these shortcuts are handled by the window system (or shell) running on the host (which doesn't mean there is no filesystem support for it). On Windows this is the Explorer, on Mac OS X the Finder and on Linux a <a href="http://www.freedesktop.org/" target="_blank">freedesktop.org</a> conforming file manager.</p>
<h2>Creating a Desktop file on Linux</h2>
<p>Desktop files on Linux (or any other UNIX system which conforms to freedesktop.org) is easy. It's a simple text file which implement the <a href="http://standards.freedesktop.org/desktop-entry-spec/latest/" target="_blank">Desktop Entry Specification</a>. In version 1.0 there are 18 possible entries, where not all of them are mandatory. In the following example I use Qt to write these files, but it should be no problem to use any other toolkit or plain C.</p>

<div class="wp_syntax"><div class="code"><pre class="cpp-qt" style="font-family:monospace;"><span style="color: #0057AE;">bool</span> createShortcut<span style="color: #006E28;">&#40;</span><span style="color: #0057AE;">const</span> <span style="color: #22aadd;">QString</span> <span style="color: #006E28;">&amp;</span>strSrcFile<span style="color: #006E28;">,</span>
                    <span style="color: #0057AE;">const</span> <span style="color: #22aadd;">QString</span> <span style="color: #006E28;">&amp;</span>strDstPath<span style="color: #006E28;">,</span>
                    <span style="color: #0057AE;">const</span> <span style="color: #22aadd;">QString</span> <span style="color: #006E28;">&amp;</span>strName<span style="color: #006E28;">&#41;</span>
<span style="color: #006E28;">&#123;</span>
 <span style="color: #22aadd;">QFile</span> link<span style="color: #006E28;">&#40;</span>strDstPath <span style="color: #006E28;">+</span> <span style="color: #22aadd;">QDir</span><span style="color: #006E28;">::</span><span style="color: #2B74C7;">separator</span><span style="color: #006E28;">&#40;</span><span style="color: #006E28;">&#41;</span> <span style="color: #006E28;">+</span> strName <span style="color: #006E28;">+</span> <span style="color: #BF0303;">&quot;.desktop&quot;</span><span style="color: #006E28;">&#41;</span><span style="color: #006E28;">;</span>
 <span style="color: #000000; font-weight:bold;">if</span> <span style="color: #006E28;">&#40;</span>link.<span style="color: #2B74C7;">open</span><span style="color: #006E28;">&#40;</span><span style="color: #22aadd;">QFile</span><span style="color: #006E28;">::</span><span style="color: #2B74C7;">WriteOnly</span> <span style="color: #006E28;">|</span> <span style="color: #22aadd;">QFile</span><span style="color: #006E28;">::</span><span style="color: #2B74C7;">Truncate</span><span style="color: #006E28;">&#41;</span><span style="color: #006E28;">&#41;</span>
 <span style="color: #006E28;">&#123;</span>
  <span style="color: #22aadd;">QTextStream</span> out<span style="color: #006E28;">&#40;</span><span style="color: #006E28;">&amp;</span>link<span style="color: #006E28;">&#41;</span><span style="color: #006E28;">;</span>
  out.<span style="color: #2B74C7;">setCodec</span><span style="color: #006E28;">&#40;</span><span style="color: #BF0303;">&quot;UTF-8&quot;</span><span style="color: #006E28;">&#41;</span><span style="color: #006E28;">;</span>
  out <span style="color: #006E28;">&lt;&lt;</span> <span style="color: #BF0303;">&quot;[Desktop Entry]&quot;</span> <span style="color: #006E28;">&lt;&lt;</span> endl
      <span style="color: #006E28;">&lt;&lt;</span> <span style="color: #BF0303;">&quot;Encoding=UTF-8&quot;</span> <span style="color: #006E28;">&lt;&lt;</span> endl
      <span style="color: #006E28;">&lt;&lt;</span> <span style="color: #BF0303;">&quot;Version=1.0&quot;</span> <span style="color: #006E28;">&lt;&lt;</span> endl
      <span style="color: #006E28;">&lt;&lt;</span> <span style="color: #BF0303;">&quot;Type=Link&quot;</span> <span style="color: #006E28;">&lt;&lt;</span> endl
      <span style="color: #006E28;">&lt;&lt;</span> <span style="color: #BF0303;">&quot;Name=&quot;</span> <span style="color: #006E28;">&lt;&lt;</span> strName <span style="color: #006E28;">&lt;&lt;</span> endl
      <span style="color: #006E28;">&lt;&lt;</span> <span style="color: #BF0303;">&quot;URL=&quot;</span> <span style="color: #006E28;">&lt;&lt;</span> strSrcFile <span style="color: #006E28;">&lt;&lt;</span> endl
      <span style="color: #006E28;">&lt;&lt;</span> <span style="color: #BF0303;">&quot;Icon=icon-name&quot;</span> <span style="color: #006E28;">&lt;&lt;</span> endl<span style="color: #006E28;">;</span>
  <span style="color: #000000; font-weight:bold;">return</span> true<span style="color: #006E28;">;</span>
 <span style="color: #006E28;">&#125;</span>
 <span style="color: #000000; font-weight:bold;">return</span> false<span style="color: #006E28;">;</span>
<span style="color: #006E28;">&#125;</span></pre></div></div>

<p>Replace <code>icon-name</code> by a registered icon on the system and you are done.</p>
<h2>Creating a Shell link on Windows</h2>
<p>Windows provides an interface for <a href="http://msdn.microsoft.com/en-us/library/bb774950%28VS.85%29.aspx" target="_blank"><code>IShellLink</code></a> since Windows XP. The following example shows how to use it:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">bool</span> createShortcut<span style="color: #008000;">&#40;</span>LPCSTR lpszSrcFile,
                    LPCSTR lpszDstPath,
                    LPCSTR lpszName<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
 IShellLink <span style="color: #000040;">*</span>pShl <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
 IPersistFile <span style="color: #000040;">*</span>pPPF <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
 HRESULT rc <span style="color: #000080;">=</span> CoCreateInstance<span style="color: #008000;">&#40;</span>CLSID_ShellLink,
                               <span style="color: #0000ff;">NULL</span>,
                               CLSCTX_INPROC_SERVER,
                               IID_IShellLink,
                               <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #000040;">**</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>pShl<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
 <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>FAILED<span style="color: #008000;">&#40;</span>rc<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
  <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
 <span style="color: #0000ff;">do</span>
 <span style="color: #008000;">&#123;</span>
  rc <span style="color: #000080;">=</span> pShl<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>SetPath<span style="color: #008000;">&#40;</span>lpszSrcFile<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>FAILED<span style="color: #008000;">&#40;</span>rc<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
   <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
  rc <span style="color: #000080;">=</span> pShl<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>QueryInterface<span style="color: #008000;">&#40;</span>IID_IPersistFile, <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #000040;">**</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">&amp;</span>pPPF<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>FAILED<span style="color: #008000;">&#40;</span>rc<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
   <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
  WORD wsz<span style="color: #008000;">&#91;</span>MAX_PATH<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
  TCHAR path<span style="color: #008000;">&#91;</span>MAX_PATH<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">0</span> <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
  lstrcat<span style="color: #008000;">&#40;</span>path, lpszDstPath<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  lstrcat<span style="color: #008000;">&#40;</span>path, <span style="color: #FF0000;">&quot;<span style="color: #000099; font-weight: bold;">\\</span>&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  lstrcat<span style="color: #008000;">&#40;</span>path, lpszName<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  lstrcat<span style="color: #008000;">&#40;</span>path, <span style="color: #FF0000;">&quot;.lnk&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  MultiByteToWideChar<span style="color: #008000;">&#40;</span>CP_ACP, <span style="color: #0000dd;">0</span>, buf, <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span>, wsz, MAX_PATH<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  rc <span style="color: #000080;">=</span> pPPF<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Save<span style="color: #008000;">&#40;</span>wsz, TRUE<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
 <span style="color: #008000;">&#125;</span> <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
 <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>pPPF<span style="color: #008000;">&#41;</span>
  pPPF<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Release<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
 <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>pShl<span style="color: #008000;">&#41;</span>
  pShl<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Release<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
 <span style="color: #0000ff;">return</span> SUCCEEDED<span style="color: #008000;">&#40;</span>rc<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>As you may noticed this uses <a href="http://en.wikipedia.org/wiki/Component_Object_Model" target="_blank">COM</a>. Many API's on Windows using the COM interface to communicate between processes. If you don't use COM in your application you have to initialize it first. This is achieved by adding the following call to the front of the function:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"> <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>FAILED<span style="color: #008000;">&#40;</span>CoInitialize<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
  <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span></pre></div></div>

<p>Depending on your application it might be worth to unitialize COM after usage by appending the following to the function:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"> CoUninitialize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></div></div>

<p>The function itself isn't any magic. It gets a COM interface to the <code>IShellLink</code> interface and then work with it, by setting the source path and adding a target path by using the <a href="http://msdn.microsoft.com/en-us/library/ms687223%28VS.85%29.aspx" target="_blank"><code>IPersistFile</code></a> interface. As I wrote before you could do much more. Providing a path to a specific application or adding your own parameters is no problem. Have a look at the documentation.</p>
<h2>Creating an Alias file on Mac OS X</h2>
<p>Shortcut files on Mac OS X are a little bit different. At first, they aren't one. There are the classical filesystem links and <a href="http://en.wikipedia.org/wiki/Alias_%28Mac_OS%29" target="_blank">Alias</a> files. Alias files are links which targeting a specific file, but they haven't all the possibilities of shortcuts like on Windows or Linux. As the name suggest they are really only an alias for another file or directory. So specifying an application to start or things like that aren't possible. Anyway they allow changing the icon and they are more persistent than on Window or Linux cause they are working with several attributes of the target file. Even if you rename or move the target, an Alias file will resolve the target correctly (if it is possible). On the other side, being such special means also being hard to create. In principle there are two possibilities. The first one is, creating a file which is no file at all, but has several <a href="http://en.wikipedia.org/wiki/Resource_fork" target="_blank">resources forks</a> attached. Therefor you need to know exactly how Alias files are built of and make sure with every release of Mac OS X you are following the development. There is a free project which does exactly that: <a href="https://github.com/nathanday/ndalias" target="_blank">NDAlias</a>. If you are like me and a little bit more lazy, you ask someone who should know how to create Alias files. This is Finder. Although writing the files itself isn't easy, asking the Finder to do the job is not really easier, cause the information about doing exactly that are really rare. The following code shows how to achieve it:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">bool createShortcut<span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>pstrSrcFile,
                    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>pstrDstPath,
                    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>pstrName<span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
 <span style="color: #11740a; font-style: italic;">/* First of all we need to figure out which process Id the Finder
  * currently has. */</span>
 <span style="color: #400080;">NSWorkspace</span> <span style="color: #002200;">*</span>pWS <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSWorkspace</span> sharedWorkspace<span style="color: #002200;">&#93;</span>;
 <span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>pApps <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>pWS launchedApplications<span style="color: #002200;">&#93;</span>;
 bool fFFound <span style="color: #002200;">=</span> <span style="color: #a61390;">false</span>;
 ProcessSerialNumber psn;
 <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span>pDict <span style="color: #a61390;">in</span> pApps<span style="color: #002200;">&#41;</span>
 <span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>pDict valueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;NSApplicationBundleIdentifier&quot;</span><span style="color: #002200;">&#93;</span>
         isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;com.apple.finder&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
  <span style="color: #002200;">&#123;</span>
   psn.highLongOfPSN <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>pDict
                          valueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;NSApplicationProcessSerialNumberHigh&quot;</span><span style="color: #002200;">&#93;</span> intValue<span style="color: #002200;">&#93;</span>;
   psn.lowLongOfPSN  <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>pDict
                          valueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;NSApplicationProcessSerialNumberLow&quot;</span><span style="color: #002200;">&#93;</span> intValue<span style="color: #002200;">&#93;</span>;
   fFFound <span style="color: #002200;">=</span> <span style="color: #a61390;">true</span>;
   <span style="color: #a61390;">break</span>;
  <span style="color: #002200;">&#125;</span>
 <span style="color: #002200;">&#125;</span>
 <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>fFFound<span style="color: #002200;">&#41;</span>
  <span style="color: #a61390;">return</span> <span style="color: #a61390;">false</span>;
 <span style="color: #11740a; font-style: italic;">/* Now the event fun begins. */</span>
 OSErr err <span style="color: #002200;">=</span> noErr;
 AliasHandle hSrcAlias <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
 AliasHandle hDstAlias <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
 <span style="color: #a61390;">do</span>
 <span style="color: #002200;">&#123;</span>
  <span style="color: #11740a; font-style: italic;">/* Create a descriptor which contains the target psn. */</span>
  <span style="color: #400080;">NSAppleEventDescriptor</span> <span style="color: #002200;">*</span>finderPSNDesc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSAppleEventDescriptor</span>
                                            descriptorWithDescriptorType<span style="color: #002200;">:</span>typeProcessSerialNumber
                                            bytes<span style="color: #002200;">:&amp;</span>psn
                                            length<span style="color: #002200;">:</span><span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>psn<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>finderPSNDesc<span style="color: #002200;">&#41;</span>
   <span style="color: #a61390;">break</span>;
  <span style="color: #11740a; font-style: italic;">/* Create the Apple event descriptor which points to the Finder
   * target already. */</span>
  <span style="color: #400080;">NSAppleEventDescriptor</span> <span style="color: #002200;">*</span>finderEventDesc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSAppleEventDescriptor</span>
                                              appleEventWithEventClass<span style="color: #002200;">:</span>kAECoreSuite
                                              eventID<span style="color: #002200;">:</span>kAECreateElement
                                              argetDescriptor<span style="color: #002200;">:</span>finderPSNDesc
                                              returnID<span style="color: #002200;">:</span>kAutoGenerateReturnID
                                              transactionID<span style="color: #002200;">:</span>kAnyTransactionID<span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>finderEventDesc<span style="color: #002200;">&#41;</span>
   <span style="color: #a61390;">break</span>;
  <span style="color: #11740a; font-style: italic;">/* Create and add an event type descriptor: Alias */</span>
  <span style="color: #400080;">NSAppleEventDescriptor</span> <span style="color: #002200;">*</span>osTypeDesc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSAppleEventDescriptor</span> descriptorWithTypeCode<span style="color: #002200;">:</span>typeAlias<span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>osTypeDesc<span style="color: #002200;">&#41;</span>
   <span style="color: #a61390;">break</span>;
  <span style="color: #002200;">&#91;</span>finderEventDesc setParamDescriptor<span style="color: #002200;">:</span>osTypeDesc forKeyword<span style="color: #002200;">:</span>keyAEObjectClass<span style="color: #002200;">&#93;</span>;
  <span style="color: #11740a; font-style: italic;">/* Now create the source Alias, which will be attached to the event. */</span>
  err <span style="color: #002200;">=</span> FSNewAliasFromPath<span style="color: #002200;">&#40;</span><span style="color: #a61390;">nil</span>, <span style="color: #002200;">&#91;</span>pstrSrcFile fileSystemRepresentation<span style="color: #002200;">&#93;</span>, <span style="color: #2400d9;">0</span>, <span style="color: #002200;">&amp;</span>hSrcAlias, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>err <span style="color: #002200;">!=</span> noErr<span style="color: #002200;">&#41;</span>
   <span style="color: #a61390;">break</span>;
  <span style="color: #a61390;">char</span> handleState;
  handleState <span style="color: #002200;">=</span> HGetState<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>Handle<span style="color: #002200;">&#41;</span>hSrcAlias<span style="color: #002200;">&#41;</span>;
  HLock<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>Handle<span style="color: #002200;">&#41;</span>hSrcAlias<span style="color: #002200;">&#41;</span>;
  <span style="color: #400080;">NSAppleEventDescriptor</span> <span style="color: #002200;">*</span>srcAliasDesc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSAppleEventDescriptor</span>
                                           descriptorWithDescriptorType<span style="color: #002200;">:</span>typeAlias
                                           bytes<span style="color: #002200;">:*</span>hSrcAlias
                                           length<span style="color: #002200;">:</span>GetAliasSize<span style="color: #002200;">&#40;</span>hSrcAlias<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>srcAliasDesc<span style="color: #002200;">&#41;</span>
   <span style="color: #a61390;">break</span>;
  <span style="color: #002200;">&#91;</span>finderEventDesc setParamDescriptor<span style="color: #002200;">:</span>srcAliasDesc
    forKeyword<span style="color: #002200;">:</span>keyASPrepositionTo<span style="color: #002200;">&#93;</span>;
  HSetState<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>Handle<span style="color: #002200;">&#41;</span>hSrcAlias, handleState<span style="color: #002200;">&#41;</span>;
  <span style="color: #11740a; font-style: italic;">/* Next create the target Alias and attach it to the event. */</span>
  err <span style="color: #002200;">=</span> FSNewAliasFromPath<span style="color: #002200;">&#40;</span><span style="color: #a61390;">nil</span>, <span style="color: #002200;">&#91;</span>pstrDstPath fileSystemRepresentation<span style="color: #002200;">&#93;</span>, <span style="color: #2400d9;">0</span>, <span style="color: #002200;">&amp;</span>hDstAlias, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>err <span style="color: #002200;">!=</span> noErr<span style="color: #002200;">&#41;</span>
   <span style="color: #a61390;">break</span>;
  handleState <span style="color: #002200;">=</span> HGetState<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>Handle<span style="color: #002200;">&#41;</span>hDstAlias<span style="color: #002200;">&#41;</span>;
  HLock<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>Handle<span style="color: #002200;">&#41;</span>hDstAlias<span style="color: #002200;">&#41;</span>;
  <span style="color: #400080;">NSAppleEventDescriptor</span> <span style="color: #002200;">*</span>dstAliasDesc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSAppleEventDescriptor</span>
                                           descriptorWithDescriptorType<span style="color: #002200;">:</span>t ypeAlias
                                           bytes<span style="color: #002200;">:*</span>hDstAlias
                                           length<span style="color: #002200;">:</span>GetAliasSize<span style="color: #002200;">&#40;</span>hDstAlias<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>dstAliasDesc<span style="color: #002200;">&#41;</span>
   <span style="color: #a61390;">break</span>;
  <span style="color: #002200;">&#91;</span>finderEventDesc setParamDescriptor<span style="color: #002200;">:</span>dstAliasDesc
    forKeyword<span style="color: #002200;">:</span>keyAEInsertHere<span style="color: #002200;">&#93;</span>;
  HSetState<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>Handle<span style="color: #002200;">&#41;</span>hDstAlias, handleState<span style="color: #002200;">&#41;</span>;
  <span style="color: #11740a; font-style: italic;">/* Finally a property descriptor containing the target
   * Alias name. */</span>
  <span style="color: #400080;">NSAppleEventDescriptor</span> <span style="color: #002200;">*</span>finderPropDesc <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSAppleEventDescriptor</span> recordDescriptor<span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>finderPropDesc<span style="color: #002200;">&#41;</span>
   <span style="color: #a61390;">break</span>;
  <span style="color: #002200;">&#91;</span>finderPropDesc setDescriptor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSAppleEventDescriptor</span> descriptorWithString<span style="color: #002200;">:</span>pstrName<span style="color: #002200;">&#93;</span>
    forKeyword<span style="color: #002200;">:</span>keyAEName<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>finderEventDesc setParamDescriptor<span style="color: #002200;">:</span>finderPropDesc forKeyword<span style="color: #002200;">:</span>keyAEPropData<span style="color: #002200;">&#93;</span>;
  <span style="color: #11740a; font-style: italic;">/* Now send the event to the Finder. */</span>
  err <span style="color: #002200;">=</span> AESend<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>finderEventDesc aeDesc<span style="color: #002200;">&#93;</span>,
               <span style="color: #a61390;">NULL</span>,
               kAENoReply,
               kAENormalPriority,
               kNoTimeOut,
               <span style="color: #2400d9;">0</span>,
               <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>;
 <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">while</span><span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>;
 <span style="color: #11740a; font-style: italic;">/* Cleanup */</span>
 <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>hSrcAlias<span style="color: #002200;">&#41;</span>
  DisposeHandle<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>Handle<span style="color: #002200;">&#41;</span>hSrcAlias<span style="color: #002200;">&#41;</span>;
 <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>hDstAlias<span style="color: #002200;">&#41;</span>
  DisposeHandle<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>Handle<span style="color: #002200;">&#41;</span>hDstAlias<span style="color: #002200;">&#41;</span>;
 <span style="color: #a61390;">return</span> err <span style="color: #002200;">==</span> noErr ? <span style="color: #a61390;">true</span> <span style="color: #002200;">:</span> <span style="color: #a61390;">false</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

<p>Although the code above looks a little bit scary, it does not much. It fetch the process serial number of the current Finder process, creates an Application event for creating an Alias file and send this event to the Finder.</p>
<h2>Conclusion</h2>
<p>Beside showing how to create file shortcuts on different platforms, this article also shows which work is necessary to create platform independent code. It's a simple example. But it also makes clear that one simple solution for platform one, not necessarily mean it's such simple on platform two.</p>
<p>Making this easy accessible to any developer is the next step. I will leave this exercise to the reader, but have a look at the <a href="http://www.virtualbox.org/browser/trunk/src/VBox/Frontends/VirtualBox/src/platform" target="_blank">platform code of the VirtualBox GUI</a> and the corresponding <a href="http://www.virtualbox.org/browser/trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk" target="_blank">Makefile</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.64k-tec.de/2010/11/creating-file-shortcuts-on-three-different-operation-systems/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Understanding some of the mysteries of launchd</title>
		<link>http://www.64k-tec.de/2010/11/understanding-some-of-the-mysteries-of-launchd/</link>
		<comments>http://www.64k-tec.de/2010/11/understanding-some-of-the-mysteries-of-launchd/#comments</comments>
		<pubDate>Sat, 20 Nov 2010 00:11:55 +0000</pubDate>
		<dc:creator>cp</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[Applications]]></category>
		<category><![CDATA[bundle]]></category>
		<category><![CDATA[file types]]></category>
		<category><![CDATA[Info.plist]]></category>
		<category><![CDATA[installation]]></category>
		<category><![CDATA[installer]]></category>
		<category><![CDATA[launchd]]></category>
		<category><![CDATA[LaunchServices]]></category>
		<category><![CDATA[lsregister]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[plist]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.64k-tec.de/?p=1716</guid>
		<description><![CDATA[Have you ever wondered how Mac OS X knows which file type belongs to which application? On Windows there is the registry. An installer writes the necessary info into it. Most applications on Mac OS X doesn't come with an installer, they are just moved from the downloaded DMG file to the /Applications folder. So [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever wondered how Mac OS X knows which file type belongs to which application? On Windows there is the registry. An installer writes the necessary info into <a href="http://msdn.microsoft.com/en-us/library/ee872121%28v=VS.85%29.aspx" target="_blank">it</a>. Most applications on Mac OS X doesn't come with an installer, they are just moved from the downloaded <a href="http://en.wikipedia.org/wiki/Apple_Disk_Image" target="_blank">DMG</a> file to the <code class="path">/Applications</code> folder. So a developer doesn't have the ability to take action when the user "install" the application. Anyway there is no need to provide an installer for just this task, cause Mac OS X register file type associations on the first start of the application. In the following post, I will show how to do this, but furthermore I will show where this information is stored and how it could be reseted.</p>
<h2>Providing the necessary information to Mac OS X</h2>
<p>Applications on Mac OS X need some defined structure. They are so-called <a href="http://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFBundles/Introduction/Introduction.html" target="_blank">bundles</a>, which means on the filesystem layer they are directories. You can prove this by checking the Applications directory within the Terminal.app. You could also right-click on an application and select "Show Package Contents". The content of the bundle directory is usually hidden from the user when he works with the Finder or any other high level function of Mac OS X (like the open dialog). Additional to this layout on the filesystem, an application provide information about itself to the system with a plist file. This file has to be named <code class="path">Application.app/Content/Info.plist</code>. The following shows exemplary the content of the <a href="http://code.google.com/p/tunnelblick/" target="_blank">Tunnelblick</a> application:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #00bbdd;">&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plist</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dict<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleDevelopmentRegion<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>     <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>English<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleExecutable<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Tunnelblick<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleIconFile<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>              <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>tunnelblick.icns<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleIdentifier<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.openvpn.tunnelblick<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleInfoDictionaryVersion<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>6.0<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundlePackageType<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>           <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>APPL<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleShortVersionString<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>3.1beta20 (build 2132)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleSignature<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>             <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>OVPN<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleVersion<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>               <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2132<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>NSMainNibFile<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>                 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>MainMenu<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>NSPrincipalClass<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>              <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>NSApplication<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>NSUIElement<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>                   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>SUEnableSystemProfiling<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>       <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;true</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>SUFeedURL<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>                     <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://tunnelblick.net/appcast.rss<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>SUPublicDSAKeyFile<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>dsa_pub.pem<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dict<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>The keys are mostly self explaining, you can find a full list <a href="http://developer.apple.com/library/mac/#documentation/General/Reference/InfoPlistKeyReference/Introduction/Introduction.html#//apple_ref/doc/uid/TP40009247" target="_blank">here</a>.</p>
<p>To register a file type association you have to add an array of the type <code>CFBundleDocumentTypes</code>. Again, here is an extraction of the Tunnelblick application, which shows the registration of the <code class="path">tblk</code> extension:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleDocumentTypes<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;array<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dict<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleTypeExtensions<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;array<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>tblk<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/array<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleTypeIconFile<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>     <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>tunnelblick_package.icns<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleTypeName<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Tunnelblick VPN Configuration<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>CFBundleTypeRole<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Editor<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>LSTypeIsPackage<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;true</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>NSPersistentStoreTypeKey<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/key<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Binary<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dict<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/array<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>You have to provide a file extension or mime-type, can add an icon and give a hint what your application can do with this type of file (viewer, editor or nothing).</p>
<p>Beside this passive way of announcing this information, there is also an active way (e.g. for use in an installer). See <a href="http://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/Reference/reference.html#//apple_ref/doc/uid/TP30000998-CH1g-LSRegisterFSRef" target="_blank">here</a> for further information.</p>
<h2>Where is this information stored</h2>
<p>Although Mac OS X hasn't a registry like windows, some information are stored in global databases, too. Applications are registered at the <code class="cmd">launchd</code>. The launchd is the central place for starting all kind of programs, from a background service to any common application, like Thunderbird. E.g. background services can register itself and even made their start depending on different events. VirtualBox has an example configuration included, which let launchd start the <a href="http://www.virtualbox.org/browser/trunk/src/VBox/Installer/darwin/VirtualBox/org.virtualbox.vboxwebsrv.plist" target="_blank">vbox webservice</a> on activity on a certain port. Although this isn't used by many users out there (and therefore disabled by default), it shows some generic usage of this functionality.</p>
<p>If you look around in Mac OS X you have the tool <code class="cmd">launchctl</code>, which allows you to start jobs or register background services with launchd. But it seems there is no tool which is able to get some information about the knowledge of launchd. Well, there is one. It's a little bit hidden in <code class="cmd">/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister</code>. To be more comfortable with it, we should include it into the user path by linking it to a known path, like this:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-s</span> <span style="color: #000000; font-weight: bold;">/</span>Frameworks<span style="color: #000000; font-weight: bold;">/</span>CoreServices.framework<span style="color: #000000; font-weight: bold;">/</span>Versions<span style="color: #000000; font-weight: bold;">/</span>A<span style="color: #000000; font-weight: bold;">/</span>Frameworks<span style="color: #000000; font-weight: bold;">/</span>LaunchServices.framework<span style="color: #000000; font-weight: bold;">/</span>Versions<span style="color: #000000; font-weight: bold;">/</span>A<span style="color: #000000; font-weight: bold;">/</span>Support<span style="color: #000000; font-weight: bold;">/</span>lsregister <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>lsregister</pre></div></div>

<p>With this tiny tool we are able to dump the launchd database. <code class="cmd">lsregister -dump | grep -n10 Tunnelblick</code> displays something like this for Tunnelblick:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000;">10823</span>---------------------------------------------------------------------------------
<span style="color: #000000;">10824</span>-bundle    <span style="color: #c20cb9; font-weight: bold;">id</span>:            <span style="color: #000000;">6984</span>
<span style="color: #000000;">10825</span>:  path:          <span style="color: #000000; font-weight: bold;">/</span>Applications<span style="color: #000000; font-weight: bold;">/</span>Tunnelblick.app
<span style="color: #000000;">10826</span>-  name:
<span style="color: #000000;">10827</span>-  identifier:    com.openvpn.tunnelblick <span style="color: #7a0874; font-weight: bold;">&#40;</span>0x800097b8<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #000000;">10828</span>-  version:       <span style="color: #000000;">2132</span>
<span style="color: #000000;">10829</span>-  mod <span style="color: #c20cb9; font-weight: bold;">date</span>:      <span style="color: #000000;">10</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">31</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">2010</span> <span style="color: #000000;">12</span>:<span style="color: #000000;">37</span>:08
<span style="color: #000000;">10830</span>-  reg <span style="color: #c20cb9; font-weight: bold;">date</span>:      <span style="color: #000000;">11</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">19</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">2010</span> <span style="color: #000000;">11</span>:<span style="color: #000000;">13</span>:<span style="color: #000000;">39</span>
<span style="color: #000000;">10831</span>-  <span style="color: #7a0874; font-weight: bold;">type</span> code:     <span style="color: #ff0000;">'APPL'</span>
<span style="color: #000000;">10832</span>-  creator code:  <span style="color: #ff0000;">'OVPN'</span>
<span style="color: #000000;">10833</span>-  sys version:   <span style="color: #000000;">0</span>
<span style="color: #000000;">10834</span>-  flags:         relative-icon-path  ui-element
<span style="color: #000000;">10835</span>-  item flags:    container  package  application  extension-hidden  native-app  ppc  i386
<span style="color: #000000;">10836</span>-  icon:          Contents<span style="color: #000000; font-weight: bold;">/</span>Resources<span style="color: #000000; font-weight: bold;">/</span>tunnelblick.icns
<span style="color: #000000;">10837</span>:  executable:    Contents<span style="color: #000000; font-weight: bold;">/</span>MacOS<span style="color: #000000; font-weight: bold;">/</span>Tunnelblick
<span style="color: #000000;">10838</span>-  inode:         <span style="color: #000000;">3800129</span>
<span style="color: #000000;">10839</span>-  <span style="color: #7a0874; font-weight: bold;">exec</span> inode:    <span style="color: #000000;">3800213</span>
<span style="color: #000000;">10840</span>-  container <span style="color: #c20cb9; font-weight: bold;">id</span>:  <span style="color: #000000;">32</span>
<span style="color: #000000;">10841</span>-  library:
<span style="color: #000000;">10842</span>-  library items:
<span style="color: #000000;">10843</span>-  <span style="color: #660033;">--------------------------------------------------------</span>
<span style="color: #000000;">10844</span>-  claim   <span style="color: #c20cb9; font-weight: bold;">id</span>:            <span style="color: #000000;">17864</span>
<span style="color: #000000;">10845</span>:          name:          Tunnelblick VPN Configuration
<span style="color: #000000;">10846</span>-          rank:          Default
<span style="color: #000000;">10847</span>-          roles:         Editor
<span style="color: #000000;">10848</span>-          flags:         relative-icon-path  package
<span style="color: #000000;">10849</span>-          icon:          Contents<span style="color: #000000; font-weight: bold;">/</span>Resources<span style="color: #000000; font-weight: bold;">/</span>tunnelblick_package.icns
<span style="color: #000000;">10850</span>-          bindings:      .tblk
<span style="color: #000000;">10851</span>---------------------------------------------------------------------------------</pre></div></div>

<p>As you see, all the information provided by the plist file is registered. Beside other information, it also has the registration and modification times stored. To let launchd reread the plist file, usual its only necessary to change the modification time of the application. This could be done by simply executing <code class="cmd">touch /Applications/Application.app</code>. Anyway, it's sometimes necessary to reset the content of this database for the own application. This could be done by executing the following:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">lsregister <span style="color: #660033;">-u</span> <span style="color: #000000; font-weight: bold;">/</span>Applications<span style="color: #000000; font-weight: bold;">/</span>Application.app</pre></div></div>

<p>To register the application again, just remove the <code>-u</code> parameter. You should also check if your application isn't registered more than once, with different paths, by using the <code>-dump</code> parameter. To fully reset the launchd database, you could use <code>-kill</code>. This will remove any file type association and registered application. You have been <span style="color: #ff0000;">warned</span>.</p>
<h2>Conclusion</h2>
<p>This article shows how Mac OS X handle informations about installed applications. With this knowledge a developer is able to register the own application into the launchd ecosystem and see how launchd interpret this information. Furthermore, the usage of lsregister allows a developer to analyze the content of the launchd database and make changes to it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.64k-tec.de/2010/11/understanding-some-of-the-mysteries-of-launchd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing Linux on a USB hard disk for the MacBook Pro</title>
		<link>http://www.64k-tec.de/2010/04/installing-linux-on-a-usb-hard-disk-for-the-macbook-pro/</link>
		<comments>http://www.64k-tec.de/2010/04/installing-linux-on-a-usb-hard-disk-for-the-macbook-pro/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 02:29:11 +0000</pubDate>
		<dc:creator>cp</dc:creator>
				<category><![CDATA[IT]]></category>
		<category><![CDATA[Root]]></category>
		<category><![CDATA[administration]]></category>
		<category><![CDATA[boot]]></category>
		<category><![CDATA[Boot Camp]]></category>
		<category><![CDATA[EFI]]></category>
		<category><![CDATA[FireWire]]></category>
		<category><![CDATA[Gentoo]]></category>
		<category><![CDATA[hard disk]]></category>
		<category><![CDATA[installation]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[MacBook Pro]]></category>
		<category><![CDATA[removable media]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[USB]]></category>

		<guid isPermaLink="false">http://www.64k-tec.de/?p=885</guid>
		<description><![CDATA[One of the features of Mac OS X I love, is the possibility to install Mac OS X on any attached removable media, like a FireWire or USB hard disk. This makes it really easy for me to test VirtualBox on the several versions of Mac OS X we support (formerly Tiger, now Leopard and [...]]]></description>
			<content:encoded><![CDATA[<p>One of the features of Mac OS X I love, is the possibility to install Mac OS X on any attached removable media, like a FireWire or USB hard disk. This makes it really easy for me to test VirtualBox on the several versions of Mac OS X we support (formerly Tiger, now Leopard and Snow Leopard). The advantage of this setup is that I don't waste disk space for operation systems I usually don't use very often. Currently I have a 150GB hard disk in my MacBook Pro which is really not that much if you deal in the virtualization business. There are several test VM's of any kind of guest operation systems and of course the ISO's to install them. The second main OS, I do much of my work, is Linux. For this I have a standard PC with Gentoo on it, which have all that I need. Unfortunately this doesn't really help when I on travel. As I soon be away for some time, I decided I need, at least for testing, the same flexibility mentioned above for a Linux installation. And here the problems start to arise. Of course Apple didn't really support installing other OS's than Mac OS X on Apple hardware. Yes, there is Boot Camp, but this is mainly for Windows, is very inflexible and doesn't really help if you try to install something on another place than the integrated hard disk. There are projects like <a href="http://refit.sourceforge.net/" target="_blank">rEFIt</a>, which even makes Boot Camp superfluous, but this project has really bad USB boot support. In the following I will explain how it is even possible to install Ubuntu 9.10 on a USB hard disk.</p>
<p>The hardware used, as already said, is a MacBook Pro 3,1 and a Western Digital My Passport Essential 500GB USB hard disk. Other combination may work, but I don't guarantee this, as always. Also you should be warned that anything I describe here could destroy your existing installation and I'm not responsible for that. Doing some kind of backup might be a good idea. Time Machine is easy to use <img src='http://www.64k-tec.de/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p>Before we start, as usual, the credits for some sites I get my information from. This is mainly the <a href="http://www.produnis.de/blog/?p=678" target="_blank">Produnis blog</a>, <a href="http://blog.christophersmart.com/2009/07/23/linux-on-an-apple-xserve-efi-only-machine/" target="_blank">the Blog of Chris</a>, the <a href="https://wiki.ubuntu.com/MactelSupportTeam/CommunityHelpPages" target="_blank">Ubuntu wiki</a> and of course the guys around the <a href="http://grub.enbug.org/TestingOnMacbook" target="_blank">Grub2</a> development.</p>
<h2>Creating the EFI boot loader</h2>
<p>Apple doesn't use the legacy BIOS to boot their machines, they use the <a href="http://en.wikipedia.org/wiki/Extensible_Firmware_Interface" target="_blank"><em>Extensible Firmware Interface</em></a> (EFI). This new way of booting operation systems is very flexible, as the name suggest, but has several drawbacks, like most of the standard operation system doesn't speaks it language. Although Linux can be configured to use EFI directly we will emulate a legacy BIOS in the following. For this we need a connector which makes EFI and Linux happy and let them both work smoothly together. This connector is <a href="http://www.gnu.org/software/grub/" target="_blank">Grub2</a>, which is in development for several years now. It's the successor of Grub and is the standard in many popular Linux distributions these days. We have to build a version our self, for which an existing Linux installation is really helpful. I used my 64-bit Gentoo installation. First you have to find out if the EFI installation on your target Apple machine is 64 or 32-bit. You can do this by executing:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">ioreg <span style="color: #660033;">-l</span> <span style="color: #660033;">-p</span> IODeviceTree <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> firmware-abi</pre></div></div>

<p>This will return EFI64 or EFI32 respectively. In my case I need the 64-bit version, which is a little bit surprising when I consider that my MacBook Pro isn't able to boot a 64-bit Snow Leopard. Anyway, grab the <a href="ftp://alpha.gnu.org/gnu/grub/grub-1.98.tar.gz">latest version</a> of Grub2 and unpack it on the Linux machine. Please note that you need a gcc with multilib support if you are targeting an architecture which isn't the same as the host one. Use the following to configure Grub2 and to build it. Of course you have to adjust the target architecture if it is a different one.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">.<span style="color: #000000; font-weight: bold;">/</span>configure <span style="color: #660033;">--with-platform</span>=efi <span style="color: #660033;">--target</span>=x86_64 <span style="color: #660033;">--disable-werror</span>
<span style="color: #c20cb9; font-weight: bold;">make</span></pre></div></div>

<p>When this is finished you create the EFI package by executing<a name="mkimage"></a></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">.<span style="color: #000000; font-weight: bold;">/</span>grub-mkimage <span style="color: #660033;">-d</span> . <span style="color: #660033;">-o</span> bootx86.efi <span style="color: #000000; font-weight: bold;">*</span>.mod</pre></div></div>

<p>Here I included all modules which are available. If size matter for you, you could of course make a selective choice on the modules included. I didn't test this myself, so you have to find out yourself which one are important.</p>
<h2>Whipping the USB hard disk into shape</h2>
<p style="text-align: left;">Next we have to prepare the USB hard disk for the new installation. In the following I assume your USB hard disk doesn't contain any valid data and could be reformatted without data lose. Make a backup of your data first if this isn't the case on your side. Apple uses the <a href="http://en.wikipedia.org/wiki/GUID_Partition_Table" target="_blank">GUID Partition Table</a> scheme to organize their partitions on a hard disk. This specification is part of EFI and remove many limitations of the <em><a href="http://en.wikipedia.org/wiki/Master_Boot_Record" target="_blank">Master boot record</a></em> (MBR) scheme, which is widely used in the PC world. That is e.g. the disk size limitation of 2TB or the maximum of 4 primary partitions. You reformat your disk, using the Disk Utility application of Mac OS X. Make sure all existing partitions on the disk are unmounted. When necessary, change the partition scheme from MBR to GUID in the Options dialog of the Partitions window. Select the partitions count you want to use. You need at least 3 partitions to make Linux works fine. My partition scheme looks like in the following: <a href="/wordpress/wp-content/uploads/Disk-Utility.png"><img class="aligncenter size-full wp-image-972" title="GUID Partition Table scheme" src="/wordpress/wp-content/uploads/Disk-Utility.png" alt="" width="188" height="390" /></a>As you can see I have 5 partitions configured. The first one is an additional Snow Leopard installation for testing. I also added a Data partition at the end for making the data transfer between the different operation systems as easy as possibly. LINUXBOOT is a small partition which will contain the EFI boot loader (size it 50MB or something like that). Linux Swap, obviously, will become the swap partition of the Linux installation. DISK1S5 is the Linux root partition itself. The Data partition has to be formated as Mac OS Extended. Don't use the Journaled version of HFS+, cause this makes trouble on the Linux side. The other partitions have to be formatted as MS-DOS (FAT).</p>
<p>After applying the changes we can add the EFI boot loader to the LINUXBOOT partition. The Apple EFI implementation is searching for a file with the efi extensions on all bootable hard disks. Mount LINUXBOOT and create a <code class="path">efi/boot</code> directory on the root path. Copy the <a href="#mkimage">bootx86.efi</a> file into the boot/ directory. As bootx86.efi is a Grub2 boot loader we need a valid Grub2 configuration file. The following <code class="path">grub.cfg</code> shows the configuration for a Ubuntu 9.10 i386 installation. For the 64-bit version or any other version of Ubuntu the settings might be slightly different.</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;"><span style="color: #000099;">menuviewer</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #933;">&quot;text&quot;</span>
<span style="color: #000099;">timeout</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">10</span>
<span style="color: #000099;">default</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">0</span>
set F1<span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">ctrl-x</span>
menuentry <span style="color: #933;">&quot;ubuntu-9.10-desktop-i386&quot;</span>
<span style="">&#123;</span>
 fakebios
 search --set -f /boot/vmlinuz-2.6.31-<span style="">14</span>-generic
 linux /boot/vmlinuz-2.6.31-<span style="">14</span>-generic root<span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">UUID=4e140981-4ab3-41a2-a2fb-26b1287beb87 ro quiet splash noefi video=efifb</span>
 initrd /boot/initrd.img-2.6.31-<span style="">14</span>-generic
<span style="">&#125;</span>
menuentry <span style="color: #933;">&quot;ubuntu-9.10-desktop-i386 single&quot;</span>
<span style="">&#123;</span>
 fakebios
 search --set -f /boot/vmlinuz-2.6.31-<span style="">14</span>-generic
 linux /boot/vmlinuz-2.6.31-<span style="">14</span>-generic root<span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">UUID=4e140981-4ab3-41a2-a2fb-26b1287beb87 ro noefi video=efifb single</span>
 initrd /boot/initrd.img-2.6.31-<span style="">14</span>-generic
<span style="">&#125;</span>
menuentry <span style="color: #933;">&quot;ubuntu-9.10-desktop-i386 text&quot;</span>
<span style="">&#123;</span>
 fakebios
 search --set -f /boot/vmlinuz-2.6.31-<span style="">14</span>-generic
 linux /boot/vmlinuz-2.6.31-<span style="">14</span>-generic root<span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">UUID=4e140981-4ab3-41a2-a2fb-26b1287beb87 ro noefi vga=normal</span>
 initrd /boot/initrd.img-2.6.31-<span style="">14</span>-generic
<span style="">&#125;</span>
menuentry <span style="color: #933;">&quot;Mac OS X&quot;</span>
<span style="">&#123;</span>
 search --set -f /usr/standalone/i386/boot.efi
 chainloader /usr/standalone/i386/boot.efi
<span style="">&#125;</span>
menuentry <span style="color: #933;">&quot;CD&quot;</span>
<span style="">&#123;</span>
 appleloader CD
<span style="">&#125;</span>
menuentry <span style="color: #933;">&quot;mbr&quot;</span>
<span style="">&#123;</span>
 appleloader HD
<span style="">&#125;</span>
menuentry <span style="color: #933;">&quot;reboot&quot;</span>
<span style="">&#123;</span>
 reboot
<span style="">&#125;</span></pre></div></div>

<p>You have to change the root UUID to the one the Ubuntu installer will assign to your hard disk after installation. Just check the fstab file when the installation has finished. The first entry boots Linux with a splash image enabled. The second one is for the single user mode in the case something went wrong. Please note the <strong>video=efifb</strong> option, which enables the graphical mode in the boot phase.</p>
<h2>Installing Ubuntu</h2>
<p>Most of the installation process is straight forward and doesn't need any special attention. Download the version of your choice from one of the mirrors, burn it on CD and start the installation. You can select the CD as boot medium by pressing <code class="key">Alt</code> when your Mac starts. When the installer ask for the partition scheme, you have to switch to "manual choice". Select the DISK1S5 (your what it is in your case) as the root / partition and change the filesystem type to ext3. Also remember the path to the system partition, cause you will need it later again. Select the swap partition and change its type to swap. Proceed with the rest of the installation until the last dialog. There select "advanced settings" and change the boot loader target from <code class="path">hd0</code> to <code class="path">/dev/sdXX</code>, where you replace XX to the path you used previously in the partition tool.</p>
<p>If all went right you should be able to select the LINUXBOOT partition by pressing <code class="key">Alt</code> when your Mac starts. After that Grub2 should shows up, you will be able to boot into your freshly installed Ubuntu.</p>
<h2>Conclusion</h2>
<p>In this post I showed how to easily add the possibility to boot Linux on your MacBook Pro. With the external USB hard disk solution, no internal valuable space is wasted. Of course the speed isn't the same as if the OS would be installed on the internal drive, but for testing software on different operation systems this is satisfactory. To increase the speed a little bit more, an external FireWire hard disk could be used.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.64k-tec.de/2010/04/installing-linux-on-a-usb-hard-disk-for-the-macbook-pro/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

