<?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>Chris Luke</title>
	<atom:link href="http://blog.flirble.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.flirble.org</link>
	<description>The thoughts of a lost Flirbler</description>
	<lastBuildDate>Sun, 10 Apr 2011 15:19:03 +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>FreeBSD ports&#8230; good but a pain.</title>
		<link>http://blog.flirble.org/2011/04/10/freebsd-ports-good-but-pain/</link>
		<comments>http://blog.flirble.org/2011/04/10/freebsd-ports-good-but-pain/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 14:55:49 +0000</pubDate>
		<dc:creator>Chris Luke</dc:creator>
				<category><![CDATA[Otherwise Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.flirble.org/?p=637</guid>
		<description><![CDATA[So. I wanted to install gnupg on a FreeBSD box. Somehow it depended on something that depended on the LDAP libraries. Which broke authentication on the box. And in fixing that, lots of other dependencies needed to be updated]]></description>
			<content:encoded><![CDATA[<p>So. I wanted to install <code class="codecolorer text default"><span class="text">gnupg</span></code> on a FreeBSD box. Somehow it depended on something that depended on the LDAP libraries. Which broke authentication on the box. And in fixing that, lots of other dependencies needed to be updated. It turned into a horrible mess and some ports wouldn&#8217;t reinstall cleanly and no amount of <code class="codecolorer text default"><span class="text">portupgrade</span></code>/<code class="codecolorer text default"><span class="text">portmaster</span></code> shenanigans would fix it without removing swathes of stuff first.</p>
<p>In trying to find out which shared libraries were now broken, I wrote a <em>very</em> crude script to find out which binaries broke.<br />
<span id="more-637"></span></p>
<div class="codecolorer-container bash default codecolorer-title" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;">find-broken-libs</div><div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#!/bin/sh</span><br />
<span style="color: #666666; font-style: italic;"># simple hack to find local binaries with broken library dependencies</span><br />
<br />
<span style="color: #007800;">dirs</span>=<span style="color: #007800;">$*</span><br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$dirs</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #007800;">dirs</span>=<span style="color: #ff0000;">&quot;/usr/local/bin /usr/local/sbin /usr/local/libexec /usr/local/lib&quot;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">for</span> <span style="color: #c20cb9; font-weight: bold;">dir</span> <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #007800;">$dirs</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$dir</span>&quot;</span><span style="color: #000000; font-weight: bold;">/*</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-x</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$file</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">l</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">ldd</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$file</span>&quot;</span> <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #ff0000;">&quot;=&gt; not found&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/=&gt; not found.*//'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$l</span>&quot;</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">p</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">basename</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$file</span>&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">pkg</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">find</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>db<span style="color: #000000; font-weight: bold;">/</span>pkg <span style="color: #660033;">-type</span> f <span style="color: #660033;">-name</span> <span style="color: #ff0000;">'+CONTENTS'</span> <span style="color: #660033;">-print0</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">xargs</span> <span style="color: #660033;">-0</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #ff0000;">&quot;/<span style="color: #007800;">$p</span><span style="color: #000099; font-weight: bold;">\$</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">cut</span> -d: <span style="color: #660033;">-f1</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sort</span> <span style="color: #660033;">-u</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/^.var.db.pkg.//'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/.+CONTENTS$//'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$p</span>: <span style="color: #007800;">$pkg</span>: <span style="color: #007800;">$l</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">done</span><br />
<span style="color: #000000; font-weight: bold;">done</span></div></td></tr></tbody></table></div>
<p>In short, it finds executable files that <code class="codecolorer text default"><span class="text">ldd</span></code> reports as having missing runtime dependencies and attempts to find those in the package directory (so you have a clue what packages it came from).</p>
<p>I renamed <code class="codecolorer text default"><span class="text">libfam</span></code> to something else and this was the output:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># sh /home/chrisy/bin/find-broken-libs<br />
imapd: courier-imap-4.8.1,2 imap-uw-2007e,1: libfam.so.0<br />
maildiracl: courier-imap-4.8.1,2: libfam.so.0<br />
maildirkw: courier-imap-4.8.1,2: libfam.so.0<br />
maildrop: maildrop-2.5.2: libfam.so.0</div></td></tr></tbody></table></div>
<p>First field is the file that is broken. Second field are packages that have files with that name. Last field are the missing libraries.</p>
<p>If no package uses a broken binary then that field in the output stays blank, wit:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># sh ~chrisy/bin/find-broken-libs<br />
libgnutls-extra.so.15: : libintl.so.8 libintl.so.8<br />
libgnutls-openssl.so.15: : libintl.so.8 libintl.so.8<br />
libgnutls.so.15: : libintl.so.8<br />
libgnutlsxx.so.15: : libintl.so.8</div></td></tr></tbody></table></div>
<p>I&#8217;m posting this in case someone else finds it useful&#8230;</p>

]]></content:encoded>
			<wfw:commentRss>http://blog.flirble.org/2011/04/10/freebsd-ports-good-but-pain/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ABC of the Sea released!</title>
		<link>http://blog.flirble.org/2011/02/11/abc-sea-released/</link>
		<comments>http://blog.flirble.org/2011/02/11/abc-sea-released/#comments</comments>
		<pubDate>Fri, 11 Feb 2011 18:31:54 +0000</pubDate>
		<dc:creator>Chris Luke</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[ABC of the Sea]]></category>
		<category><![CDATA[app store]]></category>
		<category><![CDATA[book]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://blog.flirble.org/?p=623</guid>
		<description><![CDATA[About a week ago ABC of the Sea was accepted by Apple for inclusion in the App Store! It&#8217;s a universal app that will work on all recent iOS devices but it really is visually more exciting on the iPad. Obligatory plug: It&#8217;s only 99¢ (or other local denomination)! Go buy it! ABC of the [...]]]></description>
			<content:encoded><![CDATA[<p>About a week ago <em><a title="ABC of the Sea at the App Store!" href="http://itunes.com/app/abcsea">ABC of the Sea</a></em> was accepted by Apple for inclusion in the App Store! It&#8217;s a universal app that will work on all recent iOS devices but it really is visually more exciting on the iPad.</p>
<p><strong>Obligatory plug: It&#8217;s only 99¢ (or other local denomination)! <a title="ABC of the Sea at the iTunes App Store!" href="http://itunes.com/app/abcsea" target="_self">Go buy it!</a></strong><a href="http://itunes.com/app/abcsea"><img class="alignright" title="Buy ABC of the Sea on the App Store!" src="http://www.flirble.org/iphone/appstore-115.png" alt="" width="115" height="40" /></a></p>
<p><em>ABC of the Sea</em> is a children-focussed animated book featuring 26 pages of hand-drawn marine life. The illustrations were originally produced by my wife many years ago but never published. Our own child can now read and a print of the book surfaced which she thoroughly enjoyed. We then had the idea to turn it into an iPad application. Each page has been carefully, but subtly animated in a fashion largely consistent with how the creature (or plant) behaves in its natural habitat, though some artistic license has been taken if the real-life movements would be virtually undetectable.<span id="more-623"></span></p>
<p>Visually it&#8217;s lovely and the simplicity of the images and the text are deliberate so that young-readers will enjoy it, but also so that even children who do not read yet will benefit. Planned updates include more information for each page describing the creature and its habits and narrated names and text.</p>
<h2>
<div id="attachment_19" class="wp-caption alignright" style="width: 310px"><a href="http://blog.flirble.org/wp-content/uploads/2010/10/octopus-small.png" rel="shadowbox[sbpost-623];player=img;"><img class="size-full wp-image-19" title="Octopus" src="http://blog.flirble.org/wp-content/uploads/2010/10/octopus-small.png" alt="Octopus" width="300" height="300" /></a><p class="wp-caption-text">ABC of the Sea: O is for Octopus</p></div>
<p>Behind the scenes</h2>
<p>However, the real magic is under the hood. For me this was an ideal opportunity to dive into the innards of iOS, its graphics capabilities and more besides. There were a handful of key development areas that made this book a possibility.</p>
<p>Firstly, though Apple has an app, iBooks, with a visually remarkable page turning transition, that effect is not available to other developers. Some of the functionality exists in iOS, but it is undocumented and thus would not pass muster with the app store moderators. As<a title="The anatomy of a page curl" href="http://blog.flirble.org/2010/10/08/the-anatomy-of-a-page-curl/" target="_self"> I documented in October last year</a> there are a number of 3<span style="font-size: 50%; vertical-align: super;">rd</span> party attempts to fake this effect but with more than a moments glance the approximation becomes obvious. Based on some OpenGL work by W. Dana Nuon, <a style="font-style: italic;" title="Implementing iBooks page curling using a conical deformation algorithm" href="http://wdnuon.blogspot.com/2010/05/implementing-ibooks-page-curling-using.html" target="_blank">Implementing iBooks page curling using a conical deformation algorithm</a>, I came up with an implementation of my own and some of that work is present within <em>ABC of the Sea</em>. After some more work I will probably be licensing this mechanism, if there&#8217;s interest in it. In particular it provides a framework for a developer to provide his own deformation and position-mapping algorithm should mine not be quite what is desired!</p>
<div id="attachment_628" class="wp-caption alignleft" style="width: 310px"><a href="http://blog.flirble.org/wp-content/uploads/2011/02/dolphin.png" rel="shadowbox[sbpost-623];player=img;"><img class="size-medium wp-image-628" title="Dolphin" src="http://blog.flirble.org/wp-content/uploads/2011/02/dolphin-300x246.png" alt="Dolphin" width="300" height="246" /></a><p class="wp-caption-text">D is for Dolphin</p></div>
<p>I then had the task of animating the critters. There are many frameworks out there, both opensource and paid-for, but mostly these are geared for gaming with events engines and whatnot. Many of them were in varying degrees of completeness and they all had their own learning curves. Ultimately I decided to roll my own since I knew my needs were very simple. It makes extensive use of the animation built into the<code class="codecolorer text default"><span class="text">UIView</span></code> and <code class="codecolorer text default"><span class="text">CALayer</span></code> classes and provides a simple mechanism to define, entirely in property lists, the sprites and their component parts and relative positioning, their locations on the page, the name of a path to apply and the operations that comprise a path. The operations needed were simple: timing, move and rotate. Movement can be direct or use a Bezier path. Both can incorporate randomness. The results are well exercised throughout <em>ABC of the Sea</em>. I will probably also license this code in due course.</p>
<p>The simplest sprites were animated in well under 30 minutes &#8211; which includes whatever sprite dissection necessary to turn an image into its component parts. The most complicated pages took a few hours &#8211; and most of that is spent working in a graphics application working out how best to decompose a creature.</p>
<div id="attachment_631" class="wp-caption aligncenter" style="width: 490px"><a href="http://blog.flirble.org/wp-content/uploads/2011/02/Default-e1297448895456.png" rel="shadowbox[sbpost-623];player=img;"><img src="http://blog.flirble.org/wp-content/uploads/2011/02/Default-e1297448895456.png" alt="ABC of the Sea" title="ABC of the Sea launch image" width="480" height="320" class="size-full wp-image-631" /></a><p class="wp-caption-text">ABC of the Sea cover page</p></div>
<p>If you have small children, or simply want to see how my page transition code works, I encourage you to purchase the app!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.flirble.org/2011/02/11/abc-sea-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using an RSA public key generated by OpenSSL in iOS</title>
		<link>http://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/</link>
		<comments>http://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/#comments</comments>
		<pubDate>Wed, 05 Jan 2011 05:00:48 +0000</pubDate>
		<dc:creator>Chris Luke</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Cryptography]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[OpenSSL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Public Key]]></category>
		<category><![CDATA[RSA]]></category>

		<guid isPermaLink="false">http://blog.flirble.org/?p=601</guid>
		<description><![CDATA[I was developing a mechanism to verify some data that was generated and signed outside of an iOS device. Using a simple key pair generated by OpenSSL at a command line it was very simple to create scripts in Perl and PHP to produce (and sign) and then decode (and validate) some data using this key pair. The functions to add a public or a private key to the keychain are there in iOS but they don't work as expected.]]></description>
			<content:encoded><![CDATA[
<p>Apple have gone to pains to make crypto in iOS (and MacOS in general) secure, building a layer between applications and the low-level stuff, like OpenSSL. The principle is to keep these functions in separate address space thus significantly reducing the surface area available for malicious code to find a weakness. In iOS this separation is enforced and, significantly, the documentation is sparse and terse. Public/private key use without also using certificates is mentioned but only in the context of using keys generated on the device. Posts on the Apple Developer forums indicate that using certificates is suggested because using public/private key pairs is &#8220;involved&#8221;. It turns out that the reason it&#8217;s involved is because of some odd implementation details and the aforementioned lack of documentation or useful examples.</p>
<p>I was developing a mechanism to verify some data that was generated outside the device. Using a simple key pair generated by OpenSSL at a command line it was very simple to create scripts in Perl and PHP to produce (and sign) and then decode (and validate) some data using this key pair. The functions to add a public or a private key to the keychain are there in iOS but they don&#8217;t work as expected.<span id="more-601"></span></p>
<h2>It&#8217;s all in the format</h2>
<p>There are <a href="http://en.wikipedia.org/wiki/PKCS">many ways to transmit a key</a> for use by another system but there are also some defacto standards. For an RSA public or private key, which has a pretty straightforward internal structure, that would be defined by <a href="http://en.wikipedia.org/wiki/PKCS1">PKCS#1</a>.</p>
<p>There are two common forms to transmitting and using an RSA public or private key. ASN.1 DER &#8211; which is a <em>non-displayable</em> (i.e., not ASCII) format, or the same thing but base64 encoded and referred to as PEM &#8211; which is 7-bit ASCII and thus displayable. The base64 format is usually wrapped with something like <code class="codecolorer text default"><span class="text">-----BEGIN PUBLIC KEY-----</span></code> (which is what OpenSSL produces) or <code class="codecolorer text default"><span class="text">-----BEGIN RSA PUBLIC KEY-----</span></code>.</p>
<p>You can have OpenSSL generate a key pair very easily and you select the output form right on the command line:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">chrisy@baud:~/keytmp$ openssl genrsa -out testkeypair.pem 1024<br />
Generating RSA private key, 1024 bit long modulus<br />
.......++++++<br />
...........++++++<br />
e is 65537 (0x10001)<br />
chrisy@baud:~/keytmp$ more testkeypair.pem <br />
-----BEGIN RSA PRIVATE KEY-----<br />
MIICXgIBAAKBgQDBm8yuHmd0P6scl48DEi+xp47wXVZaKWRygGKtA2XkdRuCU99f<br />
0Tq07Llcgf8XuR+Wnk+z2CdMMFMzOGhCePblVIAn33dcBVlDokpBF7AnTClsaLci<br />
xxZw1LIUiaPaBdN7oG8vt3G2caLHRrrkoEnccY+6GadfH7iuHdcVsz1mowIDAQAB<br />
AoGAWEt1TPMQuzNOFfwIfJ4OojaIOZZXi0bVSGLEnaKvFUFTCly1wjzpSRmsb0PZ<br />
0jfa8BXCw4IQae6gAvv2kFoaPjAiohDRzsNL7r5VfWqYh2rvXM7FEa5Zl6EvhHm1<br />
MdLVgqKW2gAN5N1dBqpRvzo0H8zEcbqH7a4gAyQivaxGXgECQQDz59utDOP1VS5L<br />
VVnr57M4x99/lrxHNuiTmKdwKtjhB2bZQy2R5SPC7xHF5lFfMOW35tg/6ZjCeEC/<br />
KvPYZXNNAkEAyzV4KKcL4+7S7AZ7LcmraYY2UHFAyGkS/RBVLLaTcGIZOyrw9Pez<br />
M+S8kRERO7lblStcptCd4leTtPXY0X1prwJBAOiqk7bXZhmg4SGB0N6lzyRqHfzD<br />
GOXCLkilxYvNg8fd3LGCUNUsxVlt3wFufM8WgPxWHJGTT2KrffAelDAoTr0CQQCA<br />
9DSFb8Ru596340EGBIWfmIkdMVGQHIXtTBERJ+eWmNo0HwL8Ibh6BPzY/kC2auFA<br />
X10Tiy22NidI3f6yqmiHAkEA1H/bkwBulMSoo1ylLCF1m482ucOY7wWnJ77ARc3X<br />
f5KJtsWSDfQiHP1UyJrnlZz+JLWH4fWuFm1ZPHZca38eBg==<br />
-----END RSA PRIVATE KEY-----<br />
<br />
chrisy@baud:~/keytmp$ openssl rsa -in testkeypair.pem -pubout -outform PEM -out testpublic.pem<br />
writing RSA key<br />
chrisy@baud:~/keytmp$ more testpublic.pem <br />
-----BEGIN PUBLIC KEY-----<br />
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBm8yuHmd0P6scl48DEi+xp47w<br />
XVZaKWRygGKtA2XkdRuCU99f0Tq07Llcgf8XuR+Wnk+z2CdMMFMzOGhCePblVIAn<br />
33dcBVlDokpBF7AnTClsaLcixxZw1LIUiaPaBdN7oG8vt3G2caLHRrrkoEnccY+6<br />
GadfH7iuHdcVsz1mowIDAQAB<br />
-----END PUBLIC KEY-----</div></td></tr></tbody></table></div>
<h2>Sign here</h2>
<p>So far so good. In PHP we can use the PEM encoded keys directly. For example, to acquire the signature of some data, one could do this:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?</span> php<br />
&nbsp;<span style="color: #000000; font-weight: bold;">function</span> sign_data<span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #339933;">,</span> <span style="color: #000088;">$rsaprivkeyfile</span><span style="color: #009900;">&#41;</span><br />
&nbsp;<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #000088;">$rsakey</span> <span style="color: #339933;">=</span> <span style="color: #990000;">openssl_pkey_get_private</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$rsaprivkeyfile</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$rsakey</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp;<span style="color: #000088;">$signed_data</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!@</span><span style="color: #990000;">openssl_sign</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #339933;">,</span> <span style="color: #000088;">$signed_data</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$rsakey</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>-----BEGIN DATA-----<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #990000;">chunk_split</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">base64_encode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$license_data</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0000ff;">&quot;-----END DATA-----<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0000ff;">&quot;-----BEGIN SIGNATURE-----<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #990000;">chunk_split</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">base64_encode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$signed_data</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0000ff;">&quot;-----END SIGNATURE-----&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #009900;">&#125;</span><br />
<br />
<br />
&nbsp;<span style="color: #000000; font-weight: bold;">?&gt;</span><br />
&nbsp;</div></td></tr></tbody></table></div>
<p>The format being returned is not a standard, it&#8217;s something I made up, but it&#8217;s easily transmitted and base64 implementations are pretty universal.</p>
<p>How would we verify the integrity of this message? Here&#8217;s a crude example:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?</span> php<br />
&nbsp;<span style="color: #000000; font-weight: bold;">function</span> verify_message<span style="color: #009900;">&#40;</span><span style="color: #000088;">$message</span><span style="color: #339933;">,</span> <span style="color: #000088;">$rsapubkeyfile</span><span style="color: #009900;">&#41;</span><br />
&nbsp;<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #000088;">$rsakey</span> <span style="color: #339933;">=</span> <span style="color: #990000;">openssl_pkey_get_public</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$rsapubkeyfile</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$rsakey</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">// Extract the two sections</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #000088;">$lines</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$message</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #000088;">$a_dat</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #000088;">$a_sig</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #000088;">$f_dat</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #000088;">$f_sig</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$lines</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$line</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$l</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$line</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$l</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'-----BEGIN DATA-----'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$f_dat</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$f_sig</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$l</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'-----END DATA-----'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$f_dat</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$f_sig</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$l</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'-----BEGIN SIGNATURE-----'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$f_dat</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$f_sig</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$l</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'-----END SIGNATURE-----'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$f_dat</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$f_sig</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$f_dat</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$a_dat</span><span style="color: #339933;">.</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$line</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$f_sig</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000088;">$a_sig</span><span style="color: #339933;">.</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$line</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$a_dat</span> <span style="color: #339933;">||</span> <span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$a_dat</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$a_sig</span> <span style="color: #339933;">||</span> <span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$a_sig</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp;<span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #339933;">@</span><span style="color: #990000;">base64_decode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$a_dat</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #000088;">$sig</span> &nbsp;<span style="color: #339933;">=</span> <span style="color: #339933;">@</span><span style="color: #990000;">base64_decode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$a_sig</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">// Validate signature</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #339933;">@</span><span style="color: #990000;">openssl_verify</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sig</span><span style="color: #339933;">,</span> <span style="color: #000088;">$rsakey</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #009900;">&#125;</span><br />
<br />
<br />
&nbsp;<span style="color: #000000; font-weight: bold;">?&gt;</span><br />
&nbsp;</div></td></tr></tbody></table></div>
<p>With this little nugget of code it becomes trivial to find out if someone has been tampering with the data. This is useful, for example, for software licenses. Assuming the private key is kept secure you have a degree of trust that anything signed by it is also secure.</p>
<h2>So what&#8217;s the problem with iOS?</h2>
<p>iOS provides a security framework but if you try to use it for keys you generated elsewhere then it doesn&#8217;t work and gives only very limited indications <em>why</em> it doesn&#8217;t work.</p>
<p>iOS does not provide documented direct access to the OpenSSL API. If it&#8217;s there it wouldn&#8217;t matter &#8211; being undocumented means that it would face App Store rejection if their static analysis showed use of the undocumented library.</p>
<p>You <em>could</em> statically link an OpenSSL library that you compiled and it would work but in that situation it&#8217;s your app providing the cryptography code and thus you will need to jump some hurdles (you may need a <a href="http://en.wikipedia.org/wiki/Commodity_Classification_Automated_Tracking_System">CCATS</a>) to get export clearance for your app (although it&#8217;s not that simple in general &#8211; read the <em>Export Compliance</em> FAQ in iTunes Connect). In my case, I&#8217;m using a signed software license to prevent piracy &#8211; digital rights management &#8211; and thus does not need US Government clearance &#8211; but only if I include only enough code to perform that function. If I link against the whole of OpenSSL then what my app is doing will be less clearly defined.</p>
<p>So the key to a simple life is to work out why the provided functions don&#8217;t work.</p>
<h2>What&#8217;s in a key?</h2>
<p>It comes down to format.</p>
<p>The first clue is that if you use iOS to generate a key pair then the resulting form is not ASCII. So that rules out PEM and means that if you have a PEM formatted key, you&#8217;ll also need a base64 decoder &#8211; which iOS does <em>not</em> provide. There&#8217;s plenty of them around. I used <a href="http://cocoawithlove.com/2009/06/base64-encoding-options-on-mac-and.html"><code class="codecolorer text default"><span class="text">NSData+Base64.m</span></code></a> which if you Google for you will find many varied implementations and derivations of.</p>
<p>But that is not enough, even though an Apple employee confirms on the dev forums that iOS wants a PKCS#1 key and if you&#8217;re doing signature verification, that the signature is of the SHA1 hash of the data, as I would expect.</p>
<p>The next clue came when I noticed the keys produced by iOS don&#8217;t have the normal binary ASN.1 preamble to identify itself as a PKCS#1 key. This prompted some searching and I came across <a href="http://blog.wingsofhermes.org/?p=42">this post</a> talking exactly about this issue. I have no idea why it did not come up in my earlier searching. In it Berin explains his similar discovery, but also that the payload still looks like a binary PKCS#1 key, just without the preamble. In his application he had to add the header so he could import the key elsewhere. What I wanted was the reverse.</p>
<p>And so I did the reverse. And it worked.</p>
<p>And then I came across <a href="http://blog.wingsofhermes.org/?p=75">this later post by Berin</a> also doing what I wanted. Doh. Our implementations are not identical, but functionally similar.</p>
<h2>Code or it didn&#8217;t happen</h2>
<p>Assuming you have your OpenSSL generated RSA public key in an NSData object, this method will verify that it is in fact a PKCS#1 key and strip the header:</p>
<div class="codecolorer-container objc default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>stripPublicKeyHeader<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>d_key<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Skip ASN.1 public key header</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>d_key <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">int</span> len <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>d_key length<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>len<span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">char</span> <span style="color: #002200;">*</span>c_key <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">char</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>d_key bytes<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">int</span> &nbsp;idx &nbsp; &nbsp;<span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>c_key<span style="color: #002200;">&#91;</span>idx<span style="color: #002200;">++</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">!=</span> 0x30<span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>c_key<span style="color: #002200;">&#91;</span>idx<span style="color: #002200;">&#93;</span> &gt; 0x80<span style="color: #002200;">&#41;</span> idx <span style="color: #002200;">+=</span> c_key<span style="color: #002200;">&#91;</span>idx<span style="color: #002200;">&#93;</span> <span style="color: #002200;">-</span> 0x80 <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span>;<br />
&nbsp; &nbsp; <span style="color: #a61390;">else</span> idx<span style="color: #002200;">++</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// PKCS #1 rsaEncryption szOID_RSA_RSA</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">static</span> <span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">char</span> seqiod<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#123;</span> 0x30, &nbsp; 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,<br />
&nbsp; &nbsp; &nbsp;0x01, 0x05, 0x00 <span style="color: #002200;">&#125;</span>;<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">memcmp</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>c_key<span style="color: #002200;">&#91;</span>idx<span style="color: #002200;">&#93;</span>, seqiod, <span style="color: #2400d9;">15</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; idx <span style="color: #002200;">+=</span> <span style="color: #2400d9;">15</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>c_key<span style="color: #002200;">&#91;</span>idx<span style="color: #002200;">++</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">!=</span> 0x03<span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>c_key<span style="color: #002200;">&#91;</span>idx<span style="color: #002200;">&#93;</span> &gt; 0x80<span style="color: #002200;">&#41;</span> idx <span style="color: #002200;">+=</span> c_key<span style="color: #002200;">&#91;</span>idx<span style="color: #002200;">&#93;</span> <span style="color: #002200;">-</span> 0x80 <span style="color: #002200;">+</span> <span style="color: #2400d9;">1</span>;<br />
&nbsp; &nbsp; <span style="color: #a61390;">else</span> idx<span style="color: #002200;">++</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>c_key<span style="color: #002200;">&#91;</span>idx<span style="color: #002200;">++</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">!=</span> <span style="color: #bf1d1a;">'<span style="color: #2400d9;">\0</span>'</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Now make a new NSData from this buffer</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> dataWithBytes<span style="color: #002200;">:&amp;</span>c_key<span style="color: #002200;">&#91;</span>idx<span style="color: #002200;">&#93;</span> length<span style="color: #002200;">:</span>len <span style="color: #002200;">-</span> idx<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
&nbsp;</div></td></tr></tbody></table></div>
<p>and the result can be fed into the iOS functions in the expected manner. For example, this code adds a keychain reference to a public key to an array. If you use this, don&#8217;t forget to eventually  <code class="codecolorer objc default"><span class="objc">CFRelease<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span></span></code> each SecKeyRef you acquire, and don&#8217;t forget that <code class="codecolorer text default"><span class="text">tag</span></code> needs to be unique for every key you add.</p>
<div class="codecolorer-container objc default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>addPublicKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>key withTag<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>tag<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>s_key <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> <span style="color: #a61390;">string</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #400080;">NSArray</span> &nbsp;<span style="color: #002200;">*</span>a_key <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>key componentsSeparatedByString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;<span style="color: #2400d9;">\n</span>&quot;</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #a61390;">BOOL</span> &nbsp; &nbsp; f_key &nbsp;<span style="color: #002200;">=</span> FALSE;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>a_line <span style="color: #a61390;">in</span> a_key<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>a_line isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;-----BEGIN PUBLIC KEY-----&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f_key <span style="color: #002200;">=</span> TRUE;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>a_line isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;-----END PUBLIC KEY-----&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f_key <span style="color: #002200;">=</span> FALSE;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>f_key<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s_key <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>s_key stringByAppendingString<span style="color: #002200;">:</span>a_line<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>s_key.length <span style="color: #002200;">==</span> <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span>FALSE<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// This will be base64 encoded, decode it.</span><br />
&nbsp; &nbsp; <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>d_key <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> dataFromBase64String<span style="color: #002200;">:</span>s_key<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; d_key <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #a61390;">self</span> stripPublicKeyHeader<span style="color: #002200;">:</span>d_key<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>d_key <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span>FALSE<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>d_tag <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> dataWithBytes<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>tag UTF8String<span style="color: #002200;">&#93;</span> length<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>tag length<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Delete any old lingering key with the same tag</span><br />
&nbsp; &nbsp; <span style="color: #400080;">NSMutableDictionary</span> <span style="color: #002200;">*</span>publicKey <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableDictionary</span> <span style="color: #a61390;">alloc</span><span style="color: #002200;">&#93;</span> <span style="color: #a61390;">init</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>publicKey setObject<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> kSecClassKey forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecClass<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>publicKey setObject<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> kSecAttrKeyTypeRSA forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecAttrKeyType<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>publicKey setObject<span style="color: #002200;">:</span>d_tag forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecAttrApplicationTag<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; SecItemDelete<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>publicKey<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; CFTypeRef persistKey <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Add persistent version of the key to system keychain</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>publicKey setObject<span style="color: #002200;">:</span>d_key forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecValueData<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>publicKey setObject<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> kSecAttrKeyClassPublic forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span><br />
&nbsp; &nbsp; &nbsp;kSecAttrKeyClass<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>publicKey setObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithBool<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span><br />
&nbsp; &nbsp; &nbsp;kSecReturnPersistentRef<span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; OSStatus secStatus <span style="color: #002200;">=</span> SecItemAdd<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>publicKey, <span style="color: #002200;">&amp;</span>persistKey<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>persistKey <span style="color: #002200;">!=</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> CFRelease<span style="color: #002200;">&#40;</span>persistKey<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>secStatus <span style="color: #002200;">!=</span> noErr<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&amp;&amp;</span> <span style="color: #002200;">&#40;</span>secStatus <span style="color: #002200;">!=</span> errSecDuplicateItem<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#91;</span>publicKey release<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span>FALSE<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Now fetch the SecKeyRef version of the key</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">SecKeyRef</span> keyRef <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>publicKey removeObjectForKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecValueData<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>publicKey removeObjectForKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecReturnPersistentRef<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>publicKey setObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithBool<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecReturnRef<br />
&nbsp; &nbsp; <span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>publicKey setObject<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> kSecAttrKeyTypeRSA forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kSecAttrKeyType<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; secStatus <span style="color: #002200;">=</span> SecItemCopyMatching<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>publicKey,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#40;</span>CFTypeRef <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&amp;</span>keyRef<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>publicKey release<span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>keyRef <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span>FALSE<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Add to our pseudo keychain</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#91;</span>keyRefs addObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSValue</span> valueWithBytes<span style="color: #002200;">:&amp;</span>keyRef objCType<span style="color: #002200;">:</span><span style="color: #a61390;">@encode</span><span style="color: #002200;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">SecKeyRef</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span>TRUE<span style="color: #002200;">&#41;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
&nbsp;</div></td></tr></tbody></table></div>
<p>Lastly, to verify a message in the same way we did in PHP earlier, the code might look like this:</p>
<div class="codecolorer-container objc default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br /></div></td><td><div class="objc codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>verifyMessage<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>msg<br />
<span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Search for the two sections: Data and a signature.</span><br />
&nbsp; &nbsp; <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>s_data <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> <span style="color: #a61390;">string</span><span style="color: #002200;">&#93;</span>, <span style="color: #002200;">*</span>s_signature <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> <span style="color: #a61390;">string</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #400080;">NSArray</span> &nbsp;<span style="color: #002200;">*</span>a_key &nbsp;<span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>msg componentsSeparatedByString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;<span style="color: #2400d9;">\n</span>&quot;</span><span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #a61390;">BOOL</span> &nbsp; &nbsp; f_data &nbsp;<span style="color: #002200;">=</span> FALSE, f_signature <span style="color: #002200;">=</span> FALSE;<br />
<br />
&nbsp; &nbsp; <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>a_line <span style="color: #a61390;">in</span> a_key<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>a_line isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;-----BEGIN DATA-----&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f_data &nbsp; &nbsp; &nbsp;<span style="color: #002200;">=</span> TRUE;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f_signature <span style="color: #002200;">=</span> FALSE;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>a_line isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;-----END DATA-----&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f_data &nbsp; &nbsp; &nbsp;<span style="color: #002200;">=</span> FALSE;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f_signature <span style="color: #002200;">=</span> FALSE;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>a_line isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;-----BEGIN SIGNATURE-----&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f_data &nbsp; &nbsp; &nbsp;<span style="color: #002200;">=</span> FALSE;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f_signature <span style="color: #002200;">=</span> TRUE;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>a_line isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;-----END SIGNATURE-----&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f_data &nbsp; &nbsp; &nbsp;<span style="color: #002200;">=</span> FALSE;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f_signature <span style="color: #002200;">=</span> FALSE;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>f_data<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s_data <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>s_data stringByAppendingString<span style="color: #002200;">:</span>a_line<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>f_signature<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s_signature <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>s_signature stringByAppendingString<span style="color: #002200;">:</span>a_line<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>s_data.length <span style="color: #002200;">==</span> <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span> || <span style="color: #002200;">&#40;</span>s_signature.length <span style="color: #002200;">==</span> <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span>FALSE<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// These will be base64 encoded, decode them.</span><br />
&nbsp; &nbsp; <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>d_data <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> dataFromBase64String<span style="color: #002200;">:</span>s_data<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>d_data <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span>FALSE<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>d_signature <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> dataFromBase64String<span style="color: #002200;">:</span>s_signature<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>d_signature <span style="color: #002200;">==</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span>FALSE<span style="color: #002200;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// Make SHA-1 hash of the data</span><br />
&nbsp; &nbsp; uint8_t h_data<span style="color: #002200;">&#91;</span>CC_SHA1_DIGEST_LENGTH<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; CC_SHA1<span style="color: #002200;">&#40;</span>d_data.bytes, d_data.length, h_data<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; d_hash <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSData</span> dataWithBytes<span style="color: #002200;">:</span>h_data length<span style="color: #002200;">:</span>CC_SHA1_DIGEST_LENGTH<span style="color: #002200;">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">// The signature is generated against the binary form of the data, validate</span><br />
&nbsp; &nbsp; <span style="color: #11740a; font-style: italic;">//it.</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">BOOL</span> valid <span style="color: #002200;">=</span> FALSE;<br />
&nbsp; &nbsp; <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSValue</span> <span style="color: #002200;">*</span>refVal <span style="color: #a61390;">in</span> keyRefs<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">SecKeyRef</span> p_key <span style="color: #002200;">=</span> <span style="color: #a61390;">NULL</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#91;</span>refVal getValue<span style="color: #002200;">:&amp;</span>p_key<span style="color: #002200;">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>p_key <span style="color: #002200;">==</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">continue</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; OSStatus secStatus <span style="color: #002200;">=</span> SecKeyRawVerify<span style="color: #002200;">&#40;</span>p_key, kSecPaddingPKCS1SHA1,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;d_hash.bytes, d_hash.length,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;d_signature.bytes,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;d_signature.length<span style="color: #002200;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>secStatus <span style="color: #002200;">==</span> errSecSuccess<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valid <span style="color: #002200;">=</span> TRUE;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #a61390;">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #002200;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #a61390;">return</span><span style="color: #002200;">&#40;</span>valid<span style="color: #002200;">&#41;</span>;<br />
<span style="color: #002200;">&#125;</span><br />
&nbsp;</div></td></tr></tbody></table></div>
<p>So, yes. It&#8217;s involved. But I think it&#8217;s worth it.</p>
<p>Also, for what it is worth, this does work in the Simulator, certainly at least with the current iOS SDK (4.2).</p>

<div class='amazonpress'><h2>Related Reading</h2>
</div>]]></content:encoded>
			<wfw:commentRss>http://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Graphviz Plugin Demo</title>
		<link>http://blog.flirble.org/2010/11/12/graphviz-demo/</link>
		<comments>http://blog.flirble.org/2010/11/12/graphviz-demo/#comments</comments>
		<pubDate>Sat, 13 Nov 2010 01:19:36 +0000</pubDate>
		<dc:creator>Chris Luke</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Graphviz]]></category>
		<category><![CDATA[Wordpress Plugin]]></category>

		<guid isPermaLink="false">http://blog.flirble.org/?p=429</guid>
		<description><![CDATA[Short example of TFO Graphviz plugin use]]></description>
			<content:encoded><![CDATA[<p>I came across the <a href="http://wordpress.org/extend/plugins/eht-graphviz/">EHT Graphviz</a> plugin for WordPress and, whilst useful, it has a very clumsy shortcode parser, is not well documented and only supports a subset of the <a href="http://www.graphviz.org/">Graphviz functionality</a>. Now Graphviz is not exactly a standard for clear documentation but it <em>is</em> a useful tool for flow or organisational diagramming.</p>
<p>So I wrote my own WordPress plugin, which is demonstrated here.<span id="more-429"></span></p>
<div style="float:right">
<a href="http://blog.flirble.org/wp-content/tfo-graphviz/47ddc328f01a34bae68dd42dee1aac14.png" rel="shadowbox[sbpost-429];player=img;"><img src="http://blog.flirble.org/wp-content/tfo-graphviz/47ddc328f01a34bae68dd42dee1aac14.png" class="graphviz" alt="TFO Graphviz Demo" title="TFO Graphviz Demo" usemap="#tfo_graphviz_1" /></a>
<map id="tfo_graphviz_1" name="tfo_graphviz_1">
<area shape="rect" id="node2" href="http://en.wikipedia.org/wiki/Xfs" title="File system" alt="" coords="64,55,157,103"/>
<area shape="rect" id="node3" href="http://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)" title="LVM" alt="" coords="75,151,147,199"/>
<area shape="rect" id="node4" href="http://www.ibm.com/developerworks/linux/library/l-scsi-subsystem/" title="Linux HBA driver" alt="" coords="48,247,173,295"/>
<area shape="rect" id="node13" href="http://tinyurl.com/dellpercraid" title="Physical HBA hardware" alt="" coords="27,751,195,799"/>
<area shape="rect" id="node14" href="http://www.amazon.com/exec/obidos/ASIN/B002B7EIVC/cl-blog-20/" title="Physical disks" alt="" coords="56,847,165,895"/>
<area shape="rect" id="graph2" href="http://www.ubuntu.com/" title="Virtual Machine" alt="" coords="37,16,184,305"/>
<area shape="rect" id="graph3" href="http://www.vmware.com/products/vsphere-hypervisor/" title="Hypervisor" alt="" coords="21,316,200,701"/>
<area shape="rect" id="graph4" href="http://www.dell.com/us/business/p/poweredge-r515/pd" title="Hardware" alt="" coords="16,712,205,905"/>
</map>

</p></div>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[graphviz lang=&quot;dot&quot; output=&quot;png&quot; \<br />
&nbsp;simple=&quot;yes&quot; imap=&quot;yes&quot; href=&quot;self&quot; \<br />
&nbsp;title=&quot;TFO Graphviz Demo&quot;]<br />
<br />
style=filled; bgcolor=&quot;#f1f1f1&quot;;<br />
fontsize=10; labeljust=l;<br />
<br />
node [style=&quot;rounded,filled&quot;, color=lightblue2,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fontsize=10, shape=box];<br />
edge [arrowhead=vee, arrowsize=0.5];<br />
<br />
subgraph cluster_client {<br />
&nbsp; node [label=&quot;File system&quot;, URL=&quot;http://en.wikipedia.org/wiki/Xfs&quot;]; fs;<br />
&nbsp; node [label=&quot;LVM&quot;, URL=&quot;http://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)&quot;]; lvm;<br />
&nbsp; node [label=&quot;Linux HBA driver&quot;, URL=&quot;http://www.ibm.com/developerworks/linux/library/l-scsi-subsystem/&quot;]; clienthba;<br />
&nbsp; fs -&gt; lvm -&gt; clienthba;<br />
&nbsp; bgcolor=lightgrey;<br />
&nbsp; label = &quot;Virtual Machine&quot;;<br />
&nbsp; URL = &quot;http://www.ubuntu.com/&quot;;<br />
}<br />
<br />
subgraph cluster_esxi {<br />
&nbsp; node [label=&quot;Virtual HBA hardware&quot;]; virtualhba;<br />
&nbsp; node [label=&quot;VMDK file&quot;]; vmdk;<br />
&nbsp; node [label=&quot;vmfs&quot;]; vmfs;<br />
&nbsp; node [label=&quot;ESXi HBA driver&quot;]; vmhba;<br />
&nbsp; virtualhba -&gt; vmdk -&gt; vmfs -&gt; vmhba;<br />
&nbsp; bgcolor=white;<br />
&nbsp; label = &quot;Hypervisor&quot;;<br />
&nbsp; URL = &quot;http://www.vmware.com/products/vsphere-hypervisor/&quot;;<br />
}<br />
<br />
subgraph cluster_hardware {<br />
&nbsp; node [label=&quot;Physical HBA hardware&quot;, URL=&quot;http://tinyurl.com/dellpercraid&quot;]; phba;<br />
&nbsp; node [label=&quot;Physical disks&quot;, URL=&quot;http://www.amazon.com/gp/product/B002B7EIVC?ie=UTF8&amp;tag=clblog01-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B002B7EIVC&quot;]; disks;<br />
&nbsp; phba -&gt; disks;<br />
&nbsp; style=filled; bgcolor=lightgrey;<br />
&nbsp; label = &quot;Hardware&quot;;<br />
&nbsp; URL = &quot;http://www.dell.com/us/business/p/poweredge-r515/pd&quot;;<br />
}<br />
<br />
clienthba -&gt; virtualhba;<br />
vmhba -&gt; phba;<br />
label = &quot;I/O stack&quot;;<br />
[/graphviz]</div></td></tr></tbody></table></div>
<p>This example demonstrates image maps and the anchor that encompasses the entire image (this last the WordPress Shadowbox JS plugin picks up). Note how the image maps work hierarchically and provide tool-tips too.</p>
<p>Generated files are kept around instead of being regenerated using a name based on the MD5 hash of the DOT code. If you are logged in and an Admin user then the output is always regenerated, just in case (since the hash doesn&#8217;t incorporate any attributes the shortcode tag, for instance).</p>
<p>I plan to release this plugin next week.</p>

<div class='amazonpress'><h2>Related Reading</h2>
<div class='product'><a href='http://www.amazon.com/Wordpress-Power-Guide-Plugins-ebook/dp/B005J1P8JI?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=546246187-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B005J1P8JI' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/516AXfDskbL._SL160_.jpg' class='amazonpress-product-image' alt='Wordpress Power Guide To Great 100 Plugins' title='Wordpress Power Guide To Great 100 Plugins' /></a>
</div><div class='product'><a href='http://www.amazon.com/WordPress-Domination-Beginner-NINJA-ebook/dp/B007LS0TLE?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B007LS0TLE' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51ZYk13JSpL._SL160_.jpg' class='amazonpress-product-image' alt='WordPress Domination - Beginner to NINJA in 7 Days' title='WordPress Domination - Beginner to NINJA in 7 Days' /></a>
</div><div class='product'><a href='http://www.amazon.com/Data-Visualization-Alexandru-C-Telea/dp/1568813066?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1568813066' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/41uGsPfIbnL._SL160_.jpg' class='amazonpress-product-image' alt='Data Visualization' title='Data Visualization' /></a>
</div><div class='product'><a href='http://www.amazon.com/WordPress-To-Go-Complete-ebook/dp/B0072V4EYS?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B0072V4EYS' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51bmPbi0WoL._SL160_.jpg' class='amazonpress-product-image' alt='WordPress To Go - How To Build A WordPress Website On Your Own Domain, From Scratch, Even If You Are A Complete Beginner' title='WordPress To Go - How To Build A WordPress Website On Your Own Domain, From Scratch, Even If You Are A Complete Beginner' /></a>
</div><div class='product'><a href='http://www.amazon.com/WordPress-Awards-Guide-2012-ebook/dp/B0074FBGF2?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B0074FBGF2' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51avjL5fhkL._SL160_.jpg' class='amazonpress-product-image' alt='WordPress Awards Guide 2012: The Ultimate Guide to The Best Tools &amp; Options For Creating, Optimizing and Maximizing Your WordPress Website or Blog in 2012 (WordPress Awards Guides)' title='WordPress Awards Guide 2012: The Ultimate Guide to The Best Tools &amp; Options For Creating, Optimizing and Maximizing Your WordPress Website or Blog in 2012 (WordPress Awards Guides)' /></a>
</div><div class='product'><a href='http://www.amazon.com/WordPress-3-Plugin-Development-Essentials/dp/184951352X?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=184951352X' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/519RoR6uXwL._SL160_.jpg' class='amazonpress-product-image' alt='WordPress 3 Plugin Development Essentials' title='WordPress 3 Plugin Development Essentials' /></a>
</div></div>]]></content:encoded>
			<wfw:commentRss>http://blog.flirble.org/2010/11/12/graphviz-demo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More thoughts on RAID gone Green</title>
		<link>http://blog.flirble.org/2010/11/10/errata-raid-gone-green/</link>
		<comments>http://blog.flirble.org/2010/11/10/errata-raid-gone-green/#comments</comments>
		<pubDate>Wed, 10 Nov 2010 15:05:12 +0000</pubDate>
		<dc:creator>Chris Luke</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Dell]]></category>
		<category><![CDATA[RAID]]></category>
		<category><![CDATA[RE4-GP]]></category>
		<category><![CDATA[Western Digital]]></category>

		<guid isPermaLink="false">http://blog.flirble.org/?p=424</guid>
		<description><![CDATA[Errata for RAID gone Green I noted in RAID gone Green that my read speed was lower than write speeds and provided some commentary on why that might be. I have a further explanation to add to this &#8211; the stripe size of the RAID array. When I was initially setting up the volumes on [...]]]></description>
			<content:encoded><![CDATA[<h2>Errata for <a href="http://blog.flirble.org/2010/11/07/raid-gone-green/">RAID gone Green</a></h2>
<p>I noted in <a href="http://blog.flirble.org/2010/11/07/raid-gone-green/">RAID gone Green</a> that my read speed was lower than write speeds and provided some commentary on why that might be. I have a further explanation to add to this &#8211; the stripe size of the RAID array.<span id="more-424"></span></p>
<p>When I was initially setting up the volumes on the array I was following advice I found online (on the basis I was experimenting and could change it later without harm) to set the stripe size to be the same or close to the block size used in VMFS. Since I was targeting 2TB VMFS volumes and that needed an 8MB block, I opted for the maximum that the Dell PERC supported &#8211; 1MB. In hindsight, this may not be the optimum setting.</p>
<p>The default read-ahead size for Linux is something like 512 <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-1')" title="click to expand/collapse slider sectors">sectors&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-1"></span> which means 256KB. With a stripe size of four times this a noteworthy result is that most of the time we will be reading from only one device. Consequently the performance we will observe will generally look like that of a single device, all the time &#8211; we won&#8217;t see any benefit from the stripe of the array.</p>
<p>When I tweaked the read-ahead, I started at 4096 sectors and ended up at 16384 and each time the read performance increased almost proportionately. How much does a read-ahead of 16384 equate to? 8MB. With a stripe of 1MB, how many disks does that read-ahead span? Eight. How many disks in my array? Eight. In effect, I was forcing it to read the data from all eight drives in parallel with a single I/O operation. I have not tried it but I suspect the linear gains will end at this value and any further improvements would be marginal at best. Another interesting thought is that if these drives reduce their spin rate aggressively, this also forces all of the drives up to speed a little earlier than it would otherwise and keeps them busy the entire time.</p>
<p>This is not the only factor at work and more tuning may be necessary later. In particular, I doubt I will keep a 1MB stripe size &#8211; I believe it will become a hindrance once my workload on this machine becomes much more random in nature, and I suspect an 8MB read-ahead in this particular virtual-machine will have similar problems. For the sake of testing the raw transfer ability of the drives I think it was a worthwhile setup, however, and it does feel <em>very</em> zippy with interactive use.</p>

<div class='amazonpress'><h2>Related Reading</h2>
<div class='product'><a href='http://www.amazon.com/Bays-End-ebook/dp/B00737JM16?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B00737JM16' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51oy0SsmEFL._SL160_.jpg' class='amazonpress-product-image' alt='Bay&#039;s End' title='Bay&#039;s End' /></a>
</div><div class='product'><a href='http://www.amazon.com/Israels-Lightning-Strike-Raid-Entebbe/dp/1846033977?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1846033977' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/41jXRfPOaoL._SL160_.jpg' class='amazonpress-product-image' alt='Israel&#039;s Lightning Strike - The Raid on Entebbe 1976' title='Israel&#039;s Lightning Strike - The Raid on Entebbe 1976' /></a>
</div><div class='product'><a href='http://www.amazon.com/Bad-Dont-Mean-Wrong-ebook/dp/B005U3AG1A?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B005U3AG1A' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51KmbbQvBoL._SL160_.jpg' class='amazonpress-product-image' alt='Bad Don&#039;t Mean Wrong: A Western Novel' title='Bad Don&#039;t Mean Wrong: A Western Novel' /></a>
</div><div class='product'><a href='http://www.amazon.com/Voyages-Were-Here-Crew-ebook/dp/B004YQC4B4?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B004YQC4B4' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/418YmOIEW3L._SL160_.jpg' class='amazonpress-product-image' alt='Voyages of the We&#039;re Here and Her Crew - Story 4 (The We&#039;re Here Series)' title='Voyages of the We&#039;re Here and Her Crew - Story 4 (The We&#039;re Here Series)' /></a>
</div><div class='product'><a href='http://www.amazon.com/Raid-Sun-Inside-Israels-Campaign/dp/0767914252?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=546246187-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0767914252' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51Tsvzqfj2L._SL160_.jpg' class='amazonpress-product-image' alt='Raid on the Sun: Inside Israel&#039;s Secret Campaign that Denied Saddam the Bomb' title='Raid on the Sun: Inside Israel&#039;s Secret Campaign that Denied Saddam the Bomb' /></a>
</div><div class='product'><a href='http://www.amazon.com/Gothic-Serpent-Black-Hawk-Mogadishu/dp/1849085846?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1849085846' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51o2hbA9iUL._SL160_.jpg' class='amazonpress-product-image' alt='Gothic Serpent - Black Hawk Down Mogadishu 1993 (Raid)' title='Gothic Serpent - Black Hawk Down Mogadishu 1993 (Raid)' /></a>
</div></div><div id="hackadelic-sliderNote-1" class="concealed">Sectors are a legacy concept <a href="http://www.wdc.com/wdproducts/library/WhitePapers/ENG/2579-771430.pdf">that hopefully soon will go away</a>. A sector is 512 bytes in size and is the smallest addressable unit in storage implementations without getting down to byte level.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div>]]></content:encoded>
			<wfw:commentRss>http://blog.flirble.org/2010/11/10/errata-raid-gone-green/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows command prompt still in the 80&#8242;s</title>
		<link>http://blog.flirble.org/2010/11/10/windows-command-prompt-80s/</link>
		<comments>http://blog.flirble.org/2010/11/10/windows-command-prompt-80s/#comments</comments>
		<pubDate>Wed, 10 Nov 2010 05:10:19 +0000</pubDate>
		<dc:creator>Chris Luke</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[MS-DOS]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.flirble.org/?p=412</guid>
		<description><![CDATA[I sometimes wonder if cmd.exe will ever get the -h treatment a lot of unixy tools have received&#8230; dir is definitely still living in the MS-DOS era. For example: 12345678910111213141516T:\&#62;dir v: &#160;Volume in drive V is video &#160;Volume Serial Number is 0254-04EC &#160;Directory of V:\ 26/07/2010 &#160;09:22 &#160; &#160;&#60;DIR&#62; &#160; &#160; &#160; &#160; &#160;. 04/06/2010 [...]]]></description>
			<content:encoded><![CDATA[<p>I sometimes wonder if <code class="codecolorer text default"><span class="text">cmd.exe</span></code> will ever get the <em>-h</em> treatment a lot of unixy tools have received&#8230; <code class="codecolorer text default"><span class="text">dir</span></code> is definitely still living in the MS-DOS era. For example:<span id="more-412"></span></p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">T:\&gt;dir v:<br />
&nbsp;Volume in drive V is video<br />
&nbsp;Volume Serial Number is 0254-04EC<br />
<br />
&nbsp;Directory of V:\<br />
<br />
26/07/2010 &nbsp;09:22 &nbsp; &nbsp;&lt;DIR&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.<br />
04/06/2010 &nbsp;09:56 &nbsp; &nbsp;&lt;DIR&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;..<br />
26/02/2010 &nbsp;10:41 &nbsp; &nbsp;&lt;DIR&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DVD<br />
04/10/2010 &nbsp;13:12 &nbsp; &nbsp;&lt;DIR&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TV<br />
22/03/2008 &nbsp;13:41 &nbsp; &nbsp;&lt;DIR&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TiVo<br />
26/02/2010 &nbsp;10:41 &nbsp; &nbsp;&lt;DIR&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;inbound<br />
21/05/2010 &nbsp;09:57 &nbsp; &nbsp;&lt;DIR&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;redux<br />
12/06/2010 &nbsp;19:40 &nbsp; &nbsp; 1,900,601,954 Dance Recital.mp4<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 File(s) &nbsp;1,900,601,954 bytes<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;8 Dir(s) &nbsp;4,612,702,208,000 bytes free</div></td></tr></tbody></table></div>
<p>For those that don&#8217;t get it, that&#8217;s 4.6TiB available. Why not say &#8220;4.6TiB&#8221;&#8230; or even &#8220;4.2TB&#8221; or at least provide a switch to do so? Most Unixish tools have <em>-h</em> and <em>-H</em> options to do just this. The same file system, but on the file server:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">chrisy@baud:~$ df -H /data<br />
Filesystem &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Size &nbsp; Used &nbsp;Avail Use% Mounted on<br />
/dev/mapper/vmraw-data<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;8.0T &nbsp; 3.4T &nbsp; 4.6T &nbsp;42% /data<br />
<br />
chrisy@baud:~$ df -h /data<br />
Filesystem &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Size &nbsp;Used Avail Use% Mounted on<br />
/dev/mapper/vmraw-data<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7.3T &nbsp;3.1T &nbsp;4.2T &nbsp;42% /data</div></td></tr></tbody></table></div>
<p>The <a href="http://en.wikipedia.org/wiki/TiB">difference between the two</a> being whether it uses 1000 or 1024 as the divisor.</p>

<div class='amazonpress'><h2>Related Reading</h2>
<div class='product'><a href='http://www.amazon.com/Elastic-Compute-Microsoft-Windows-ebook/dp/B007Q4LJZS?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B007Q4LJZS' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/417ubV9VU5L._SL160_.jpg' class='amazonpress-product-image' alt='Amazon Elastic Compute Cloud (EC2) Microsoft Windows Guide' title='Amazon Elastic Compute Cloud (EC2) Microsoft Windows Guide' /></a>
</div><div class='product'><a href='http://www.amazon.com/INTRODUCES-HALF-TERABYTE-SERIAL-DESKTOP-DRIVES/dp/B000EMI8VW?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B000EMI8VW' target='_blank' rel='nofollow'></a>
</div><div class='product'><a href='http://www.amazon.com/ORACLE-WORLD-RECORD-TERABYTE-BENCHMARK/dp/B000B7O5NA?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B000B7O5NA' target='_blank' rel='nofollow'></a>
</div><div class='product'><a href='http://www.amazon.com/Windows-Command-Beginners-Computer-ebook/dp/B005NRXU0W?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B005NRXU0W' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51nlpGuRNOL._SL160_.jpg' class='amazonpress-product-image' alt='The Windows Command Line Beginner&#039;s Guide (Computer Beginner&#039;s Guides)' title='The Windows Command Line Beginner&#039;s Guide (Computer Beginner&#039;s Guides)' /></a>
</div><div class='product'><a href='http://www.amazon.com/Inside-Windows-Debugging-Practical-Strategies/dp/0735662789?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0735662789' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/41V0lDGERxL._SL160_.jpg' class='amazonpress-product-image' alt='Inside Windows Debugging: A Practical Guide to Debugging and Tracing Strategies in Windows' title='Inside Windows Debugging: A Practical Guide to Debugging and Tracing Strategies in Windows' /></a>
</div><div class='product'><a href='http://www.amazon.com/Windows®-Step-Microsoft/dp/0735626677?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=546246187-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0735626677' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51zZ1dKq-ML._SL160_.jpg' class='amazonpress-product-image' alt='Windows&Acirc;&reg; 7 Step by Step (Step by Step (Microsoft))' title='Windows&Acirc;&reg; 7 Step by Step (Step by Step (Microsoft))' /></a>
</div></div>]]></content:encoded>
			<wfw:commentRss>http://blog.flirble.org/2010/11/10/windows-command-prompt-80s/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to map a raw LUN when ESXi doesn&#8217;t want you to&#8230;</title>
		<link>http://blog.flirble.org/2010/11/09/how-to-map-raw-lun-esxi/</link>
		<comments>http://blog.flirble.org/2010/11/09/how-to-map-raw-lun-esxi/#comments</comments>
		<pubDate>Tue, 09 Nov 2010 19:30:14 +0000</pubDate>
		<dc:creator>Chris Luke</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Dell]]></category>
		<category><![CDATA[ESXi]]></category>
		<category><![CDATA[hard disk]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[LVM]]></category>
		<category><![CDATA[RAID]]></category>
		<category><![CDATA[storage]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[VMM386]]></category>
		<category><![CDATA[VMware]]></category>

		<guid isPermaLink="false">http://blog.flirble.org/?p=288</guid>
		<description><![CDATA[VMware ESXi is a very popular hypervisor and the underpinning of the vSphere virtualisation suite which caters for enthusiasts up to large scale datacenter operations for enterprise and service providers. VMware offers a variety of software to achieve virtualisation, Workstation, Server, ESX and ESXi being the main flavors with very different focusses: Desktop use, existing [...]]]></description>
			<content:encoded><![CDATA[
<p>VMware ESXi is a very popular hypervisor and the underpinning of the vSphere virtualisation suite which caters for enthusiasts up to large scale datacenter operations for enterprise and service providers. VMware offers a <a href="http://blog.flirble.org/wp-content/uploads/2010/11/vmware-logo.jpg" rel="shadowbox[sbpost-288];player=img;"><img src="http://blog.flirble.org/wp-content/uploads/2010/11/vmware-logo-300x114.jpg" alt="VMware logo" title="VMware logo" width="300" height="114" class="alignright size-medium wp-image-383" /></a>variety of software to achieve virtualisation, Workstation, Server, ESX and ESXi being the main flavors with very different focusses: Desktop use, existing server, with a Linux console and without. ESXi is the variant with the smallest footprint and is ideal if you don&#8217;t need to implement a bunch of monitoring or other scripting on the host, are going to do all that management stuff elsewhere, or just don&#8217;t need to do any. As with the trusty old VMware Server, ESX and ESXi are available with a free license that gives you lots of room to play with but removes some of the more advanced features (like being able to move VM&#8217;s between hosts whilst running).<span id="more-288"></span></p>
<h2>Playing with your LUNs</h2>
<p>I&#8217;ve been a long-time VMware server user, since before ESX existed. In reality, I&#8217;ve used virtualisation since before the current market for it existed &#8211; my <a href="http://www.flirble.org/chrisy/vmm386/">undergraduate university software project</a> at UKC in the early 90&#8242;s was as part of a three-guy team to build a virtual machine monitor (VMM) &#8211; what is now called a hypervisor. When VMware got started they even emailed me a couple of times to talk about it. Most recently I&#8217;ve been running the 64bit variant of VMware Server 2 on my previous local NAS/VM host box which runs Ubuntu. This machine had roughly 6TB of space to play with and VMware could use as much or as little as I wanted.</p>
<p>I recently upgraded hardware and decided to give ESXi 4.1 a go, friends having reported positive things and finding the concept appealing (since it mirrored exactly what I did almost 20 years ago.) One key quirk is a limitation on file system size. In general, VMware provides virtual storage space by mapping the space occupied by a file in the host machine via software to the logical storage provided by a virtual <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-2')" title="click to expand/collapse slider host bus adapter (HBA).">host bus adapter (HBA).&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-2"></span> On ESX and ESXi the common approach is for VMware to format storage <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-3')" title="click to expand/collapse slider volumes">volumes&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-3"></span> using their own file system format called VMFS, optimised for large blocks. For most file systems the maximum size of a single file system is a function of the size of its blocks &#8211; the smallest allocatable unit of space &#8211; since it addresses blocks with a number and numbers on computers have a finite range. Sometimes, file systems also impose limits on the block size and for VMFS this is 8MB, which translates into a 2TB file system limit. ESX and ESXi also support presenting a raw device, via its <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-4')" title="click to expand/collapse slider LUN">LUN&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-4"></span>, to virtual machines &#8211; but only under certain circumstances, as discussed below.</p>
<p>Moreover, if you present a volume to ESXi (and I presume ESX) that is larger than 2TB in size it gets very confused and, in my case, refused to create a file system larger than ~900MB. This was less than optimal &#8211; I had 12TB of space and ESXi was being dumb with it. But, there are workarounds.</p>
<h2>Workaround 1: Concatenation of VMFS volumes</h2>
<p>First, and simplest, since ESXi has a 2TB limit, is to only present volumes to it that are 2TB or less. Depending on the underlying infrastructure there are a variety of ways to do this &#8211; with partitioning or with logical volumes on a hardware <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-5')" title="click to expand/collapse slider RAID controller">RAID controller&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-5"></span> or <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-6')" title="click to expand/collapse slider SAN.">SAN.&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-6"></span> VMware can then install VMFS onto these volumes and you can present them to the VM.</p>
<p>Most operating systems offer tools to provide software-RAID. This is usually avoided for the higher RAID levels because of the computational requirements but if your underlying storage infrastructure is already providing the fault tolerance there will be only a minimal impact if you use <a href="http://en.wikipedia.org/wiki/Standard_RAID_levels#RAID_0">RAID-0</a>, or simple block-level striping. If your hardware already stripes you will probably want to concatenate rather than stripe but the concept is similar. For FreeBSD you can use <a href="http://www.freebsd.org/doc/handbook/disks-virtual.html">memory disk (md)</a> to do this, for Linux you can also use md or, alternatively, the <a href="http://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)">Logical Volume Manager (LVM)</a> will oblige and with Windows one can use <a href="http://msdn.microsoft.com/en-us/library/aa363785(VS.85).aspx#dynamic_disks">dynamic disks</a> and extend our NTFS volumes across them.</p>
<p>In my case, using Ubuntu Server, I opted for LVM and setting up a simple concatenated volume is really very easy. I created four 1.8TB volumes on the RAID controller, created file stores in ESXi, created the virtual disks on those file stores (VMDK) and mapped them to SCSI controller targets in the virtual machine configuration. Linux then sees these four volumes as ordinary SCSI devices, <em>sdb</em>, <em>sbc</em>, <em>sdd</em> and <em>sde</em>. Using the whole of these virtual devices to create one large <em>volume group</em> and then carving it up into two <em>logical volumes</em> for <code class="codecolorer text default"><span class="text">/home</span></code> and <code class="codecolorer text default"><span class="text">/data</span></code> is quite easy to do.</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># Install LVM if you don't have it already</span><br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> lvm2<br />
<br />
<span style="color: #666666; font-style: italic;"># Older Ubuntu needs this too:</span><br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> modprobe dm-mod<br />
<br />
<span style="color: #666666; font-style: italic;"># Label the virtual devices as managed by LVM</span><br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> pvcreate <span style="color: #660033;">-v</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdb <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdc <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdd <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sde<br />
<br />
<span style="color: #666666; font-style: italic;"># Create a volume group with those devices</span><br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> vgcreate <span style="color: #660033;">-v</span> vmraw <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdb <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdc <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdd <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sde<br />
<br />
<span style="color: #666666; font-style: italic;"># Create a /home volume</span><br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> lvcreate <span style="color: #660033;">-n</span> home <span style="color: #660033;">-L</span> 64G vmraw<br />
<br />
<span style="color: #666666; font-style: italic;"># Use the rest of the space for /data</span><br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> lvcreate <span style="color: #660033;">-n</span> data <span style="color: #660033;">-l</span> <span style="color: #000000;">100</span><span style="color: #000000; font-weight: bold;">%</span>FREE vmraw<br />
<br />
<span style="color: #666666; font-style: italic;"># Initialise the file systems</span><br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> mkfs.ext4 <span style="color: #660033;">-j</span> <span style="color: #660033;">-L</span> home <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>vmraw<span style="color: #000000; font-weight: bold;">/</span>home<br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> mkfs.xfs <span style="color: #660033;">-L</span> data <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>vmraw<span style="color: #000000; font-weight: bold;">/</span>data</div></td></tr></tbody></table></div>
<p>And then add these lines to <code class="codecolorer text default"><span class="text">fstab</span></code>:</p>
<div class="codecolorer-container text default codecolorer-title" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;">Append to /etc/fstab</div><div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">LABEL=home &nbsp; &nbsp;/home &nbsp; &nbsp;ext4 &nbsp; &nbsp;defaults,acl &nbsp;0 2<br />
LABEL=data &nbsp; &nbsp;/data &nbsp; &nbsp;xfs &nbsp; &nbsp; defaults &nbsp; &nbsp; &nbsp;0 2</div></td></tr></tbody></table></div>
<p>Assuming you have <code class="codecolorer text default"><span class="text">/home</span></code> and <code class="codecolorer text default"><span class="text">/data</span></code> mount points already created, you can then mount them. Here&#8217;s some <code class="codecolorer text default"><span class="text">df</span></code> output after I loaded the filesystems with some data:</p>
<div class="codecolorer-container text default codecolorer-title" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;">df -h</div><div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Filesystem &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Size &nbsp;Used Avail Use% Mounted on<br />
/dev/sda1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;48G &nbsp;3.7G &nbsp; 42G &nbsp; 9% /<br />
none &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2.0G &nbsp;188K &nbsp;2.0G &nbsp; 1% /dev<br />
none &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2.0G &nbsp; &nbsp; 0 &nbsp;2.0G &nbsp; 0% /dev/shm<br />
none &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2.0G &nbsp;1.8M &nbsp;2.0G &nbsp; 1% /var/run<br />
none &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2.0G &nbsp;8.0K &nbsp;2.0G &nbsp; 1% /var/lock<br />
none &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 48G &nbsp;3.7G &nbsp; 42G &nbsp; 9% /var/lib/ureadahead/debugfs<br />
/dev/mapper/vmraw-home<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;63G &nbsp; 14G &nbsp; 47G &nbsp;23% /home<br />
/dev/mapper/vmraw-data<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7.3T &nbsp;3.1T &nbsp;4.2T &nbsp;42% /data</div></td></tr></tbody></table></div>
<p>Job done.</p>
<h2>Workaround 2: Concatenation of directly mapped LUNs</h2>
<p>Wait a moment, doesn&#8217;t that all seem horribly inefficient? </p>
<p><center>File system<br />
↓<br />
LVM<br />
↓<br />
Linux HBA driver<br />
↓<br />
Virtual HBA hardware<br />
↓<br />
VMDK file<br />
↓<br />
VMFS<br />
↓<br />
ESXi HBA driver<br />
↓<br />
Physical HBA hardware<br />
↓<br />
Disks<br />
</center></p>
<p>That&#8217;s a <em>lot</em> of layers that all have to do significant amounts of work in an I/O stack &#8211; in particular in having to map block numbers from one view of the storage to another. Worse, most of it runs on your CPU, using up cycles that could be used doing useful work.</p>
<p>We can remove some of this by mapping the volumes from the RAID controller directly into the virtual HBA provided to the client. VM and ESXi provides a virtual hard disk type entitled &#8220;<em>Raw Device Mappings</em>&#8221; (RDM) which does exactly this. However they <a href="http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&#038;cmd=displayKC&#038;externalId=1017704">only make the feature available to remotely-attached storage</a> (SAN or an HBA with storage attached to <em>external</em> connectors).</p>
<p>I&#8217;ve not seen any definitive reason why they imposed this limitation, there&#8217;s certainly no technical reason to. My suspicion is to prevent a good number of their customers from shooting themselves in the proverbial foot. By mapping storage in a virtual machine to a physical unit of storage you form a very strong anchor between the machine and that storage.  A key part of vSphere, in the upper-echelons of the licensing map, is to be able to migrate your virtual installations between hosts at will. VMDK files nicely abstract this storage into a quantifiable object that VMware has complete control over. Volumes on physical hardware are beyond its control. So, to reduce support calls, I believe they disabled the feature for local storage.</p>
<p>However, it&#8217;s only disabled in-so-far-as being able to configure it with the graphical tools is concerned. Using remote command line tools or the tech-support CLI you can use the right magic to create the raw device mapping you need. There are two commands key to this: <code class="codecolorer text default"><span class="text">esxcfg-scsidevs</span></code> to list the path that VMware uses to reference all of the volumes presented to it by the hardware and <code class="codecolorer text default"><span class="text">vmkfstools</span></code> to create the mapping. On my system I renamed the volumes under the hosts <em>Configuration → Storage Adapters</em> menu in the vSphere client to make them easier to spot, and on this page you can see the LUN values for each volume. <code class="codecolorer text default"><span class="text">esxcfg-scsidevs</span></code> told me this:</p>
<div class="codecolorer-container text default codecolorer-title" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;">/sbin/esxcfg-scsidevs -c</div><div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Device UID &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Device Type &nbsp; &nbsp; &nbsp;Console Device &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Size &nbsp; &nbsp; &nbsp;Multipath PluginDisplay Name &nbsp; &nbsp; &nbsp; &nbsp;<br />
mpx.vmhba33:C0:T0:L0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CD-ROM &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /vmfs/devices/cdrom/mpx.vmhba33:C0:T0:L0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0MB &nbsp; &nbsp; &nbsp; NMP &nbsp; &nbsp; Local USB CD-ROM (mpx.vmhba33:C0:T0:L0)<br />
mpx.vmhba33:C0:T0:L1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Direct-Access &nbsp; &nbsp;/vmfs/devices/disks/mpx.vmhba33:C0:T0:L1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0MB &nbsp; &nbsp; &nbsp; NMP &nbsp; &nbsp; Local USB Direct-Access (mpx.vmhba33:C0:T0:L1)<br />
naa.6842b2b0229e1800145d5234061dc8ee &nbsp;Direct-Access &nbsp; &nbsp;/vmfs/devices/disks/naa.6842b2b0229e1800145d5234061dc8ee &nbsp;139392MB &nbsp;NMP &nbsp; &nbsp; Bell Raid1 Boot &nbsp; &nbsp; <br />
naa.6842b2b0229e1800145d523406237f53 &nbsp;Direct-Access &nbsp; &nbsp;/vmfs/devices/disks/naa.6842b2b0229e1800145d523406237f53 &nbsp;304128MB &nbsp;NMP &nbsp; &nbsp; Bell Raid0 Scratch &nbsp;<br />
naa.6842b2b0229e1800146855550c728258 &nbsp;Direct-Access &nbsp; &nbsp;/vmfs/devices/disks/naa.6842b2b0229e1800146855550c728258 &nbsp;1906674MB NMP &nbsp; &nbsp; Bell Raid6 Data0 &nbsp; &nbsp;<br />
naa.6842b2b0229e18001468573b295e172f &nbsp;Direct-Access &nbsp; &nbsp;/vmfs/devices/disks/naa.6842b2b0229e18001468573b295e172f &nbsp;1906674MB NMP &nbsp; &nbsp; Bell Raid6 Data1 &nbsp; &nbsp;<br />
naa.6842b2b0229e1800146857b730cd92a5 &nbsp;Direct-Access &nbsp; &nbsp;/vmfs/devices/disks/naa.6842b2b0229e1800146857b730cd92a5 &nbsp;1906674MB NMP &nbsp; &nbsp; Bell Raid6 Data2 &nbsp; &nbsp;<br />
naa.6842b2b0229e1800146857e0333bc891 &nbsp;Direct-Access &nbsp; &nbsp;/vmfs/devices/disks/naa.6842b2b0229e1800146857e0333bc891 &nbsp;1906674MB NMP &nbsp; &nbsp; Bell Raid6 Data3 &nbsp; &nbsp;<br />
naa.6842b2b0229e1800146858543a1fc2f1 &nbsp;Direct-Access &nbsp; &nbsp;/vmfs/devices/disks/naa.6842b2b0229e1800146858543a1fc2f1 &nbsp;1906686MB NMP &nbsp; &nbsp; Bell Raid6 Data4 &nbsp; &nbsp;<br />
naa.6842b2b0229e18001468587e3c9c498e &nbsp;Direct-Access &nbsp; &nbsp;/vmfs/devices/disks/naa.6842b2b0229e18001468587e3c9c498e &nbsp;1909818MB NMP &nbsp; &nbsp; Bell Raid6 Data5 &nbsp; &nbsp;<br />
t10.DP______BACKPLANE000000 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Enclosure Svc Dev/vmfs/devices/genscsi/t10.DP______BACKPLANE000000 &nbsp; &nbsp; &nbsp; &nbsp; 0MB &nbsp; &nbsp; &nbsp; NMP &nbsp; &nbsp; Dell PERC H700</div></td></tr></tbody></table></div>
<p>The four devices I am interested in are &#8220;<em>Bell Raid6 Data2</em>&#8221; to &#8220;<em>Data5</em>&#8220;. Take note of the paths listed under &#8220;<em>Console Device</em>&#8220;.</p>
<p>Next you need to find where the virtual machine configuration lives. Each volume that has been formatted with VMFS is mounted with a path that uses the same ID as its underlying volume &#8211; you can see them by typing <code class="codecolorer text default"><span class="text">mount</span></code>. In that list above, you can see the volume I labelled &#8220;<em>Bell Raid1 Boot</em>&#8220;. Well, I also labelled the VMFS file system with the same name, and ESXi conveniently installs a link from that name to where it is mounted, so I can <code class="codecolorer text default"><span class="text">cd &quot;/vmfs/volumes/Bell Raid1 Boot/&quot;</span></code> and end up in the root of that file system. My VM configuration is in a directory off of there and I change directory into that.</p>
<p>The next bit of magic is using <code class="codecolorer text default"><span class="text">vmkfstools</span></code>. In previous releases of VMware you had to create a raw mapping by <a href="http://itknowledgeexchange.techtarget.com/virtualization-pro/vmware-esx-storage-how-to-get-local-storage-to-act-as-a-raw-disk-for-vms/">cloning another virtual disk and importing it into the LUN</a>. ESXi 4.1 lets you skip that fuss and do just what you want, thus:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">/</span>sbin<span style="color: #000000; font-weight: bold;">/</span>vmkfstools <span style="color: #660033;">-r</span> <span style="color: #000000; font-weight: bold;">/</span>vmfs<span style="color: #000000; font-weight: bold;">/</span>devices<span style="color: #000000; font-weight: bold;">/</span>disks<span style="color: #000000; font-weight: bold;">/</span>naa.6842b2b0229e1800146857b730cd92a5 <span style="color: #660033;">-a</span> lsilogic disk_1_2.vmdk<br />
<span style="color: #000000; font-weight: bold;">/</span>sbin<span style="color: #000000; font-weight: bold;">/</span>vmkfstools <span style="color: #660033;">-r</span> <span style="color: #000000; font-weight: bold;">/</span>vmfs<span style="color: #000000; font-weight: bold;">/</span>devices<span style="color: #000000; font-weight: bold;">/</span>disks<span style="color: #000000; font-weight: bold;">/</span>naa.6842b2b0229e1800146857e0333bc891 <span style="color: #660033;">-a</span> lsilogic disk_1_3.vmdk<br />
<span style="color: #000000; font-weight: bold;">/</span>sbin<span style="color: #000000; font-weight: bold;">/</span>vmkfstools <span style="color: #660033;">-r</span> <span style="color: #000000; font-weight: bold;">/</span>vmfs<span style="color: #000000; font-weight: bold;">/</span>devices<span style="color: #000000; font-weight: bold;">/</span>disks<span style="color: #000000; font-weight: bold;">/</span>naa.6842b2b0229e1800146858543a1fc2f1 <span style="color: #660033;">-a</span> lsilogic disk_1_4.vmdk<br />
<span style="color: #000000; font-weight: bold;">/</span>sbin<span style="color: #000000; font-weight: bold;">/</span>vmkfstools <span style="color: #660033;">-r</span> <span style="color: #000000; font-weight: bold;">/</span>vmfs<span style="color: #000000; font-weight: bold;">/</span>devices<span style="color: #000000; font-weight: bold;">/</span>disks<span style="color: #000000; font-weight: bold;">/</span>naa.6842b2b0229e18001468587e3c9c498e <span style="color: #660033;">-a</span> lsilogic disk_1_5.vmdk</div></td></tr></tbody></table></div>
<p>This creates four virtual disks that map directly to the logical units presented to us by the HBA.</p>
<p>These VMDK&#8217;s can be added to your virtual machine using the vSphere client in the normal way &#8211; just tell it that they are existing virtual disks and it works out the rest. It will list them as &#8220;<em>Mapped Raw LUN</em>&#8221; in the VM configuration. Just make sure you attach them to a SCSI controller of the same type above. <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-7')" title="click to expand/collapse slider Note: You used <em>lsilogic</em>, any reason why?">Note: You used <em>lsilogic</em>, any reason why?&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-7"></span></p>
<p>After that, I use LVM again, in exactly the same way, to concatenate the volumes together in the VM client, and as a result a good amount of processing and block number mapping has been eliminated.</p>
<h2>Workaround 3: Can I directly map a big LUN?</h2>
<p>The next logical step in this train of thought is&#8230; why use LVM at all? If we can map LUNs on the host to LUNs in the VM, why not create one big volume on the hardware and pass this right through?</p>
<p>I do not have an answer other than &#8220;I believe it should work, but I&#8217;ve not tested it and anytime I search online I see lots of advice against it.&#8221;</p>
<p>Right now my suspicion is that VMware imposed a 2TB limitation for a reason and I suspect that either their physical or their virtual hardware drivers don&#8217;t work beyond 2TB. If that is so, then any mapped LUN will also fail because it will not be able to pass through commands with big enough a block number. Or perhaps, if the drivers could work, some of the ancillary features, like snapshots, can&#8217;t cope with it.</p>
<p>I may test it at some point, but I suspect the performance gains will be marginal and <a href="http://blog.flirble.org/2010/11/07/raid-gone-green/#performance">this setup performs really very well</a>, currently.</p>
<h2>Issues with using mapped LUNs</h2>
<p>The obvious issue is that if the use of mapped LUNs on local storage is not supported then anyone doing it should not cry if/when it breaks. One very obvious thing to note is that in all of the vSphere configuration and summary screens none of the mapped LUNs appear as being in use making it potentially easy to make mistakes and lose data.</p>
<p>Also worth thinking about is that VMware is not going to be able to do anything sensible with snapshots &#8211; experiment with it, but don&#8217;t rely on it.</p>

<div class='amazonpress'><h2>Related Reading</h2>
<div class='product'><a href='http://www.amazon.com/VMware-vSphere-4-1-Technical-deepdive/dp/1456301446?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1456301446' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/41lguq0GcrL._SL160_.jpg' class='amazonpress-product-image' alt='VMware vSphere 4.1 HA and DRS Technical deepdive' title='VMware vSphere 4.1 HA and DRS Technical deepdive' /></a>
</div><div class='product'><a href='http://www.amazon.com/Fireproof-A-Maggie-ODell-Novel/dp/0385535511?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0385535511' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/5134RtYvc7L._SL160_.jpg' class='amazonpress-product-image' alt='Fireproof: A Maggie O&#039;Dell Novel' title='Fireproof: A Maggie O&#039;Dell Novel' /></a>
</div><div class='product'><a href='http://www.amazon.com/Linux-All-One-For-Dummies/dp/0470770198?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0470770198' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/5178Cta7tQL._SL160_.jpg' class='amazonpress-product-image' alt='Linux All-in-One For Dummies' title='Linux All-in-One For Dummies' /></a>
</div><div class='product'><a href='http://www.amazon.com/Working-Ubuntu-Command-Line-Prompt-ebook/dp/B004RYVI0Q?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=546246187-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B004RYVI0Q' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51EfBhi5x9L._SL160_.jpg' class='amazonpress-product-image' alt='Working at the Ubuntu Command-Line Prompt (Linux Nitty Gritty)' title='Working at the Ubuntu Command-Line Prompt (Linux Nitty Gritty)' /></a>
</div><div class='product'><a href='http://www.amazon.com/Linux-System-Administration-Handbook-Edition/dp/0131480057?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0131480057' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/61w%2B%2BNmnQIL._SL160_.jpg' class='amazonpress-product-image' alt='UNIX and Linux System Administration Handbook (4th Edition)' title='UNIX and Linux System Administration Handbook (4th Edition)' /></a>
</div><div class='product'><a href='http://www.amazon.com/Mastering-VMware-vSphere-Computer-Tech/dp/0470481382?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0470481382' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51P7qPvYJBL._SL160_.jpg' class='amazonpress-product-image' alt='Mastering VMware vSphere 4 (Computer/Tech)' title='Mastering VMware vSphere 4 (Computer/Tech)' /></a>
</div></div><div id="hackadelic-sliderNote-2" class="concealed">For this discussion a <a href="http://en.wikipedia.org/wiki/Host_adapter">host bus adapter (HBA)</a> is the hardware that provides access to storage devices, be that the SATA controller on the motherboard, a RAID controller, a Fibre Channel interface or their virtual equivalents provided in software by a hypervisor.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div><div id="hackadelic-sliderNote-3" class="concealed">There is much terminology when it comes to storage and it&#8217;s complicated by having multiple layers between the disk and whatever ultimately uses it. Volume is a term that most often refers to an administratively defined portion of some storage medium. Usually called a logical volume it&#8217;s function is to present what looks like a linear and contiguous amount of storage space and hide however it is constructed (which could be a single whole disk, partitions on a disk, a RAID system, a concatenation of various storage areas from various places and so on) from the system.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div><div id="hackadelic-sliderNote-4" class="concealed">Logical Unit Number which is a term used in storage to refer to the <em>address</em> of a storage volume on a given HBA. It&#8217;s use has however been generalised to also refer to the volume itself, wherever it may reside and it&#8217;s presentation to the system. Some people use LUN and volume interchangeable, though they refer to different, but related, underlying concepts.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div><div id="hackadelic-sliderNote-5" class="concealed"><a href="http://en.wikipedia.org/wiki/RAID">RAID</a> is a mature set of storage technologies that provide varying levels of performance and fault-tolerance across multiple physical storage devices. A RAID controller is a device (which can be in dedicated hardware or in a general purpose software driver) that presents logical volumes to a system and hides the complexity of providing the performance or fault-tolerance. Often hardware controllers contain local cache memory that can provide significant mitigation of the performance penalties some of the fault-tolerant schemes introduce.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div><div id="hackadelic-sliderNote-6" class="concealed">Storage area network (SAN) is broadly speaking where the RAID controller sits close to the physical storage and the connection between it and the users of that storage is extended over a dedicated network, usually Fibre Channel or iSCSI. Often SANs provide advanced features such as sharing of a volume across multiple client devices simultaneously or greater degrees of fault tolerance.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div><div id="hackadelic-sliderNote-7" class="concealed">The LSI Logic virtual HBA can be virtualised into 64bit guests. BusLogic cannot. I&#8217;ve not tested the Paravirtualision controller.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div>]]></content:encoded>
			<wfw:commentRss>http://blog.flirble.org/2010/11/09/how-to-map-raw-lun-esxi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RAID gone Green</title>
		<link>http://blog.flirble.org/2010/11/07/raid-gone-green/</link>
		<comments>http://blog.flirble.org/2010/11/07/raid-gone-green/#comments</comments>
		<pubDate>Mon, 08 Nov 2010 03:00:47 +0000</pubDate>
		<dc:creator>Chris Luke</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Dell]]></category>
		<category><![CDATA[ESXi]]></category>
		<category><![CDATA[green]]></category>
		<category><![CDATA[hard drive]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[low power]]></category>
		<category><![CDATA[PowerEdge R515]]></category>
		<category><![CDATA[RAID]]></category>
		<category><![CDATA[RE4-GP]]></category>
		<category><![CDATA[VMware]]></category>
		<category><![CDATA[Western Digital]]></category>

		<guid isPermaLink="false">http://blog.flirble.org/?p=294</guid>
		<description><![CDATA[Western Digital released their lower-power &#8220;Enterprise&#8221; RAID Edition (The RE-GP series) Serial ATA (SATA) drives some time ago, and the 1.5 and 2TB versions (RE4-GP series) last year. They were found to have an issue with certain RAID controllers and received much bad press as a result. It&#8217;s now more than a year on and [...]]]></description>
			<content:encoded><![CDATA[<p><div id="attachment_305" class="wp-caption alignright" style="width: 160px"><a href="http://blog.flirble.org/wp-content/uploads/2010/11/wdfEnterprise_RE4_GP.jpg" rel="shadowbox[sbpost-294];player=img;"><img src="http://blog.flirble.org/wp-content/uploads/2010/11/wdfEnterprise_RE4_GP-150x150.jpg" alt="Western Digital RE4-GP Hard Drive" title="Western Digital RE4-GP Hard Drive" width="150" height="150" class="size-thumbnail wp-image-305" /></a><p class="wp-caption-text">Western Digital RE4-GP</p></div> <br/></p>
<p>Western Digital released their lower-power &#8220;Enterprise&#8221; RAID Edition (The RE-GP series) Serial ATA (SATA) drives some time ago, and the 1.5 and 2TB versions (RE4-GP series) last year. They were found to have an issue with certain RAID controllers and received much bad press as a result.</p>
<p>It&#8217;s now more than a year on and they have newer firmware, which has been generally well received. I also was toying with reducing the energy footprint of my home-business mass storage needs (not to mention to improve its reliability and performance) so I decided to give them a whirl in my newest server build<span id="more-294"></span> which has eight <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-8')" title="click to expand/collapse slider Western Digital 2TB RE4-GP's">Western Digital 2TB RE4-GP's&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-8"></span> in RAID-6.</p>
<h2>What makes it green?</h2>
<p>Western Digital (WDC) has had a &#8220;Green&#8221; variant of their desktop drive for some time and the key difference is that it nominally runs at a lower rotational speed (5400RPM versus 7200RPM), though in reality it varies the spin rate with load. The RE version follows ostensibly the same idea but incorporates the other RAID-focussed features, such as <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-9')" title="click to expand/collapse slider time-limited error recovery">time-limited error recovery&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-9"></span> and a <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-10')" title="click to expand/collapse slider tolerance for vibration.">tolerance for vibration.&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-10"></span> The area that gives one pause before choosing a drive with a lower rotational speed is it may have a direct impact on the drives data transfer performance. The drive heads can only pass over the physical locations where data is stored as fast as the surface moves beneath them and this translates directly to the rate at which data can be sent to the host. Further, if you want to read data that&#8217;s on the other side of the platter, you have to wait for it to arrive &#8211; as data density capabilities have increased, so has the volume of data that is more than half a revolution away.</p>
<p>Lower rotational speed has a direct impact on the power required to spin the platters but it comes at the cost of performance. You could go install the 7200RPM SATA drives, or even go with Serially Attached SCSI (SAS) to get 10,000 and 15,000RPM drives &#8211; but if they spend any time idle, or less than say 50% busy, you may be wasting energy on it. And they cost more, too.</p>
<p>Most of the literature published by WDC doesn&#8217;t explicitly state the range of rotational speeds the RE4-GP drives operate at and most reviewers online either guess a value or have some way of measuring the speed and end up at 5400RPM along with comments like &#8220;I&#8217;ve not seen it vary with load&#8221;. This is disappointing but then I stumbled across a <a href="http://support.wdc.com/product/kb.asp?groupid=615&#038;lang=en">WDC Knowledge Base page</a> which supports the notion that the drives will vary their spin rate between 5400 and 7200RPM. This encouraged me and the fact that all the nay-sayers comments were from last year, and thus probably on old firmware, persuaded me to spin up some RE4-GP.</p>
<h2>The Setup</h2>
<p>I&#8217;ve long been a proponent of home-built machines &#8211; you get what you want, sometimes for less cash, with no vendor lock-in. Sometimes, however, I just can&#8217;t be bothered with it especially when I just want it to work. In superseding my trusty VMware/NAS host I decided to do something a bit more off-the-shelf. Supermicro and Dell were the obvious candidates for me. I was leery of Dell after reading about <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-11')" title="click to expand/collapse slider vendor lock-in">vendor lock-in&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-11"></span> issues with their RAID controllers. However they didn&#8217;t count on a huge customer backlash and quickly backtracked. Now it&#8217;s worth mentioning that Dell does offer very good support on the hard drives it supplies, but sometimes I feel that vendors lose sight of the <a href="http://en.wikipedia.org/wiki/RAID">&#8220;<em>I</em>&#8221; in <em>RAID</em></a>. <em>Inexpensive</em>.</p>
<p>In the end what sold me, after confirming the current firmware wasn&#8217;t vendor crippled, was that Dell had introduced the <a href="http://www.dell.com/us/business/p/poweredge-r515/pd">PowerEdge R515</a>: a dual AMD Opteron box with room for lots of memory and, more importantly, had a 12-drive chassis with an option for two more internal drives. I may not need all of them now, but I like having options down the road. Furthermore, they had some <em>huge</em> discounts for Small Business and for the second processor. It was a bargain. And free shipping too. I ordered it after forcing myself to spend a week considering whether it was a good idea or not.</p>
<p>I had drive trays already and I ordered the front drives from <a href="http://www.amazon.com/exec/obidos/ASIN/B002B7EIVC/cl-blog-20/">Amazon.com</a>. I kitted the machine out with two 2.8GHz Opterons and 32GB of DRAM. The Dell PERC H700 Raid Controller I ordered with 1GB of NVRAM. Basically, this thing should fly. I ordered two internal 10k RPM SAS drives, from Dell, configured as RAID-1 for the boot device and loaded the eight RE4-GP&#8217;s in the front, configured as RAID-6.</p>
<p>This setup has VMware ESXi 4.1 installed on the boot volume, hosted on the internal drives, and a combination of VMFS volumes and LUNs mapped directly into a client VM on the RE4-GP drives.</p>
<h2>How hungry are they?</h2>
<p>Western Digital specifies the RE4-GP and it&#8217;s 7200RPM brother power consumption as follows:</p>
<table>
<tr>
<th></th>
<th>RE4-GP</th>
<th>RE4</th>
</th>
<th>Difference</th>
</tr>
<tr>
<td>Read/Write</td>
<td>6.80 Watts</td>
<td>10.70 Watts</td>
<td>-36%</td>
</tr>
<tr>
<td>Idle</td>
<td>3.70 Watts</td>
<td>8.10 Watts</td>
<td>-54%</td>
</tr>
<tr>
<td>Standby</td>
<td>0.80 Watts</td>
<td>1.50 Watts</td>
<td>-47%</td>
</tr>
<tr>
<td>Sleep</td>
<td>0.80 Watts</td>
<td>1.50 Watts</td>
<td>-47%</td>
</tr>
</table>
<p>I added the difference column. It shows quite a drop. On a machine with ten drives that would mean at idle the GP uses 44W less than its counterpart and under load the difference is 39W. That&#8217;s 1 kWh per day. Where I live, that&#8217;s US$75 a year. Add in that the GP model costs less than its friend, there is a decent saving to be had.</p>
<p>Compare this to old NAS where it&#8217;s pulling about 150W just for hard drives when busy &#8211; and even when idle, they pull more than 110W (whole machine draws about 300 to 350W total). My replacement machine is looking good. In fact, the new Dell servers brag about having more efficient power supplies than previously and include power monitoring sensors, so I can tell you that before I put the RE4-GP drives in it was using a under 200W when I taxed both CPUs. This went up to just over 200W after I inserted them and now, whilst doing some file transfers from another host, the load is hovering at about 230W.</p>
<div id="attachment_326" class="wp-caption aligncenter" style="width: 733px"><a href="http://blog.flirble.org/wp-content/uploads/2010/11/bell-power.png" rel="shadowbox[sbpost-294];player=img;"><img src="http://blog.flirble.org/wp-content/uploads/2010/11/bell-power.png" alt="Dell PowerEdge R515 Power Graphi" title="Dell PowerEdge R515 Power Graph" width="723" height="312" class="size-full wp-image-326" /></a><p class="wp-caption-text">Dell PowerEdge R515 Power Graph</p></div>
<p>In the graph it is very obvious when the drives are idle or under load. Overall,  I&#8217;m better off by about 120W. 2.8 kWh per day. About $200 a year. Tangible.</p>
<h2>Performance</h2>
<p>The crux of the story, however, is what is the penalty of this power reduction? Well the host itself (discounting the hard drives) is using about the same amount of power as the older machine but has more cores (twelve versus four), more memory (32GB DDR3 versus 8GB DDR2) and a better memory management architecture (Opteron memory bandwidth scales with processors and this is a dual-chip board, the older machine was a Core2 Quad chip which is not known for its memory abilities). So we have <em>lots</em> more compute power. What about its storage?</p>
<p>The older machine uses 14 500GB drives (mostly RE2 but some RE3 as they&#8217;ve been replaced) drives in RAID-6 on an Areca controller with 1GB of cache memory. This configuration has usually done moderately well, easily reaching 150MBytes/sec on sequential reads once I&#8217;ve made sure it&#8217;s not fetching from the cache. By itself this is not a useful indicator of overall performance, but indicative of the ability to extract data from the platters which is, as mentioned above, a function of (to a large extent) rotational speed &#8211; my minor concern with the RE4-GP series.</p>
<p>This new setup has a major difference from the older one: fewer spindles. Fewer drives means that the load of reading and writing is spread across less hardware. With RAID-5 and RAID-6 setups this decreases some of the work performed by the RAID system when writing (the read-modify-write cycle) but, during reading especially, it means potentially that there is less bandwidth available.</p>
<p>Imagine my surprise, then, when I wrote out a 10 gigabyte file in under a minute. 200MBytes/sec. And reading was no slouch &#8211; from the cache it reached 600MBytes/sec at one point (The PERC H700 is a PCI-Express x8 card, so 8Gbits/sec is the physical maximum it can do &#8211; 600MBytes/sec is not too far from that limit!) and larger sequential reads ran between 150 and 200MBytes/sec. <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-12')" title="click to expand/collapse slider Note: Why would reads be slower?">Note: Why would reads be slower?&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-12"></span> Very respectable considering this is from within a guest virtual machine, too. For what it was worth the results were comparable with various file-system types, but ext4 and xfs are what I generally use with Linux. I may later post more comprehensive data from <code class="codecolorer text default"><span class="text">bonnie++</span></code>.</p>
<h2>Final word</h2>
<p>It&#8217;s only been a handful of days and I&#8217;ve not really exercised the new drives, or the new machine, but I&#8217;m happy with it so far. It uses less power than the machine it supplants, gives more compute resource, more storage space, more expandability and any concerns I had over the impact of using the low-power version of the hard drives and their indeterminate-but-probably-mostly-less-than-7200RPM rotational speed are diminished.</p>
<p><div id="attachment_337" class="wp-caption alignright" style="width: 310px"><a href="http://blog.flirble.org/wp-content/uploads/2010/11/bell-disk-perf.png" rel="shadowbox[sbpost-294];player=img;"><img src="http://blog.flirble.org/wp-content/uploads/2010/11/bell-disk-perf-300x118.png" alt="VMware ESXi Disk Performance Graph" title="VMware ESXi Disk Performance Graph" width="300" height="118" class="size-medium wp-image-337" /></a><p class="wp-caption-text">VMware ESXi Disk Performance Graph</p></div>Time will tell once I get some random-access workload going on the machine but right now I have it transferring a few terabytes of data using <code class="codecolorer text default"><span class="text">rsync</span></code> (read: as individual files of varying sizes) over my internal LAN and the only thing slowing it down is the Gigabit Ethernet interface. It&#8217;s doing a solid ~100MBytes/sec writing to disk, per the graph shown here, and has been for hours.</p>
<p>Yes, I&#8217;m happy.</p>
<h2>Errata</h2>
<p>I have posted some <a href="http://blog.flirble.org/2010/11/10/errata-raid-gone-green/">post-publication thoughts</a> on the read performance noted above.</p>

<div class='amazonpress'><h2>Related Reading</h2>
<div class='product'><a href='http://www.amazon.com/Accidental-Administrator-Step-Step-Configuration/dp/1453689923?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1453689923' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51nCexcuyxL._SL160_.jpg' class='amazonpress-product-image' alt='The Accidental Administrator: Linux Server Step-by-Step Configuration Guide' title='The Accidental Administrator: Linux Server Step-by-Step Configuration Guide' /></a>
</div><div class='product'><a href='http://www.amazon.com/Introducing-Windows-Server-Mitch-Tulloch/dp/0735624216?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=546246187-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0735624216' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51W6oLIfsFL._SL160_.jpg' class='amazonpress-product-image' alt='Introducing Windows Server 2008' title='Introducing Windows Server 2008' /></a>
</div><div class='product'><a href='http://www.amazon.com/Working-Ubuntu-Command-Line-Prompt-ebook/dp/B004RYVI0Q?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B004RYVI0Q' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51EfBhi5x9L._SL160_.jpg' class='amazonpress-product-image' alt='Working at the Ubuntu Command-Line Prompt (Linux Nitty Gritty)' title='Working at the Ubuntu Command-Line Prompt (Linux Nitty Gritty)' /></a>
</div><div class='product'><a href='http://www.amazon.com/Official-Ubuntu-Book-The-Edition/dp/0133017605?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0133017605' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51axScD29AL._SL160_.jpg' class='amazonpress-product-image' alt='Official Ubuntu Book, The (7th Edition)' title='Official Ubuntu Book, The (7th Edition)' /></a>
</div><div class='product'><a href='http://www.amazon.com/Ubuntu-Linux-Toolbox-Commands-Debian/dp/0470082933?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0470082933' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51bR0IMkbrL._SL160_.jpg' class='amazonpress-product-image' alt='Ubuntu Linux Toolbox: 1000+ Commands for Ubuntu and Debian Power Users' title='Ubuntu Linux Toolbox: 1000+ Commands for Ubuntu and Debian Power Users' /></a>
</div><div class='product'><a href='http://www.amazon.com/Managing-Ubuntu-Software-System-ebook/dp/B004SHF03S?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B004SHF03S' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51EVEBoMALL._SL160_.jpg' class='amazonpress-product-image' alt='Managing the Ubuntu Software System (Linux Nitty Gritty)' title='Managing the Ubuntu Software System (Linux Nitty Gritty)' /></a>
</div></div><div id="hackadelic-sliderNote-8" class="concealed">Western Digital 2 TB RE4-GP SATA 64MB Cache Enterprise Hard Drive WD2002FYPS: <a href="http://www.amazon.com/exec/obidos/ASIN/B002B7EIVC/cl-blog-20/">Amazon.com Product link</a>. <a href="http://www.wdc.com/en/products/products.asp?driveid=610">Manufacturer product link</a>.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div><div id="hackadelic-sliderNote-9" class="concealed">Desktop drives try quite hard to recover from read and write errors, so much so that sometimes they will spend a <em>really long time</em> working on a single operation to complete it &#8211; and make the host wait for it &#8211; so long, in fact, that RAID implementations will often give up on the drive altogether long before it starts talking again and assume the <em>entire</em> device is broken. RAID-savvy drives limit the amount of time that they&#8217;ll spend recovering from an error to avoid this blanket treatment and instead report an error sooner on the assumption that a fault-tolerant RAID implementation will have a quicker way to recover from occasional errors. Of course, if the errors are not intermittent, the RAID subsystem may yet decide the entire unit is defective &#8211; but it is in a better position to make that determination if it has more control.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div><div id="hackadelic-sliderNote-10" class="concealed">If you have many hard drives running adjacent to each other, or lots of servers in a single rack, there will be lots of vibrations. Hard drives, which have moving parts and tolerances in the &micro;m scale, don&#8217;t like vibrations &#8211; they can cause physical damage and impact performance. Even noise, which is just vibrations in the air, will have an effect.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div><div id="hackadelic-sliderNote-11" class="concealed">Where a manufacturer will try to force people who buy an expandable item from them to also buy all of the accessories from them, usually by making it arbitrarily incompatible with the other stuff on the market. Often this is dressed up as &#8220;to provide better end-user support by providing qualified/supported accessories&#8221; but in reality it&#8217;s to improve their margins.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div><div id="hackadelic-sliderNote-12" class="concealed">A suprising result from modern storage infrastructure is that sometimes reading can be slower than writes under certain load conditions. There&#8217;s many reasons why this may be so but a large part of it is the infrastructure trying to be too clever. Predictive reads and read-ahead logic try to fetch data from the device before you ask for it and some drives will read data that passes under its heads regardless, <em>just in case</em> you ask for it. Sometimes these strategies help a lot, sometimes they merely use up cache memory. Sometimes, they get in the way &#8211; particularly when you consider that a modern system may have such algorithms in the applications you run, in the operating system, in the storage subsystem (RAID controller) <em>and</em> on the hard drive itself. Sometimes these systems are not working in harmony and tuning is required.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div>]]></content:encoded>
			<wfw:commentRss>http://blog.flirble.org/2010/11/07/raid-gone-green/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iOS Ad-Hoc Beta publishing directly from Xcode</title>
		<link>http://blog.flirble.org/2010/10/28/adhoc-beta-directly-from-xcode/</link>
		<comments>http://blog.flirble.org/2010/10/28/adhoc-beta-directly-from-xcode/#comments</comments>
		<pubDate>Thu, 28 Oct 2010 14:10:35 +0000</pubDate>
		<dc:creator>Chris Luke</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[BetaBuilder]]></category>
		<category><![CDATA[Hunter Hillegas]]></category>
		<category><![CDATA[iPad]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[shell script]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">https://blog.flirble.org/?p=242</guid>
		<description><![CDATA[Using BetaBuilder and some shell scripting to fully automate iOS Ad Hoc beta app distribution directly from Xcode]]></description>
			<content:encoded><![CDATA[<p><br/></p>
<p>A couple of weeks ago I posted about <a href="http://blog.flirble.org/2010/10/16/app-ad-hoc-beta-publishing/">automating Ad-Hoc publishing</a> using some simple shell scripting and a modified version of the <a href="http://www.hanchorllc.com/2010/08/27/ios-betabuilder-source-code-on-github/">BetaBuilder</a> utility by Hunter Hillegas. Based on a <a href="http://www.hanchorllc.com/2010/10/24/some-interesting-betabuilder-forks/">comment on his blog</a> I&#8217;ve taken this a step further: I&#8217;ve fully integrated the publishing mechanism into Xcode. Here&#8217;s how&#8230;<span id="more-242"></span></p>
<h2>Aggregate Targets</h2>
<p>First step, if you don&#8217;t have one already, create a build configuration called something like &#8220;<em>Ad Hoc</em>&#8221; to differentiate a build from the normal <em>Release</em> and <em>Debug</em> variants. This is easily done: Go to the <em>Project menu → Edit Project Settings</em> (or, right-click or control-click on the project name at the top of <em>Groups &amp; Files</em> or you can even double-click on the icon to open this). Go to the Configurations tab and &#8220;<em>Duplicate</em>&#8221; the Release configuration. I call this copy &#8220;<em>Ad Hoc</em>&#8220;. Then you can change the code signing identity of this new configuration to the Ad Hoc profile you generate on the Apple Provisioning Portal. Remember in future that if you change any settings in the <em>Release</em> configuration, you may also need to change them in the <em>Ad Hoc</em> one too. <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-13')" title="click to expand/collapse slider Note: Does it need to be called Ad Hoc?">Note: Does it need to be called Ad Hoc?&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-13"></span></p>
<p><div id="attachment_258" class="wp-caption alignright" style="width: 310px"><a href="http://blog.flirble.org/wp-content/uploads/2010/10/Screen-shot-2010-10-28-at-10.45.24-PM.png" rel="shadowbox[sbpost-242];player=img;"><img class="size-medium wp-image-258" title="Xcode Aggregate Targets" src="http://blog.flirble.org/wp-content/uploads/2010/10/Screen-shot-2010-10-28-at-10.45.24-PM-300x244.png" alt="Xcode Aggregate Targets" width="300" height="244" /></a><p class="wp-caption-text">Xcode Aggregate Targets</p></div>At first thought the approach to use to automate distribution appeared to be adding a build step at the end of the target configuration in Xcode &#8211; however this has a problem: Codesigning occurs <em>after</em> any configurable build steps and we need to be able to use the signed version of the package. No problem! Xcode has an aggregate target type for just this situation &#8211; a <em>Shell Script Target</em> whose description reads &#8220;Target that just executes a script rather than building a product&#8221;. Better yet, aggregate targets are designed to be dependent on other targets so that they get executed after they have been built. This is exactly what we need. You add a target by right-clicking (control-click) on <em>Targets</em> in <em>Groups &amp; Files</em>, choosing <em>Add → New Target&#8230;</em> and in the <em>Mac OS X → Other</em> section there&#8217;s a selection of aggregate targets. I name this target &#8220;<em>Package &amp; Distribute Ad Hoc</em>&#8221; but you can call it whatever you want.</p>
<div id="attachment_259" class="wp-caption alignright" style="width: 277px"><a href="http://blog.flirble.org/wp-content/uploads/2010/10/Screen-shot-2010-10-28-at-10.45.45-PM.png" rel="shadowbox[sbpost-242];player=img;"><img class="size-full wp-image-259" title="Example Shell Script Target" src="http://blog.flirble.org/wp-content/uploads/2010/10/Screen-shot-2010-10-28-at-10.45.45-PM.png" alt="Example Shell Script Target" width="267" height="122" /></a><p class="wp-caption-text">Example Shell Script Target</p></div>
<p>You now have a new target in <em>Groups &amp; Files</em>, expand it and you&#8217;ll see it has a single build step named &#8220;<em>Run Script</em>&#8220;. Right-click on this, select<em> Get Info</em> and you&#8217;re presented with a dialog with a basic &#8220;<em>Script</em>&#8220;. What I use here looks like:</p>
<div class="codecolorer-container bash default codecolorer-title" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;">Package and Distribute Ad Hoc → Run Script</div><div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #800000;">${HOME}</span><span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>ipa-packager <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">0</span></div></td></tr></tbody></table></div>
<p>Quite simply, <code class="codecolorer text default"><span class="text">ipa-packager</span></code> is a shell script based on the one in a previous blog post that does the packaging for me. If it returns an error code, so do we &#8211; this is the signal to Xcode to stop the build process. All the other options to the <em>Run Script</em> dialog we leave at defaults.</p>
<div id="attachment_260" class="wp-caption alignright" style="width: 207px"><a href="http://blog.flirble.org/wp-content/uploads/2010/10/Screen-shot-2010-10-28-at-10.46.36-PM.png" rel="shadowbox[sbpost-242];player=img;"><img class="size-medium wp-image-260" title="Shell Script Configuration" src="http://blog.flirble.org/wp-content/uploads/2010/10/Screen-shot-2010-10-28-at-10.46.36-PM-197x300.png" alt="Shell Script Configuration" width="197" height="300" /></a><p class="wp-caption-text">Shell Script Configuration</p></div>
<p>Lastly, we need to make this new target depend on the target of our app. The easiest mechanism to do this is to simply drag-and-drop the app target, under <em>Groups &amp; Files</em>, into the new target. Job done.</p>
<h2>Packaging revisited</h2>
<p>So, what next? If we try to build the project above it will complain because <code class="codecolorer text default"><span class="text">ipa-packager</span></code> doesn&#8217;t exist. I reworked the script from my previous blog post to work either directly from the command line or using the environment variables that Xcode passes to scripts. The revised version appears below and is attached at the bottom, for download.</p>
<p>I also improved a number of items, particularly dependency checking so it does not re-do work that is unnecessary. Another area I paid attention to is being able to provide some of the settings in either the Xcode project or target build configuration &#8211; any user-defined values are also provided in the environment of the script. This is just as well since, because the script is called from its own target, the environment variable identifying the current target is that of the script, not our iOS app! Consequently, I have to provide at least one setting in the project: <code class="codecolorer text default"><span class="text">ADHOC_TARGET_NAME</span></code> which I set to the name of the app.</p>
<p>One more major improvement is the provision of a local &#8220;configuration&#8221; file that allows a user of this script to set their own defaults without having to tweak the script itself. An example is given below. I will at some point add a command line tweak to allow for an arbitrary file to be used for this configuration.</p>
<a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-14')" title="click to expand/collapse slider Shell script: ipa-packager">Shell script: ipa-packager&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-14"></span> <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-15')" title="click to expand/collapse slider Configuration file: ~/.adhoc-distribution.conf">Configuration file: ~/.adhoc-distribution.conf&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-15"></span></p>
<p>Naturally you will wish to alter the publishing URL to one that works for you or, as described in the next section, you can do this in the project configuration inside Xcode.</p>
<p>The observant reader will have noticed references to an <code class="codecolorer text default"><span class="text">ADHOC_TEMPLATE_HTML</span></code> value. This is not yet used but it will allow a project to provide its own HTML template for the generated <code class="codecolorer text default"><span class="text">index.html</span></code> file, the same way it does now for the <code class="codecolorer text default"><span class="text">README.txt</span></code> file.</p>
<h2>Configuring from Xcode</h2>
<p>So, we have our Xcode target and we have the script that does the magic of packaging and distributing an Ad Hoc build. There&#8217;s one component left &#8211; the values that we need to pass from Xcode to <code class="codecolorer text default"><span class="text">ipa-packager</span></code>. There&#8217;s more than one place you can do this (project or target level), and you can apply it to just Ad Hoc builds or to all &#8211; even though it won&#8217;t distribute code for non Ad Hoc builds, you may wish to archive development and release builds all the same. You should decide what functionality you want and where to keep the values. The suggested approach is to keep values unique to a target within that targets configuration and is what I shall demonstrate here.</p>
<div id="attachment_267" class="wp-caption alignright" style="width: 310px"><a href="http://blog.flirble.org/wp-content/uploads/2010/10/Screen-shot-2010-10-29-at-9.26.33-AM.png" rel="shadowbox[sbpost-242];player=img;"><img src="http://blog.flirble.org/wp-content/uploads/2010/10/Screen-shot-2010-10-29-at-9.26.33-AM-300x150.png" alt="Xcode Target Build Configuration" title="Xcode Target Build Configuration" width="300" height="150" class="size-medium wp-image-267" /></a><p class="wp-caption-text">Xcode Target Build Configuration</p></div>
<p>We need the Target Info page open for the aggregate &#8220;Run Shell Script&#8221; target we added earlier (right-click, control-click or double-click on the target under <em>Groups &amp; Files</em>) and select the <em>Build</em> tab. The item &#8220;<em>Configuration:</em>&#8221; is where you will decide whether to apply the values to one specific configuration (such as <em>Ad Hoc</em>) or to all of them. Then quit simply use the cog-menu at bottom-left to <em>Add User-Defined Setting</em>. There is only value you must specify as barest minimum: <code class="codecolorer text default"><span class="text">ADHOC_TARGET_NAME</span></code> which needs to refer to the name of the target in the project that contains your app. This should also be the same as the application name &#8211; that is, the name of the <code class="codecolorer text default"><span class="text">.app</span></code> package.</p>
<p>You can also specify <em>any</em> of the values used by <code class="codecolorer text default"><span class="text">ipa-packager</span></code> though note that the results may be undefined if you try to redefine a value provided by Xcode itself. Where I use a common URL scheme for all my projects, others may wish to specify a unique URL for each project and you can do that here by adding a value for <code class="codecolorer text default"><span class="text">ADHOC_PUBLISHING_URL</span></code> to their project. See the script for the full list of values it will look for.</p>
<h2>Replaceable values</h2>
<p>Some of the environment variables that <code class="codecolorer text default"><span class="text">ipa-packager</span></code> uses have a notion of replaceable values. These are components of a string that are replaced with values that are determined at runtime. The idea is to enable these variables to provide a template for the final value. For example, the default for <code class="codecolorer text default"><span class="text">ADHOC_PUBLISHING_URL</span></code> is <code class="codecolorer text default"><span class="text">http://localhost/iosbeta/#SHORTBUNDLEID#-#BUILD#</span></code>. <a href="javascript:;" class="hackadelic-sliderButton"onclick="toggleSlider('#hackadelic-sliderPanel-16')" title="click to expand/collapse slider Note: You keep using 'localhost'. Why?">Note: You keep using 'localhost'. Why?&raquo;</a> <span class="hackadelic-sliderPanel concealed" id="hackadelic-sliderPanel-16"></span> #SHORTBUNDLEID# is replaced with &#8220;<em>abcsea</em>&#8221; (the last component of <em>org.flirble.abcsea</em>) and #BUILD# is replaced by the current build number which is discovered by reading the key <code class="codecolorer text default"><span class="text">CFBundleVersion</span></code> from the targets <code class="codecolorer text default"><span class="text">Info.plist</span></code> file.</p>
<p>Not all variables are checked for replaceable values since it is not a trivial process in a shell script. You can check in the script to see which ones are by looking at the contents of variable <code class="codecolorer text default"><span class="text">replacement_options</span></code>. At the time of writing, this contained:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #007800;">replacement_options</span>=<span style="color: #ff0000;">&quot;ADHOC_PUBLISHING_URL ADHOC_DELIVERY_NAME <span style="color: #000099; font-weight: bold;">\<br />
</span> &nbsp; &nbsp;ADHOC_TEMPLATE_HTML ADHOC_PUBLISHING_DIRECTORY <span style="color: #000099; font-weight: bold;">\<br />
</span> &nbsp; &nbsp;ADHOC_PUBLISHING_COMMAND&quot;</span></div></td></tr></tbody></table></div>
<p>The replaceable values are:</p>
<table>
<tbody>
<tr>
<td><code class="codecolorer text default"><span class="text">#PROJECT#</span></code></td>
<td>Project name  (spaces removed)</td>
</tr>
<tr>
<td><code class="codecolorer text default"><span class="text">#APP#</span></code> or <code class="codecolorer text default"><span class="text">#TARGET#</span></code></td>
<td>The app/target name (spaces removed)</td>
</tr>
<tr>
<td><code class="codecolorer text default"><span class="text">#CONFIG#</span></code></td>
<td>The build configuration name (Release, Ad Hoc)</td>
</tr>
<tr>
<td><code class="codecolorer text default"><span class="text">#VERSION#</span></code></td>
<td>The version number  (from CFBundleShortVersionString)</td>
</tr>
<tr>
<td><code class="codecolorer text default"><span class="text">#BUILD#</span></code></td>
<td>The build number  (from CFBundleVersion)</td>
</tr>
<tr>
<td><code class="codecolorer text default"><span class="text">#BUNDLEID#</span></code></td>
<td>The bundle ID</td>
</tr>
<tr>
<td><code class="codecolorer text default"><span class="text">#SHORTBUNDLEID#</span></code></td>
<td>The last component of the bundle ID</td>
</tr>
<tr>
<td><code class="codecolorer text default"><span class="text">#PLATFORM#</span></code></td>
<td>The targetted platform, iphoneos or iphonesimulator</td>
</tr>
</tbody>
</table>
<p>These values can appear anywhere within variables that are inspected, and any number of times.</p>
<h2>The result</h2>
<p>A picture says it all&#8230;</p>
<div id="attachment_261" class="wp-caption aligncenter" style="width: 816px"><a href="http://blog.flirble.org/wp-content/uploads/2010/10/Screen-shot-2010-10-28-at-10.48.38-PM.png" rel="shadowbox[sbpost-242];player=img;"><img class="size-full wp-image-261" title="Xcode Build Results" src="http://blog.flirble.org/wp-content/uploads/2010/10/Screen-shot-2010-10-28-at-10.48.38-PM.png" alt="Xcode Build Results" width="806" height="548" /></a><p class="wp-caption-text">Xcode Build Results with ipa-packager</p></div>
<h2>Attachments</h2>
<p><em>Note that some files may be downloaded with a <code class="codecolorer text default"><span class="text">.txt</span></code> file extension to overcome WordPress security checks. Just rename the file if necessary once downloaded.</em></p>
<ul>
<li><a href="http://blog.flirble.org/wp-content/uploads/2010/10/ipa-packager.txt">ipa-packager</a></li>
<li><a href="http://blog.flirble.org/wp-content/uploads/2010/10/adhoc-distribution.conf.txt">adhoc-distribution.conf</a></li>
</ul>

<div class='amazonpress'><h2>Related Reading</h2>
<div class='product'><a href='http://www.amazon.com/Learning-iOS-Programming-Xcode-Store/dp/1449303773?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1449303773' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/41SkH9yTX2L._SL160_.jpg' class='amazonpress-product-image' alt='Learning iOS Programming: From Xcode to App Store' title='Learning iOS Programming: From Xcode to App Store' /></a>
</div><div class='product'><a href='http://www.amazon.com/iPhone-The-Missing-Manual-Edition/dp/1449393659?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=546246187-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1449393659' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51N4agxhXVL._SL160_.jpg' class='amazonpress-product-image' alt='iPhone: The Missing Manual, 4th Edition' title='iPhone: The Missing Manual, 4th Edition' /></a>
</div><div class='product'><a href='http://www.amazon.com/iOS-Programming-Ranch-Edition-Guides/dp/0321821521?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0321821521' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/41ybikkCyLL._SL160_.jpg' class='amazonpress-product-image' alt='iOS Programming: The Big Nerd Ranch Guide (3rd Edition) (Big Nerd Ranch Guides)' title='iOS Programming: The Big Nerd Ranch Guide (3rd Edition) (Big Nerd Ranch Guides)' /></a>
</div><div class='product'><a href='http://www.amazon.com/Mastering-Unix-Shell-Scripting-Administrators/dp/0470183012?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0470183012' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51Q25JyGckL._SL160_.jpg' class='amazonpress-product-image' alt='Mastering Unix Shell Scripting: Bash, Bourne, and Korn Shell Scripting for Programmers, System Administrators, and UNIX Gurus' title='Mastering Unix Shell Scripting: Bash, Bourne, and Korn Shell Scripting for Programmers, System Administrators, and UNIX Gurus' /></a>
</div><div class='product'><a href='http://www.amazon.com/The-Unofficial-Siri-Handbook-ebook/dp/B006BZNWOE?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B006BZNWOE' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/41mfUSMY0RL._SL160_.jpg' class='amazonpress-product-image' alt='The Unofficial Siri Handbook: The Essential Reference for Your iPhone 4S' title='The Unofficial Siri Handbook: The Essential Reference for Your iPhone 4S' /></a>
</div><div class='product'><a href='http://www.amazon.com/Unix-Shell-Programming-3rd-Edition/dp/0672324903?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0672324903' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/510agXOHSOL._SL160_.jpg' class='amazonpress-product-image' alt='Unix Shell Programming (3rd Edition)' title='Unix Shell Programming (3rd Edition)' /></a>
</div></div><div id="hackadelic-sliderNote-13" class="concealed">You don&#8217;t need to call it Ad Hoc &#8211; the packaging script below contains a configurable value for this name, <code class="codecolorer text default"><span class="text">ADHOC_CONFIG_ADHOC</span></code> which you are free to change.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div><div id="hackadelic-sliderNote-14" class="concealed"><p>
<div class="codecolorer-container bash default codecolorer-title" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;">ipa-packager</div><div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br />91<br />92<br />93<br />94<br />95<br />96<br />97<br />98<br />99<br />100<br />101<br />102<br />103<br />104<br />105<br />106<br />107<br />108<br />109<br />110<br />111<br />112<br />113<br />114<br />115<br />116<br />117<br />118<br />119<br />120<br />121<br />122<br />123<br />124<br />125<br />126<br />127<br />128<br />129<br />130<br />131<br />132<br />133<br />134<br />135<br />136<br />137<br />138<br />139<br />140<br />141<br />142<br />143<br />144<br />145<br />146<br />147<br />148<br />149<br />150<br />151<br />152<br />153<br />154<br />155<br />156<br />157<br />158<br />159<br />160<br />161<br />162<br />163<br />164<br />165<br />166<br />167<br />168<br />169<br />170<br />171<br />172<br />173<br />174<br />175<br />176<br />177<br />178<br />179<br />180<br />181<br />182<br />183<br />184<br />185<br />186<br />187<br />188<br />189<br />190<br />191<br />192<br />193<br />194<br />195<br />196<br />197<br />198<br />199<br />200<br />201<br />202<br />203<br />204<br />205<br />206<br />207<br />208<br />209<br />210<br />211<br />212<br />213<br />214<br />215<br />216<br />217<br />218<br />219<br />220<br />221<br />222<br />223<br />224<br />225<br />226<br />227<br />228<br />229<br />230<br />231<br />232<br />233<br />234<br />235<br />236<br />237<br />238<br />239<br />240<br />241<br />242<br />243<br />244<br />245<br />246<br />247<br />248<br />249<br />250<br />251<br />252<br />253<br />254<br />255<br />256<br />257<br />258<br />259<br />260<br />261<br />262<br />263<br />264<br />265<br />266<br />267<br />268<br />269<br />270<br />271<br />272<br />273<br />274<br />275<br />276<br />277<br />278<br />279<br />280<br />281<br />282<br />283<br />284<br />285<br />286<br />287<br />288<br />289<br />290<br />291<br />292<br />293<br />294<br />295<br />296<br />297<br />298<br />299<br />300<br />301<br />302<br />303<br />304<br />305<br />306<br />307<br />308<br />309<br />310<br />311<br />312<br />313<br />314<br />315<br />316<br />317<br />318<br />319<br />320<br />321<br />322<br />323<br />324<br />325<br />326<br />327<br />328<br />329<br />330<br />331<br />332<br />333<br />334<br />335<br />336<br />337<br />338<br />339<br />340<br />341<br />342<br />343<br />344<br />345<br />346<br />347<br />348<br />349<br />350<br />351<br />352<br />353<br />354<br />355<br />356<br />357<br />358<br />359<br />360<br />361<br />362<br />363<br />364<br />365<br />366<br />367<br />368<br />369<br />370<br />371<br />372<br />373<br />374<br />375<br />376<br />377<br />378<br />379<br />380<br />381<br />382<br />383<br />384<br />385<br />386<br />387<br />388<br />389<br />390<br />391<br />392<br />393<br />394<br />395<br />396<br />397<br />398<br />399<br />400<br />401<br />402<br />403<br />404<br />405<br />406<br />407<br />408<br />409<br />410<br />411<br />412<br />413<br />414<br />415<br />416<br />417<br />418<br />419<br />420<br />421<br />422<br />423<br />424<br />425<br />426<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#!/bin/sh</span><br />
<span style="color: #666666; font-style: italic;"># Build an IPA package from an Ad Hoc build and then</span><br />
<span style="color: #666666; font-style: italic;"># package it for Ad Hoc distribution.</span><br />
<span style="color: #666666; font-style: italic;"># This version is designed for use as a Shell Script Target</span><br />
<span style="color: #666666; font-style: italic;"># called directly by Xcode.</span><br />
<span style="color: #666666; font-style: italic;"># (c) 2010 Chris Luke. Copying is fine, but please attribute to me!</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Useful environment variables Xcode provides:</span><br />
<span style="color: #666666; font-style: italic;"># BUILD_DIR</span><br />
<span style="color: #666666; font-style: italic;"># CONFIGURATION</span><br />
<span style="color: #666666; font-style: italic;"># CONFIGURATION_BUILD_DIR</span><br />
<span style="color: #666666; font-style: italic;"># CONFIGURATION_TEMP_DIR</span><br />
<span style="color: #666666; font-style: italic;"># EFFECTIVE_PLATFORM_NAME</span><br />
<span style="color: #666666; font-style: italic;"># ACTION (build|clean)</span><br />
<span style="color: #666666; font-style: italic;"># CURRENT_PROJECT_VERSION</span><br />
<span style="color: #666666; font-style: italic;"># PROJECT_DIR</span><br />
<span style="color: #666666; font-style: italic;"># PROJECT_NAME</span><br />
<span style="color: #666666; font-style: italic;"># PROJECT_TEMP_DIR</span><br />
<span style="color: #666666; font-style: italic;"># TARGET_TEMP_DIR</span><br />
<br />
<span style="color: #666666; font-style: italic;"># User settings we can place in the target settings:</span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_PUBLISHING_URL &nbsp;with replaceables</span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_TARGET_NAME &nbsp; &nbsp; the target we want to copy from </span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_BUNDLE_SOURCE &nbsp; the build dir of the app we want to copy for</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; distribution- built from TARGET_NAME if not set</span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_TEMPLATE_HTML &nbsp; template for index.html</span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_TEMPLATE_README templatye for readme file</span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_DELIVERY_NAME &nbsp; name of .zip/.ipa with replaceables</span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_DELIVERY_DIRECTORY directory to deliver a .zip archive of app to</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ie, releases, archived copies</span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_DELIVER_DSYM &nbsp; &nbsp;If set and not 0 or no then we also copy the .dSYM</span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_PUBLISHING_DIRECTORY directory to deliver the pkg to with replaceables</span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_PUBLISHING_COMMAND command to execute to push materials out with</span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_CONFIG_ADHOC &nbsp;the label used for ad hoc builds</span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_CONFIG_RELEASE &nbsp;the label used for release builds</span><br />
<span style="color: #666666; font-style: italic;"># ADHOC_AUTHOR</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Configuration can go into ~/.adhoc-distribution.conf . Defaults have the</span><br />
<span style="color: #666666; font-style: italic;"># form DEFAULT_&lt;VARIABLE_NAME&gt; and are used only if the variable is not set.</span><br />
<span style="color: #666666; font-style: italic;"># If you name a variable directly in the config, it overwrites any existing</span><br />
<span style="color: #666666; font-style: italic;"># value.</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Replaceable values, where supported:</span><br />
<span style="color: #666666; font-style: italic;"># #PROJECT# &nbsp; &nbsp; &nbsp; Project name &nbsp;(spaces removed)</span><br />
<span style="color: #666666; font-style: italic;"># #APP# #TARGET# &nbsp;The app/target name (spaces removed)</span><br />
<span style="color: #666666; font-style: italic;"># #CONFIG# &nbsp; &nbsp; &nbsp; &nbsp;The build configuration name (Release, Ad Hoc)</span><br />
<span style="color: #666666; font-style: italic;"># #VERSION# &nbsp; &nbsp; &nbsp; The version number &nbsp;(from CFBundleShortVersionString)</span><br />
<span style="color: #666666; font-style: italic;"># #BUILD# &nbsp; &nbsp; &nbsp; &nbsp; The build number &nbsp;(from CFBundleVersion)</span><br />
<span style="color: #666666; font-style: italic;"># #BUNDLEID# &nbsp; &nbsp; &nbsp;The bundle ID</span><br />
<span style="color: #666666; font-style: italic;"># #SHORTBUNDLEID# The last component of the bundle ID</span><br />
<span style="color: #666666; font-style: italic;"># #PLATFORM# &nbsp; &nbsp; &nbsp;The targetted platform, iphoneos or iphonesimulator</span><br />
<span style="color: #666666; font-style: italic;"># </span><br />
<br />
<span style="color: #007800;">pfx</span>=<span style="color: #ff0000;">&quot;Ad-Hoc IPA Packager:&quot;</span><br />
<span style="color: #007800;">err</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$pfx</span>&quot;</span><br />
<span style="color: #007800;">config_file</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$HOME</span>/.adhoc-distribution.conf&quot;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Some generic defaults. These can be overridden in a local config file</span><br />
<span style="color: #007800;">DEFAULT_BASEDIR</span>=<br />
<span style="color: #007800;">DEFAULT_ADHOC_PUBLISHING_URL</span>=<span style="color: #ff0000;">&quot;http://localhost/iosbeta/#SHORTBUNDLEID#-#BUILD#&quot;</span><br />
<span style="color: #007800;">DEFAULT_ADHOC_PUBLISHING_DIRECTORY</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$HOME</span>/Documents/iosbeta/#SHORTBUNDLEID#-#BUILD#&quot;</span><br />
<span style="color: #007800;">DEFAULT_ADHOC_PUBLISHING_COMMAND</span>=<span style="color: #007800;">$HOME</span><span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>sync-iosbeta<br />
<span style="color: #007800;">DEFAULT_ADHOC_DELIVERY_NAME</span>=<span style="color: #ff0000;">&quot;#APP#-#VERSION#-#BUILD#-#CONFIG#.ipa&quot;</span><br />
<span style="color: #007800;">DEFAULT_ADHOC_DELIVERY_DIRECTORY</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$HOME</span>/Documents/iOSArchives&quot;</span><br />
<span style="color: #007800;">DEFAULT_ADHOC_DELIVER_DSYM</span>=<span style="color: #c20cb9; font-weight: bold;">yes</span><br />
<span style="color: #007800;">DEFAULT_ADHOC_CONFIG_ADHOC</span>=<span style="color: #ff0000;">&quot;Ad Hoc&quot;</span><br />
<span style="color: #007800;">DEFAULT_ADHOC_CONFIG_RELEASE</span>=<span style="color: #ff0000;">&quot;Release&quot;</span><br />
<span style="color: #007800;">DEFAULT_ADHOC_AUTHOR</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">id</span> <span style="color: #660033;">-P</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">cut</span> -d: -f8<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #007800;">DEFAULT_verbose</span>=<span style="color: #000000;">0</span><br />
<span style="color: #007800;">DEFAULT_FORCEPKG</span>=<span style="color: #000000;">0</span><br />
<br />
<span style="color: #007800;">default_options</span>=<span style="color: #ff0000;">&quot;BASEDIR <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; ADHOC_PUBLISHING_URL ADHOC_TARGET_NAME ADHOC_BUNDLE_SOURCE <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; ADHOC_TEMPLATE_HTML ADHOC_TEMPLATE_README ADHOC_DELIVERY_NAME <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; ADHOC_DELIVERY_DIRECTORY ADHOC_PUBLISHING_DIRECTORY <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; ADHOC_PUBLISHING_COMMAND ADHOC_CONFIG_ADHOC ADHOC_CONFIG_RELEASE <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; ADHOC_DELIVER_DSYM ADHOC_AUTHOR verbose FORCEPKG&quot;</span><br />
<span style="color: #007800;">mandatory_options</span>=<span style="color: #ff0000;">&quot;ADHOC_TARGET_NAME ADHOC_DELIVERY_NAME <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; ADHOC_DELIVERY_DIRECTORY ADHOC_CONFIG_ADHOC ADHOC_CONFIG_RELEASE <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; BUILD_DIR CONFIGURATION CONFIGURATION_BUILD_DIR <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; CONFIGURATION_TEMP_DIR ACTION PROJECT_DIR PROJECT_NAME <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; TARGET_TEMP_DIR&quot;</span><br />
<span style="color: #007800;">mandatory_directories</span>=<span style="color: #ff0000;">&quot;PROJECT_DIR CONFIGURATION_BUILD_DIR <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; CONFIGURATION_TEMP_DIR TARGET_TEMP_DIR ADHOC_DELIVERY_DIRECTORY&quot;</span><br />
<span style="color: #007800;">replacement_options</span>=<span style="color: #ff0000;">&quot;ADHOC_PUBLISHING_URL ADHOC_DELIVERY_NAME <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; ADHOC_TEMPLATE_HTML ADHOC_PUBLISHING_DIRECTORY <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; ADHOC_PUBLISHING_COMMAND&quot;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Load any local configuration</span><br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${config_file}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> . <span style="color: #ff0000;">&quot;<span style="color: #007800;">${config_file}</span>&quot;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># See if any defaults need to be loaded</span><br />
<span style="color: #000000; font-weight: bold;">for</span> opt <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${default_options}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; <span style="color: #007800;">val</span>=<br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;val=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #000099; font-weight: bold;">\$</span><span style="color: #007800;">$opt</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$val</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">val</span>=<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;val=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #000099; font-weight: bold;">\$</span>DEFAULT_<span style="color: #007800;">$opt</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$val</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$opt</span>=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$val</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
<span style="color: #000000; font-weight: bold;">done</span><br />
<br />
<span style="color: #007800;">docmd</span>=<span style="color: #000000;">0</span><br />
<span style="color: #007800;">dohelp</span>=<span style="color: #000000;">0</span><br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-t</span> <span style="color: #000000;">0</span> <span style="color: #660033;">-a</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ACTION}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #007800;">dohelp</span>=<span style="color: #000000;">1</span><br />
<span style="color: #000000; font-weight: bold;">while</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; <span style="color: #007800;">opt</span>=<span style="color: #007800;">$1</span><br />
&nbsp; &nbsp; <span style="color: #007800;">dohelp</span>=<span style="color: #000000;">0</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$opt</span>&quot;</span> <span style="color: #000000; font-weight: bold;">in</span><br />
&nbsp; &nbsp; --project<span style="color: #000000; font-weight: bold;">|</span>-p<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">PROJECT_NAME</span>=<span style="color: #ff0000;">&quot;$2&quot;</span>; <span style="color: #7a0874; font-weight: bold;">shift</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">docmd</span>=<span style="color: #000000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">shift</span><span style="color: #000000; font-weight: bold;">;;</span><br />
<br />
&nbsp; &nbsp; --target<span style="color: #000000; font-weight: bold;">|</span>--app<span style="color: #000000; font-weight: bold;">|</span>-t<span style="color: #000000; font-weight: bold;">|</span>-a<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">ADHOC_TARGET_NAME</span>=<span style="color: #ff0000;">&quot;$2&quot;</span>; <span style="color: #7a0874; font-weight: bold;">shift</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">docmd</span>=<span style="color: #000000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">shift</span><span style="color: #000000; font-weight: bold;">;;</span><br />
<br />
&nbsp; &nbsp; --config<span style="color: #000000; font-weight: bold;">*|</span>-c<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">CONFIGURATION</span>=<span style="color: #ff0000;">&quot;$2&quot;</span>; <span style="color: #7a0874; font-weight: bold;">shift</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">shift</span><span style="color: #000000; font-weight: bold;">;;</span><br />
<br />
&nbsp; &nbsp; --basedir<span style="color: #000000; font-weight: bold;">|</span>-b<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${PROJECT_NAME}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$err</span> Specify project name before base directory.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_TARGET_NAME}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$err</span> Specify target name before base directory.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">BASEDIR</span>=<span style="color: #ff0000;">&quot;$2&quot;</span>; <span style="color: #7a0874; font-weight: bold;">shift</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">shift</span><span style="color: #000000; font-weight: bold;">;;</span><br />
<br />
&nbsp; &nbsp; --force<span style="color: #000000; font-weight: bold;">*|</span>-f<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">FORCEPKG</span>=<span style="color: #000000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">shift</span><span style="color: #000000; font-weight: bold;">;;</span><br />
<br />
&nbsp; &nbsp; --verbose<span style="color: #000000; font-weight: bold;">|</span>-v<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">verbose</span>=<span style="color: #000000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">shift</span><span style="color: #000000; font-weight: bold;">;;</span><br />
<br />
&nbsp; &nbsp; --help<span style="color: #000000; font-weight: bold;">|</span>-h<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">dohelp</span>=<span style="color: #000000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">shift</span><span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">dohelp</span>=<span style="color: #000000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Unknown option <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$opt</span><span style="color: #000099; font-weight: bold;">\&quot;</span>.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">shift</span><span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">esac</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dohelp}</span>&quot;</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> <span style="color: #7a0874; font-weight: bold;">break</span><br />
<span style="color: #000000; font-weight: bold;">done</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dohelp}</span>&quot;</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><br />
<span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #cc0000; font-style: italic;">&lt;&lt; EOT<br />
$pfx Usage: $(basename $0) [options]<br />
&nbsp; &nbsp; --project|-p &lt;name&gt; &nbsp; &nbsp; Project name<br />
&nbsp; &nbsp; --target|--app|-t|-a &lt;name&gt; Target name<br />
&nbsp; &nbsp; --config|-c &lt;name&gt;&nbsp; &nbsp; &nbsp; Project configuration name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (Debug, Release, Ad Hoc)<br />
&nbsp; &nbsp; --basedir|-b &lt;dir&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Parent directory of projects<br />
&nbsp; &nbsp; --force|-f&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Force packaging, even if up-to-date<br />
<br />
&nbsp; &nbsp; --help|-h &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; This message<br />
&nbsp; &nbsp; --verbose|-v&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Verbose mode<br />
<br />
Configuration can also be loaded from &quot;${config_file}&quot;<br />
<br />
EOT</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${BASEDIR}</span>&quot;</span> <span style="color: #660033;">-a</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${docmd}</span>&quot;</span> = <span style="color: #000000;">1</span> <span style="color: #660033;">-a</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${PROJECT_NAME}</span>&quot;</span> <span style="color: #660033;">-a</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_TARGET_NAME}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${BASEDIR}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$err</span> Basedir <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${BASEDIR}</span><span style="color: #000099; font-weight: bold;">\&quot;</span> is not readable.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${CONFIGURATION}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #007800;">CONFIGURATION</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${DEFAULT_ADHOC_CONFIG_ADHOC}</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">ACTION</span>=build<br />
&nbsp; &nbsp; <span style="color: #007800;">EFFECTIVE_PLATFORM_NAME</span>=-iphoneos<br />
&nbsp; &nbsp; <span style="color: #007800;">PROJECT_DIR</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${BASEDIR}</span>/<span style="color: #007800;">${PROJECT_NAME}</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">BUILD_DIR</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${PROJECT_DIR}</span>/build&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">PROJECT_TEMP_DIR</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${BUILD_DIR}</span>/<span style="color: #007800;">${PROJECT_NAME}</span>.build&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">CONFIGURATION_BUILD_DIR</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${BUILD_DIR}</span>/<span style="color: #007800;">${CONFIGURATION}</span><span style="color: #007800;">${EFFECTIVE_PLATFORM_NAME}</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">CONFIGURATION_TEMP_DIR</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${BUILD_DIR}</span>/<span style="color: #007800;">${PROJECT_NAME}</span>.build/<span style="color: #007800;">${CONFIGURATION}</span><span style="color: #007800;">${EFFECTIVE_PLATFORM_NAME}</span>/<span style="color: #007800;">${PROJECT_NAME}</span>.build&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">TARGET_BUILD_DIR</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${CONFIGURATION_BUILD_DIR}</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">TARGET_TEMP_DIR</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${BUILD_DIR}</span>/<span style="color: #007800;">${PROJECT_NAME}</span>.build/<span style="color: #007800;">${CONFIGURATION}</span><span style="color: #007800;">${EFFECTIVE_PLATFORM_NAME}</span>/<span style="color: #007800;">${ADHOC_TARGET_NAME}</span>.build&quot;</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ACTION}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">!</span>= build <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${docmd}</span>&quot;</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><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$err</span> Incomplete parameters.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Need basedir, project name and target name, at minimum.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${verbose}</span>&quot;</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> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$pfx</span> No packaging for action <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${ACTION}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>.&quot;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">0</span> &nbsp;<span style="color: #666666; font-style: italic;"># we only work when building, not cleaning</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${BUILD_DIR}</span>&quot;</span> <span style="color: #660033;">-o</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${BUILD_DIR}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$err</span> No valid BUILD_DIR!&quot;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Check for mandatory values</span><br />
<span style="color: #000000; font-weight: bold;">for</span> opt <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${mandatory_options}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; <span style="color: #007800;">val</span>=<br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;val=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #000099; font-weight: bold;">\$</span><span style="color: #007800;">$opt</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$val</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$err</span> Variable <span style="color: #007800;">$opt</span> is mandatory, yet empty.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
<span style="color: #000000; font-weight: bold;">done</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Check for mandatory directories</span><br />
<span style="color: #000000; font-weight: bold;">for</span> opt <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${mandatory_directories}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; <span style="color: #007800;">val</span>=<br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;val=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #000099; font-weight: bold;">\$</span><span style="color: #007800;">$opt</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$val</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$err</span> <span style="color: #007800;">$opt</span> is a missing mandatory directory <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$val</span><span style="color: #000099; font-weight: bold;">\&quot;</span>.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
<span style="color: #000000; font-weight: bold;">done</span><br />
<br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_BUNDLE_SOURCE}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #007800;">ADHOC_BUNDLE_SOURCE</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${CONFIGURATION_BUILD_DIR}</span>/<span style="color: #007800;">${ADHOC_TARGET_NAME}</span>.app&quot;</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_BUNDLE_SOURCE}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$err</span> Can't find App <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${ADHOC_TARGET_NAME}</span><span style="color: #000099; font-weight: bold;">\&quot;</span> at <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${ADHOC_BUNDLE_SOURCE}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #007800;">plist</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_BUNDLE_SOURCE}</span>/Info.plist&quot;</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${plist}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$err</span> Can't find <span style="color: #000099; font-weight: bold;">\&quot;</span>Info.plist<span style="color: #000099; font-weight: bold;">\&quot;</span> at <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${plist}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">pwd</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Get build and release versions</span><br />
<span style="color: #007800;">bundle_id</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>plutil <span style="color: #660033;">-convert</span> xml1 <span style="color: #660033;">-o</span> - - <span style="color: #000000; font-weight: bold;">&lt;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${plist}</span>&quot;</span> &nbsp;<span style="color: #000000; font-weight: bold;">|</span> \<br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-A</span> <span style="color: #000000;">1</span> CFBundleIdentifier <span style="color: #000000; font-weight: bold;">|</span> \<br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/&lt;[^&gt;]*&gt;//g'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/[ &nbsp; ]//g'</span><span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">tail</span> -<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #007800;">bundle_short</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${bundle_id}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-Ee</span> <span style="color: #ff0000;">'s/^.*\.(.*)$/\1/'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #007800;">release_ver</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>plutil <span style="color: #660033;">-convert</span> xml1 <span style="color: #660033;">-o</span> - - <span style="color: #000000; font-weight: bold;">&lt;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${plist}</span>&quot;</span> &nbsp;<span style="color: #000000; font-weight: bold;">|</span> \<br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-A</span> <span style="color: #000000;">1</span> CFBundleShortVersionString <span style="color: #000000; font-weight: bold;">|</span> \<br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/&lt;[^&gt;]*&gt;//g'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/[ &nbsp; ]//g'</span><span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">tail</span> -<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #007800;">build_ver</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>plutil <span style="color: #660033;">-convert</span> xml1 <span style="color: #660033;">-o</span> - - <span style="color: #000000; font-weight: bold;">&lt;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${plist}</span>&quot;</span> &nbsp;<span style="color: #000000; font-weight: bold;">|</span> \<br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-A</span> <span style="color: #000000;">1</span> CFBundleVersion <span style="color: #000000; font-weight: bold;">|</span> \<br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/&lt;[^&gt;]*&gt;//g'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/[ &nbsp; ]//g'</span><span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">tail</span> -<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #007800;">config</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${CONFIGURATION}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/ &nbsp;*//g'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #007800;">ws_project_name</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${PROJECT_NAME}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/ &nbsp;*/_/g'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #007800;">ws_app_name</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_TARGET_NAME}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/ &nbsp;*/_/g'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #007800;">ws_platform</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${EFFECTIVE_PLATFORM_NAME}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/^-//'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Packaging project <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${PROJECT_NAME}</span><span style="color: #000099; font-weight: bold;">\&quot;</span> target <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${ADHOC_TARGET_NAME}</span><span style="color: #000099; font-weight: bold;">\&quot;</span> config <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${CONFIGURATION}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;* Bundle ID <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${bundle_id}</span><span style="color: #000099; font-weight: bold;">\&quot;</span> (<span style="color: #007800;">${bundle_short}</span>) version <span style="color: #007800;">${release_ver}</span> build <span style="color: #007800;">${build_ver}</span>...&quot;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Do parameter replacement</span><br />
<span style="color: #000000; font-weight: bold;">for</span> opt <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${replacement_options}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; <span style="color: #007800;">val</span>=<br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;val=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #000099; font-weight: bold;">\$</span><span style="color: #007800;">$opt</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">val</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$val</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/#PROJECT#/<span style="color: #007800;">${ws_project_name}</span>/g&quot;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/#APP#/<span style="color: #007800;">${ws_app_name}</span>/g&quot;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/#TARGET#/<span style="color: #007800;">${ws_app_name}</span>/g&quot;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/#CONFIG#/<span style="color: #007800;">${config}</span>/g&quot;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/#BUILD#/<span style="color: #007800;">${build_ver}</span>/g&quot;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/#VERSION#/<span style="color: #007800;">${release_ver}</span>/g&quot;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/#BUNDLEID#/<span style="color: #007800;">${bundle_id}</span>/g&quot;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/#SHORTBUNDLEID#/<span style="color: #007800;">${bundle_short}</span>/g&quot;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/#PLATFORM#/<span style="color: #007800;">${ws_platform}</span>/g&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$opt</span>=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$val</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
<span style="color: #000000; font-weight: bold;">done</span><br />
<br />
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #660033;">-p</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_DELIVERY_DIRECTORY}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_DELIVERY_NAME}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> \<br />
&nbsp; &nbsp; <span style="color: #007800;">ADHOC_DELIVERY_NAME</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_TARGET_NAME}</span>-<span style="color: #007800;">${release_ver}</span>-<span style="color: #007800;">${build_ver}</span>-<span style="color: #007800;">${config}</span>.zip&quot;</span><br />
<span style="color: #007800;">zip</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_DELIVERY_DIRECTORY}</span>/<span style="color: #007800;">${ADHOC_DELIVERY_NAME}</span>&quot;</span><br />
<span style="color: #007800;">zip</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${zip}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/ &nbsp;*/_/g'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$(echo &quot;${zip}&quot; | grep -Ec '\.(zip|ipa)</span>$')&quot;</span> = <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$err</span> ADHOC_DELIVERY_NAME needs to end with .ipa or .zip&quot;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;The expanded name was: <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$zip</span><span style="color: #000099; font-weight: bold;">\&quot;</span>.&quot;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$verbose</span>&quot;</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> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;+ zip=<span style="color: #007800;">$zip</span>&quot;</span><br />
<span style="color: #007800;">dsymin</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_BUNDLE_SOURCE}</span>.dSYM&quot;</span><br />
<span style="color: #007800;">dsymout</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${zip}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-Ee</span> <span style="color: #ff0000;">'s/\.(zip|ipa)$/.dSYM.zip/'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$verbose</span>&quot;</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> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;+ dsymin=<span style="color: #007800;">$dsymin</span>&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$verbose</span>&quot;</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> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;+ dsym=<span style="color: #007800;">$dsymout</span>&quot;</span><br />
<br />
<span style="color: #007800;">dozip</span>=<span style="color: #c20cb9; font-weight: bold;">yes</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${zip}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># See if zip is older than the code signature or binary</span><br />
&nbsp; &nbsp; <span style="color: #007800;">tf</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_BUNDLE_SOURCE}</span>/_CodeSignature/CodeResources&quot;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${tf}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #007800;">tf</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_BUNDLE_SOURCE}</span>/<span style="color: #007800;">${ADHOC_TARGET_NAME}</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${tf}</span>&quot;</span> <span style="color: #660033;">-a</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${zip}</span>&quot;</span> <span style="color: #660033;">-nt</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${tf}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">dozip</span>=no<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${verbose}</span>&quot;</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> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$pfx</span> Existing archive is still current, no need to build.&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #007800;">dodsym</span>=no<br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_DELIVER_DSYM}</span>&quot;</span> <span style="color: #660033;">-a</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dsymin}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_DELIVER_DSYM}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">in</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span>Nn<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span>Oo<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">dodsym</span>=no<span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">dodsym</span>=<span style="color: #c20cb9; font-weight: bold;">yes</span><span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">esac</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dsymin}</span>&quot;</span> <span style="color: #660033;">-ot</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dsymout}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${verbose}</span>&quot;</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> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$pfx</span> Existing dSYM is still current, no need to copy.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">dodsym</span>=no<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dozip}</span>&quot;</span> = <span style="color: #c20cb9; font-weight: bold;">yes</span> <span style="color: #660033;">-o</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${FORCEPKG}</span>&quot;</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><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Make a copy of the build into the Payload directory</span><br />
&nbsp; &nbsp; <span style="color: #007800;">tmpdir</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${TARGET_TEMP_DIR}</span>/adhoc-pkg&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">payloaddir</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${tmpdir}</span>/Payload/<span style="color: #007800;">${ADHOC_TARGET_NAME}</span>.app&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">payload</span>=<span style="color: #ff0000;">&quot;Payload&quot;</span><br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${tmpdir}</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #660033;">-p</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${payloaddir}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #660033;">-rp</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_BUNDLE_SOURCE}</span>/&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${payloaddir}</span>/&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
<br />
&nbsp; &nbsp; <span style="color: #007800;">oldpwd</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">pwd</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${payloaddir}</span>/../../&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; <span style="color: #007800;">bindir</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${payload}</span>/<span style="color: #007800;">${ADHOC_TARGET_NAME}</span>.app&quot;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Now zip it up</span><br />
&nbsp; &nbsp; <span style="color: #007800;">year</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">date</span> +<span style="color: #000000; font-weight: bold;">%</span>Y<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${zip}</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">opt_zip</span>=<br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${verbose}</span>&quot;</span> = <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #007800;">opt_zip</span>=<span style="color: #ff0000;">&quot;-q&quot;</span><br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">zip</span> <span style="color: #660033;">-Xyrz</span> <span style="color: #800000;">${opt_zip}</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${zip}</span>&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${bindir}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">&lt;&lt;</span> EOT <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-v</span> <span style="color: #ff0000;">'enter new zip file comment'</span><br />
Project: <span style="color: #800000;">${PROJECT_NAME}</span><br />
App: <span style="color: #800000;">${ADHOC_TARGET_NAME}</span><br />
Build configuration: <span style="color: #800000;">${CONFIGURATION}</span><br />
Release: <span style="color: #800000;">${release_ver}</span><br />
Build: <span style="color: #800000;">${build_ver}</span><br />
<span style="color: #7a0874; font-weight: bold;">&#40;</span>c<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #800000;">${year}</span> <span style="color: #800000;">${ADHOC_AUTHOR}</span><br />
<br />
.<br />
EOT<br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">#zip -T &quot;${zip}&quot; || exit 1</span><br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">unzip</span> <span style="color: #660033;">-tq</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${zip}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Packaged into <span style="color: #007800;">${zip}</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${oldpwd}</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${tmpdir}</span>&quot;</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dodsym}</span>&quot;</span> = <span style="color: #c20cb9; font-weight: bold;">yes</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${verbose}</span>&quot;</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> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$pfx</span> Archiving dSYM...&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">oldpwd</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">pwd</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dsymin}</span>/../&quot;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #007800;">year</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">date</span> +<span style="color: #000000; font-weight: bold;">%</span>Y<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dsymout}</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">opt_zip</span>=<br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${verbose}</span>&quot;</span> = <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #007800;">opt_zip</span>=<span style="color: #ff0000;">&quot;-q&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">dsymname</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">basename</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dsymin}</span>&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">zip</span> <span style="color: #660033;">-Xyrz</span> <span style="color: #800000;">${opt_zip}</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dsymout}</span>&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dsymname}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">&lt;&lt;</span> EOT <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-v</span> <span style="color: #ff0000;">'enter new zip file comment'</span><br />
Project: <span style="color: #800000;">${PROJECT_NAME}</span><br />
App: <span style="color: #800000;">${ADHOC_TARGET_NAME}</span><br />
Build configuration: <span style="color: #800000;">${CONFIGURATION}</span><br />
Release: <span style="color: #800000;">${release_ver}</span><br />
Build: <span style="color: #800000;">${build_ver}</span><br />
<span style="color: #7a0874; font-weight: bold;">&#40;</span>c<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #800000;">${year}</span> <span style="color: #800000;">${ADHOC_AUTHOR}</span><br />
<br />
.<br />
EOT<br />
<br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${oldpwd}</span>&quot;</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #666666; font-style: italic;"># If it's Ad Hoc, the right options are set, it's iphoneos and it has been codesigned, we can publish it.</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${CONFIGURATION}</span>&quot;</span> = <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_CONFIG_ADHOC}</span>&quot;</span> <span style="color: #660033;">-a</span> \<br />
&nbsp; &nbsp; <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_PUBLISHING_DIRECTORY}</span>&quot;</span> <span style="color: #660033;">-a</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_PUBLISHING_URL}</span>&quot;</span> \<br />
&nbsp; &nbsp; <span style="color: #660033;">-a</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${EFFECTIVE_PLATFORM_NAME}</span>&quot;</span> = <span style="color: #ff0000;">&quot;-iphoneos&quot;</span> <span style="color: #660033;">-a</span> \<br />
&nbsp; &nbsp; <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_BUNDLE_SOURCE}</span>/_CodeSignature/CodeResources&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># If it exists already, see if it is fresh.</span><br />
&nbsp; &nbsp; <span style="color: #007800;">dopkg</span>=<span style="color: #c20cb9; font-weight: bold;">yes</span><br />
&nbsp; &nbsp; <span style="color: #007800;">pkg</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_PUBLISHING_DIRECTORY}</span>/&quot;</span>$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_DELIVERY_NAME}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/\.ipa$/.zip/'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${pkg}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${pkg}</span>&quot;</span> <span style="color: #660033;">-nt</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${zip}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">dopkg</span>=no<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${verbose}</span>&quot;</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> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$pfx</span> Existing package is still current, no need to package and distribute.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${dopkg}</span>&quot;</span> = <span style="color: #c20cb9; font-weight: bold;">yes</span> <span style="color: #660033;">-o</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${FORCEPKG}</span>&quot;</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><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># One more step - package it up for iosbeta distribution!</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Distributing Ad Hoc release into <span style="color: #007800;">${ADHOC_PUBLISHING_DIRECTORY}</span>...&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #660033;">-p</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_PUBLISHING_DIRECTORY}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">opt_readme</span>=<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_TEMPLATE_README}</span>&quot;</span> <span style="color: #660033;">-a</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_TEMPLATE_README}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">opt_readme</span>=<span style="color: #ff0000;">&quot;-r <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${ADHOC_TEMPLATE_README}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">opt_html</span>=<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_TEMPLATE_HTML}</span>&quot;</span> <span style="color: #660033;">-a</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_TEMPLATE_HTML}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">opt_html</span>=<span style="color: #ff0000;">&quot;-r <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${ADHOC_TEMPLATE_HTML}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">cmd</span>=<span style="color: #ff0000;">&quot;open -n <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$HOME</span>/Documents/MacOSX Projects/BetaBuilder TFO/build/Debug/BetaBuilder.app<span style="color: #000099; font-weight: bold;">\&quot;</span> --args <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -i <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${zip}</span><span style="color: #000099; font-weight: bold;">\&quot;</span> <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -o <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${ADHOC_PUBLISHING_DIRECTORY}</span><span style="color: #000099; font-weight: bold;">\&quot;</span> <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -u <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${ADHOC_PUBLISHING_URL}</span><span style="color: #000099; font-weight: bold;">\&quot;</span> <span style="color: #000099; font-weight: bold;">\<br />
</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">${opt_readme}</span> <span style="color: #007800;">${opt_html}</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${cmd}</span>&quot;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_PUBLISHING_COMMAND}</span>&quot;</span> <span style="color: #660033;">-a</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">-x</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_PUBLISHING_COMMAND}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Distributing Ad Hoc release to website...&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff0000;">&quot;<span style="color: #007800;">${ADHOC_PUBLISHING_COMMAND}</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;BetaBuilder encountered an error. Check system logs.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">0</span><br />
<br />
&nbsp;</div></td></tr></tbody></table></div>
<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div><div id="hackadelic-sliderNote-15" class="concealed"><p></p>
<div class="codecolorer-container bash default codecolorer-title" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;">~/.adhoc-distribution.conf</div><div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># ~/.adhoc-distribution.conf</span><br />
<span style="color: #666666; font-style: italic;"># Default values for our IPA packager and Ad Hoc distribution script</span><br />
<span style="color: #666666; font-style: italic;">#</span><br />
<span style="color: #007800;">DEFAULT_BASEDIR</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$HOME</span>/Documents/iPhone Projects&quot;</span><br />
<br />
<span style="color: #007800;">DEFAULT_ADHOC_PUBLISHING_URL</span>=<span style="color: #ff0000;">&quot;http://localhost/iosbeta/#SHORTBUNDLEID#-#BUILD#&quot;</span><br />
<span style="color: #007800;">DEFAULT_ADHOC_PUBLISHING_DIRECTORY</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$HOME</span>/Documents/iosbeta/#SHORTBUNDLEID#-#BUILD#&quot;</span><br />
<span style="color: #007800;">DEFAULT_ADHOC_PUBLISHING_COMMAND</span>=<span style="color: #007800;">$HOME</span><span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>sync-iosbeta<br />
<br />
<span style="color: #007800;">DEFAULT_ADHOC_DELIVERY_NAME</span>=<span style="color: #ff0000;">&quot;#APP#-#VERSION#-#BUILD#-#PLATFORM#-#CONFIG#.ipa&quot;</span><br />
<span style="color: #007800;">DEFAULT_ADHOC_DELIVERY_DIRECTORY</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$HOME</span>/Documents/iOSArchives&quot;</span><br />
<br />
<span style="color: #007800;">DEFAULT_ADHOC_CONFIG_ADHOC</span>=<span style="color: #ff0000;">&quot;Ad Hoc&quot;</span><br />
<span style="color: #007800;">DEFAULT_ADHOC_CONFIG_RELEASE</span>=<span style="color: #ff0000;">&quot;Release&quot;</span><br />
<span style="color: #007800;">DEFAULT_ADHOC_AUTHOR</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">id</span> <span style="color: #660033;">-P</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">cut</span> -d: -f8<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<br />
<span style="color: #007800;">DEFAULT_ADHOC_TEMPLATE_README</span>=README.txt<br />
<span style="color: #007800;">DEFAULT_ADHOC_TEMPLATE_HTML</span>=<br />
<br />
&nbsp;</div></td></tr></tbody></table></div>
<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div><div id="hackadelic-sliderNote-16" class="concealed">I&#8217;m using <code class="codecolorer text default"><span class="text">localhost</span></code> just as an example, and to avoid making the URL of my real beta site too public. You should set <code class="codecolorer text default"><span class="text">ADHOC_PUBLISHING_URL</span></code> to use the hostname of your own website.<span style="display: block; margin-top: 3px; font-size: 7px"><a href="http://hackadelic.com/solutions/wordpress/sliding-notes" title="Powered by Hackadelic Sliding Notes 1.6.5">Powered by Hackadelic Sliding Notes 1.6.5</a></span></div>]]></content:encoded>
			<wfw:commentRss>http://blog.flirble.org/2010/10/28/adhoc-beta-directly-from-xcode/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Poor-guys CDN (ish)</title>
		<link>http://blog.flirble.org/2010/10/19/poor-guys-cdn/</link>
		<comments>http://blog.flirble.org/2010/10/19/poor-guys-cdn/#comments</comments>
		<pubDate>Tue, 19 Oct 2010 14:46:23 +0000</pubDate>
		<dc:creator>Chris Luke</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[BIND]]></category>
		<category><![CDATA[CDN]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[dynamic DNS]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[IPv6]]></category>
		<category><![CDATA[LWP]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[reverse proxy]]></category>
		<category><![CDATA[shell script]]></category>
		<category><![CDATA[Squid]]></category>

		<guid isPermaLink="false">http://blog.flirble.org/?p=224</guid>
		<description><![CDATA[For fun, I setup a couple of Squid proxies in reverse-proxy fashion to see how it performed. Overall, I am happy with the result but a key thought behind the idea is to provide front-end resilience to the resources they publish. To that end, I made what can be best described as a poor-guys CDN. [...]]]></description>
			<content:encoded><![CDATA[<p><br />
For fun, I setup a couple of Squid proxies in reverse-proxy fashion to see how it performed. Overall, I am happy with the result but a key thought behind the idea is to provide front-end resilience to the resources they publish. To that end, I made what can be best described as a poor-guys CDN. It&#8217;s not truly a CDN in the sense of global presence nor the ability to choose a front-end server closer to the end-user (not least because some of that functionality is patent-encumbered), but it does provide some degree of resilience.<br />
<span id="more-224"></span><br />
Once you have a reverse-proxy setup (which I am not covering here) the key elements are testing the front-end servers and then updating a dynamic-DNS entry with the results. Then you may feel the need to pre-load your caches. This is all simple to achieve &#8211; it can be done with some shell scripting, a tiny bit of Perl and the BIND <code class="codecolorer text default"><span class="text">nsupdate</span></code> utility.</p>
<h3>Testing front-end availability</h3>
<p>To probe each front-end reverse-proxy we use the <code class="codecolorer text default"><span class="text">GET</span></code> tool that is installed with the <code class="codecolorer text default"><span class="text">LWP</span></code> package in Perl. This provides a very simple no-bells mechanism to perform an HTTP request. We configure <code class="codecolorer text default"><span class="text">GET</span></code> with a proxy server, that of the reverse-proxy we wish to test, and the URL of a resource that it should succeed in fetching. Since we want to run this often, we choose something small and with minimal CPU impact. You do need to decide whether to fetch a cacheable object or one that will always force a fetch from the origin-server &#8211; this depends on how deeply you want to test the system. For this example, we&#8217;ll just fetch this blogs <code class="codecolorer text default"><span class="text">favicon.ico</span></code>.</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#!/bin/sh</span><br />
<span style="color: #007800;">target_url</span>=<span style="color: #ff0000;">&quot;http://blog.flirble.org/favicon.ico&quot;</span><br />
<span style="color: #007800;">target_proxies</span>=<span style="color: #ff0000;">&quot;10.1.0.0.1 10.2.0.0.2&quot;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">for</span> proxy <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${target_proxies}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Testing proxy: <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${proxy}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>...&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; GET <span style="color: #660033;">-t</span> <span style="color: #000000;">10</span> <span style="color: #660033;">-P</span> <span style="color: #660033;">-p</span> <span style="color: #ff0000;">&quot;http://<span style="color: #007800;">${proxy}</span>:<span style="color: #007800;">${proxy_port}</span>/&quot;</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${target_url}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #007800;">final_proxies</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${final_proxies}</span> <span style="color: #007800;">${proxy}</span>&quot;</span><br />
<span style="color: #000000; font-weight: bold;">done</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Strip leading space</span><br />
<span style="color: #007800;">final_proxies</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${final_proxies}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/^ //'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Final proxies: <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${final_proxies}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span></div></td></tr></tbody></table></div>
<p>Yes, I am using fake IP addresses there.</p>
<h4>Fixing LWP for IPv6</h4>
<p>Unfortunately, <code class="codecolorer text default"><span class="text">LWP</span></code> doesn&#8217;t handle IPv6 very well. There are two workarounds needed to make it work. Firstly, the code that parses HTTP proxy configuration doesn&#8217;t understand the URI form <code class="codecolorer text default"><span class="text">http://[2001:0db8::1]:80/</span></code> &#8211; anything with square brackets makes it croak with <code class="codecolorer text default"><span class="text">Bad http proxy specification</span></code>. This is a simple regexp fix, per the diff below. Hopefully this will be fixed in CPAN sometime.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">*** UserAgent-orig.pm &nbsp; Tue Oct 19 10:28:43 2010<br />
--- UserAgent.pm&nbsp; &nbsp; Tue Oct 19 10:15:47 2010<br />
***************<br />
*** 914,920 ****<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $url = shift;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (defined($url) &amp;&amp; length($url)) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Carp::croak(&quot;Proxy must be specified as absolute URI; '$url' is not&quot;) unless $url =~ /^$URI::scheme_re:/;<br />
! &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Carp::croak(&quot;Bad http proxy specification '$url'&quot;) if $url =~ /^https?:/ &amp;&amp; $url !~ m,^https?://\w,;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;{proxy}{$key} = $url;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;set_my_handler(&quot;request_preprepare&quot;, \&amp;_need_proxy)<br />
--- 914,920 ----<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $url = shift;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (defined($url) &amp;&amp; length($url)) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Carp::croak(&quot;Proxy must be specified as absolute URI; '$url' is not&quot;) unless $url =~ /^$URI::scheme_re:/;<br />
! &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Carp::croak(&quot;Bad http proxy specification '$url'&quot;) if $url =~ /^https?:/ &amp;&amp; $url !~ m,^https?://[\w\[],;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;{proxy}{$key} = $url;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;set_my_handler(&quot;request_preprepare&quot;, \&amp;_need_proxy)</div></td></tr></tbody></table></div>
<p>The second problem is more fundamental, but also easier to fix. LWP doesn&#8217;t know that IPv6 connections use a different module library from IPv4 (IPv6 in Perl is approximately broken in general as a result). Thankfully someone has a workaround for this, the module <a href="http://search.cpan.org/~sullr/Net-INET6Glue-0.4/lib/Net/INET6Glue/INET_is_INET6.pm">Net::INET6Glue::INET_is_INET6</a> (available in Ubuntu/Debian as package <code class="codecolorer text default"><span class="text">libnet-inet6glue-perl</span></code>) which does some low-level Perl hackery to make the normal socket routines work for IPv6 also.</p>
<p>Armed with a modified UserAgent.pm and this INET6Glue module, we can do this:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">perl -MNet::INET6Glue::INET_is_INET6 $(which GET) -t 10 -P <br />
&nbsp; &nbsp; &nbsp; &nbsp; -p &quot;http://[${proxy}]:${proxy_port}/&quot; -d &quot;${target_url}&quot;</div></td></tr></tbody></table></div>
<p>and achieve the desired result.</p>
<h3>Dynamic DNS</h3>
<p>There are several aspects to updating a DNS record dynamically. You need to have a DNS server that is authoritative for a zone, is the primary authoritative server for that zone, and it must be configured to allow updates for a record, or records, or a sub-zone.<br />
Then you can use a client utility to cause DNS records to be updated with the results of the tests performed above.</p>
<h4>DNS server configuration</h4>
<p>My setup uses BIND (for better or for worse) and I keep my dynamic records under the zone &#8220;<em>dyn.flirble.org</em>&#8220;. The record for this reverse-proxy setup has the name &#8220;<em>ac</em>&#8220;.</p>
<p>The configuration for this zone looks a bit like this:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">key &quot;ac-key&quot; {<br />
&nbsp; &nbsp; algorithm hmac-md5;<br />
&nbsp; &nbsp; secret &quot;encryptedkeytexthere==&quot;;<br />
};<br />
...<br />
zone &quot;dyn.flirble.org&quot; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; type master;<br />
&nbsp; &nbsp; &nbsp; &nbsp; file &quot;dynamic/dyn.flirble.org&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; allow-update {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key ac-key;<br />
&nbsp; &nbsp; &nbsp; &nbsp; };<br />
&nbsp; &nbsp; &nbsp; &nbsp; also-notify {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1.2.3.5; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; };<br />
};</div></td></tr></tbody></table></div>
<p>There are other, stronger, crypto schemes, but this works for my purposes. You can generate a key simply with <code class="codecolorer text default"><span class="text">dnssec-keygen</span></code> as follows:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ dnssec-keygen -a HMAC-MD5 -b 128 -n HOST ac-key<br />
Kac-key.+157+53816<br />
<br />
$ cat Kac-key.+157+53816.key<br />
ac-key. IN KEY 512 3 157 kmLKD48bOaodPm0vkUyLqQ==<br />
<br />
$</div></td></tr></tbody></table></div>
<p>Delete the two files generated when you&#8217;re done. That string &#8220;kmL&#8230;Q==&#8221; is the one you want. It&#8217;s random and you can generate it however you like. </p>
<h4>Sending in updates</h4>
<p>We&#8217;ll use another BIND tool for this, <code class="codecolorer text default"><span class="text">nsupdate</span></code>. It works by collecting together a batch of commands and them sending them as a unit to the name server. As a result, the operation is (probably) atomic, meaning you can simply erase the existing records and add the new set without worrying about a period of time when you return no A or AAAA records.</p>
<p>I do this as follows:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #007800;">ns_ttl</span>=<span style="color: #000000;">60</span><br />
<span style="color: #007800;">ns_server</span>=1.2.3.4<br />
<span style="color: #007800;">ns_zone</span>=dyn.flirble.org<br />
<span style="color: #007800;">ns_hostname</span>=ac.<span style="color: #800000;">${ns_zone}</span><br />
<br />
<span style="color: #007800;">nu_key</span>=<span style="color: #ff0000;">&quot;ac-key:encryptedkeytexthere==&quot;</span><br />
<span style="color: #007800;">nu_cmd</span>=<span style="color: #ff0000;">&quot;/usr/bin/nsupdate -v -y <span style="color: #007800;">${nu_key}</span>&quot;</span><br />
...<br />
<span style="color: #7a0874; font-weight: bold;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> server <span style="color: #800000;">${ns_server}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> zone <span style="color: #800000;">${ns_zone}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> update delete <span style="color: #800000;">${ns_hostname}</span> A<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> update delete <span style="color: #800000;">${ns_hostname}</span> AAAA<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> proxy <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${final_proxies}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> update add <span style="color: #800000;">${ns_hostname}</span> <span style="color: #800000;">${ns_ttl}</span> A <span style="color: #800000;">${proxy}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">done</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> proxy <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${final_proxies6}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> update add <span style="color: #800000;">${ns_hostname}</span> <span style="color: #800000;">${ns_ttl}</span> AAAA <span style="color: #800000;">${proxy}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">done</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> send<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span><br />
<span style="color: #7a0874; font-weight: bold;">&#125;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #800000;">${nu_cmd}</span></div></td></tr></tbody></table></div>
<h3>Putting it all together</h3>
<p>Here&#8217;s the entire script:</p>
<div class="codecolorer-container bash default codecolorer-title" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;">update-proxy-cluster-dns</div><div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#!/bin/sh</span><br />
<br />
<span style="color: #007800;">ns_ttl</span>=<span style="color: #000000;">60</span><br />
<span style="color: #007800;">ns_server</span>=1.2.3.4<br />
<span style="color: #007800;">ns_zone</span>=dyn.flirble.org<br />
<span style="color: #007800;">ns_hostname</span>=ac.<span style="color: #800000;">${ns_zone}</span><br />
<br />
<span style="color: #007800;">nu_key</span>=<span style="color: #ff0000;">&quot;ac-key:encryptedkeytexthere==&quot;</span><br />
<span style="color: #007800;">nu_cmd</span>=<span style="color: #ff0000;">&quot;/usr/bin/nsupdate -v -y <span style="color: #007800;">${nu_key}</span>&quot;</span><br />
<br />
<span style="color: #007800;">target_url</span>=<span style="color: #ff0000;">&quot;http://blog.flirble.org/favicon.ico&quot;</span><br />
<span style="color: #007800;">target_proxies</span>=<span style="color: #ff0000;">&quot;10.1.0.1 10.2.0.2&quot;</span><br />
<span style="color: #007800;">target_proxies6</span>=<span style="color: #ff0000;">&quot;2001:0db8::1 2001:0db8::2&quot;</span><br />
<span style="color: #007800;">proxy_port</span>=<span style="color: #000000;">80</span><br />
<span style="color: #007800;">final_proxies</span>=<span style="color: #ff0000;">&quot;&quot;</span><br />
<span style="color: #007800;">final_proxies6</span>=<span style="color: #ff0000;">&quot;&quot;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">for</span> proxy <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${target_proxies}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Testing proxy: <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${proxy}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>...&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; GET <span style="color: #660033;">-t</span> <span style="color: #000000;">10</span> <span style="color: #660033;">-P</span> <span style="color: #660033;">-p</span> <span style="color: #ff0000;">&quot;http://<span style="color: #007800;">${proxy}</span>:<span style="color: #007800;">${proxy_port}</span>/&quot;</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${target_url}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">final_proxies</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${final_proxies}</span> <span style="color: #007800;">${proxy}</span>&quot;</span><br />
<span style="color: #000000; font-weight: bold;">done</span><br />
<span style="color: #000000; font-weight: bold;">for</span> proxy <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${target_proxies6}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Testing proxy: <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${proxy}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>...&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># libnet-inet6glue-perl</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">perl</span> -MNet::INET6Glue::INET_is_INET6 $<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">which</span> GET<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #660033;">-t</span> <span style="color: #000000;">10</span> <span style="color: #660033;">-P</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">-p</span> <span style="color: #ff0000;">&quot;http://[<span style="color: #007800;">${proxy}</span>]:<span style="color: #007800;">${proxy_port}</span>/&quot;</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${target_url}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">final_proxies6</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${final_proxies}</span> <span style="color: #007800;">${proxy}</span>&quot;</span><br />
<span style="color: #000000; font-weight: bold;">done</span><br />
<br />
<span style="color: #007800;">final_proxies</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${final_proxies}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/^ //'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #007800;">final_proxies6</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${final_proxies6}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/^ //'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Final proxies: <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${final_proxies}</span><span style="color: #000099; font-weight: bold;">\&quot;</span> <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">${final_proxies6}</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${final_proxies}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Oh dear. Just point at them all, in case they come back.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">final_proxies</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${target_proxies}</span>&quot;</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #7a0874; font-weight: bold;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> server <span style="color: #800000;">${ns_server}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> zone <span style="color: #800000;">${ns_zone}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> update delete <span style="color: #800000;">${ns_hostname}</span> A<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> update delete <span style="color: #800000;">${ns_hostname}</span> AAAA<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> proxy <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${final_proxies}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> update add <span style="color: #800000;">${ns_hostname}</span> <span style="color: #800000;">${ns_ttl}</span> A <span style="color: #800000;">${proxy}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">done</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> proxy <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${final_proxies6}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> update add <span style="color: #800000;">${ns_hostname}</span> <span style="color: #800000;">${ns_ttl}</span> AAAA <span style="color: #800000;">${proxy}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">done</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> send<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span><br />
<span style="color: #7a0874; font-weight: bold;">&#125;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #800000;">${nu_cmd}</span></div></td></tr></tbody></table></div>
<p>Then you just CNAME your resources to this dynamic entry. Presto, site resilience. I run this script every two minutes from <code class="codecolorer text default"><span class="text">cron</span></code>.</p>
<h3>Pre-loading the cache</h3>
<p>Finally, I also have another simple script that I use to pre-load the contents of the caches. This is as simple as recursively iterating the page structure downloading the contents &#8211; in this case using <code class="codecolorer text default"><span class="text">wget</span></code>. There are two options to ensure the cache is loaded: A forced load which always fetches from the origin server, or one that validates the cached object and fetches from the origin only if it&#8217;s out of date or not loaded.</p>
<p>This script specifically takes only the reverse-proxies currently listed as available by the dynamic DNS method above. At the moment it skips IPv6 addresses since they point to the same servers as the IPv4 addresses and would be redundant.</p>
<div class="codecolorer-container bash default codecolorer-title" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;">force-cache-load</div><div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#!/bin/sh</span><br />
<br />
<span style="color: #007800;">force</span>=no<br />
<span style="color: #007800;">quiet</span>=<span style="color: #c20cb9; font-weight: bold;">yes</span><br />
<br />
<span style="color: #007800;">args</span>=<br />
<span style="color: #000000; font-weight: bold;">while</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #000000; font-weight: bold;">in</span><br />
&nbsp; &nbsp; --force<span style="color: #000000; font-weight: bold;">|</span>-f<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">force</span>=<span style="color: #c20cb9; font-weight: bold;">yes</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; --noforce<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">force</span>=no<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; --quiet<span style="color: #000000; font-weight: bold;">|</span>-q<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">quiet</span>=<span style="color: #c20cb9; font-weight: bold;">yes</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; --verbose<span style="color: #000000; font-weight: bold;">|</span>-v<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">quiet</span>=no<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; --help<span style="color: #000000; font-weight: bold;">|</span>-h<span style="color: #000000; font-weight: bold;">|</span>-<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #cc0000; font-style: italic;">&lt;&lt; EOT<br />
Usage: $0 [options] &lt;url&gt; ...<br />
Options:<br />
&nbsp; &nbsp; --force &nbsp; Force cache refresh<br />
&nbsp; &nbsp; --verbose Be noisy<br />
<br />
EOT</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${args}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">args</span>=<span style="color: #ff0000;">&quot;$1&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">args</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">${args}</span> $1&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">esac</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">shift</span><br />
<span style="color: #000000; font-weight: bold;">done</span><br />
<span style="color: #000000; font-weight: bold;">set</span> <span style="color: #660033;">--</span> <span style="color: #800000;">${args}</span><br />
<br />
<br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;You need to give a base url on the command line!&quot;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #007800;">host</span>=ac.dyn.flirble.org<br />
<span style="color: #007800;">proxies</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>host <span style="color: #800000;">${host}</span>. <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sort</span> <span style="color: #660033;">-u</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-v</span> IPv6 <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'/address/{print $4;}'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${proxies}</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Can't resolve proxies, <span style="color: #007800;">${host}</span> is empty!&quot;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #7a0874; font-weight: bold;">echo</span> Proxies to refresh: <span style="color: #800000;">${proxies}</span><br />
<br />
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">no_proxy</span>=<br />
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">NO_PROXY</span>=<br />
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">http_proxy</span>=<br />
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">HTTP_PROXY</span>=<br />
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">ftp_proxy</span>=<br />
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">FTP_PROXY</span>=<br />
<br />
<span style="color: #007800;">cache_opt</span>=<span style="color: #ff0000;">&quot;--header=Pragma:max-age=0 --header=Cache-Control:max-age=0&quot;</span><br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${force}</span>&quot;</span> = <span style="color: #c20cb9; font-weight: bold;">yes</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #007800;">cache_opt</span>=<span style="color: #ff0000;">&quot;--no-cache&quot;</span><br />
<br />
<span style="color: #007800;">quiet_opt</span>=<br />
<span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${quiet}</span>&quot;</span> = <span style="color: #c20cb9; font-weight: bold;">yes</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #007800;">quiet_opt</span>=<span style="color: #ff0000;">&quot;--no-verbose --progress=dot&quot;</span><br />
<br />
<span style="color: #007800;">other_opt</span>=<span style="color: #ff0000;">&quot;--user-agent=tfo-prefetch --recursive --no-directories --no-parent --delete-after&quot;</span><br />
<span style="color: #000000; font-weight: bold;">for</span> url <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #007800;">$*</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> proxy <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${proxies}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">http_proxy</span>=http:<span style="color: #000000; font-weight: bold;">//</span><span style="color: #800000;">${proxy}</span>:<span style="color: #000000;">80</span><span style="color: #000000; font-weight: bold;">/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">HTTP_PROXY</span>=<span style="color: #800000;">${http_proxy}</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">tmpdir</span>=<span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>force-cache-load<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${tmpdir}</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #660033;">-p</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${tmpdir}</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${tmpdir}</span>&quot;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">wget</span> <span style="color: #800000;">${cache_opt}</span> <span style="color: #800000;">${quiet_opt}</span> <span style="color: #800000;">${other_opt}</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${url}</span>&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">done</span><br />
<span style="color: #000000; font-weight: bold;">done</span></div></td></tr></tbody></table></div>
<h3>Other thoughts</h3>
<p>And that&#8217;s my poor-guys CDN. It does have limitations, of course. It does not replace origin-server resilience. The reverse-proxy, if it follows RFCs, will frequently re-validate cached objects and if it cannot reach the origin server, will say so. There are tweaks to overcome this but they can have side effects. And there&#8217;s of course the issue that the net bandwidth benefit from using a reverse-proxy only comes from cacheable objects, but since images are generally the larger items and generally static, the benefit should be there.</p>
<p>If you&#8217;re using something like WordPress and one of the caching plugins, they will make pages look like static html to unregistered users and you may get a caching benefit there, but note that this means that any other plugins have to work well with a static page (server-side functionality is limited on a static cached page!)</p>
<p>It works for me, for now. YMMV.</p>

<div class='amazonpress'><h2>Related Reading</h2>
<div class='product'><a href='http://www.amazon.com/Pro-DNS-BIND-Ron-Aitchison/dp/1430230487?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1430230487' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/517Lod%2BesxL._SL160_.jpg' class='amazonpress-product-image' alt='Pro DNS and BIND 10' title='Pro DNS and BIND 10' /></a>
</div><div class='product'><a href='http://www.amazon.com/DNS-BIND-IPv6-Cricket-Liu/dp/1449305199?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=546246187-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1449305199' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51q2kcB94TL._SL160_.jpg' class='amazonpress-product-image' alt='DNS and BIND on IPv6' title='DNS and BIND on IPv6' /></a>
</div><div class='product'><a href='http://www.amazon.com/Internet-Mail-Mixed-Mode-Surveys-Tailored/dp/0471698687?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0471698687' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/41FLGE8Y9NL._SL160_.jpg' class='amazonpress-product-image' alt='Internet, Mail, and Mixed-Mode Surveys: The Tailored Design Method' title='Internet, Mail, and Mixed-Mode Surveys: The Tailored Design Method' /></a>
</div><div class='product'><a href='http://www.amazon.com/bash-Pocket-Reference-OReilly/dp/1449387888?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1449387888' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51iiAuf7pAL._SL160_.jpg' class='amazonpress-product-image' alt='bash Pocket Reference (Pocket Reference (O&#039;Reilly))' title='bash Pocket Reference (Pocket Reference (O&#039;Reilly))' /></a>
</div><div class='product'><a href='http://www.amazon.com/2009-2014-Outlook-Delivery-Networks-Services/dp/B001QLZY26?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B001QLZY26' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51PCN3y8wVL._SL160_.jpg' class='amazonpress-product-image' alt='The 2009-2014 Outlook for Video Content Delivery (CDN) Networks and Services in Greater China' title='The 2009-2014 Outlook for Video Content Delivery (CDN) Networks and Services in Greater China' /></a>
</div><div class='product'><a href='http://www.amazon.com/DNS-Windows-Server-2003-Cricket/dp/0596005628?SubscriptionId=0H3J4DB1NS1S9SS9FN82&tag=clblog01-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=0596005628' target='_blank' rel='nofollow'><img src='http://ecx.images-amazon.com/images/I/51UlkIAmGXL._SL160_.jpg' class='amazonpress-product-image' alt='DNS on Windows Server 2003' title='DNS on Windows Server 2003' /></a>
</div></div>]]></content:encoded>
			<wfw:commentRss>http://blog.flirble.org/2010/10/19/poor-guys-cdn/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

