<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Jonathan Perkin</title>
    <link>http://www.perkin.org.uk/</link>
    <atom:link href="http://www.perkin.org.uk/rss.xml" rel="self" type="application/rss+xml" />
    <description>learn | understand | share</description>
    <language>en-gb</language>
    <pubDate>Thu, 02 May 2013 21:07:40 +0100</pubDate>
    <lastBuildDate>Thu, 02 May 2013 21:07:40 +0100</lastBuildDate>

    
    <item>
      <title>What's new in pkgsrc-2013Q1</title>
      <link>http://www.perkin.org.uk/posts/whats-new-in-pkgsrc-2013Q1.html</link>
      <pubDate>Mon, 15 Apr 2013 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/whats-new-in-pkgsrc-2013Q1.html</guid>
      <description>&lt;p&gt;The latest branch of &lt;a href='http://www.pkgsrc.org/'&gt;pkgsrc&lt;/a&gt; was released at the beginning of April, and binary packages for SmartOS/illumos and OSX are now available.&lt;/p&gt;

&lt;p&gt;Instructions for installing, as well as a list of the major new features in pkgsrc-2013Q1 are below.&lt;/p&gt;

&lt;h2 id='installing'&gt;Installing&lt;/h2&gt;

&lt;p&gt;The instructions are similar to previous branches.&lt;/p&gt;

&lt;h3 id='smartosillumos'&gt;SmartOS/illumos&lt;/h3&gt;

&lt;p&gt;SmartOS users are encouraged to use our pre-built machine images, and installing your choice of base/standard image with version &lt;code&gt;13.1.x&lt;/code&gt; (available very soon) will get you a pkgsrc-2013Q1 based image.&lt;/p&gt;

&lt;p&gt;For general illumos users or SmartOS users who want access to a full package set, the instructions are below:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; curl http://pkgsrc.smartos.org/packages/illumos/bootstrap/bootstrap-2013Q1-illumos.tar.gz | gtar -zxpf - -C /
&lt;span class='gp'&gt;#&lt;/span&gt; &lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/opt/pkg/sbin:/opt/pkg/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;
&lt;span class='gp'&gt;#&lt;/span&gt; pkgin -y update
&lt;span class='gp'&gt;#&lt;/span&gt; pkgin avail | wc -l
&lt;span class='go'&gt;    9842&lt;/span&gt;
&lt;span class='gp'&gt;#&lt;/span&gt; pkgin search &amp;lt;package&amp;gt;
&lt;span class='gp'&gt;#&lt;/span&gt; pkgin -y install &amp;lt;package&amp;gt; &amp;lt;package...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='osx'&gt;OSX&lt;/h3&gt;

&lt;p&gt;Beginning with pkgsrc-2013Q1 I will now be providing regular builds for OSX. Again, the instructions are similar to those &lt;a href='/posts/7000-packages-for-osx-lion.html'&gt;previously provided&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These packages are built on OSX Leopard (10.5) but use the &lt;code&gt;PREFER_PKGSRC&lt;/code&gt; mechanism to ensure that they are portable across OSX releases, and have been successfully tested on OSX Lion (10.7).&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; curl http://pkgsrc.smartos.org/packages/Darwin/bootstrap/bootstrap-2013Q1-Darwin.tar.gz | sudo gnutar -zxpf - -C /
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/usr/pkg/sbin:/usr/pkg/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; sudo pkgin -y update
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin avail | wc -l
&lt;span class='go'&gt;    8108&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin search &amp;lt;package&amp;gt;
&lt;span class='gp'&gt;$&lt;/span&gt; sudo pkgin -y install &amp;lt;package&amp;gt; &amp;lt;package...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='whats_new'&gt;What&amp;#8217;s New&lt;/h2&gt;

&lt;p&gt;As usual there were many hundreds of changes which went into this quarterly release of pkgsrc. Here are some of the more interesting and useful changes.&lt;/p&gt;

&lt;h3 id='openssl_101_with_aesni_support'&gt;OpenSSL 1.0.1 with AES-NI support&lt;/h3&gt;

&lt;p&gt;OpenSSL has been upgraded from the 0.9.8 series to the 1.0.1 series. The driving reason to pursue this upgrade was to take advantage of AES-NI support which significantly improves crypto performance on Intel CPUs which provide that feature.&lt;/p&gt;

&lt;p&gt;On my OSX 10.7 Core i7 laptop the numbers below speak for themselves:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;: /usr/bin/openssl &amp;#39;OpenSSL 0.9.8r 8 Feb 2011&amp;#39;&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; openssl speed -evp aes-128-cbc
&lt;span class='go'&gt;  type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes&lt;/span&gt;
&lt;span class='go'&gt;  aes-128-cbc     157297.05k   173874.73k   176805.45k   177719.17k   179441.78k&lt;/span&gt;

&lt;span class='go'&gt;: pkgsrc openssl &amp;#39;OpenSSL 1.0.1e 11 Feb 2013&amp;#39;&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; openssl speed -evp aes-128-cbc
&lt;span class='go'&gt;  type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes&lt;/span&gt;
&lt;span class='go'&gt;  aes-128-cbc     643315.29k   685811.37k   696899.67k   699977.39k   693968.90k&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;A pretty significant 4x improvement for many hundreds of applications which use OpenSSL for crypto.&lt;/p&gt;

&lt;h3 id='gcc_go_support_for_smartosillumos'&gt;GCC Go support for SmartOS/illumos&lt;/h3&gt;

&lt;p&gt;&lt;a href='http://golang.org/'&gt;Go&lt;/a&gt; is a reasonably new programming language from Google that a number of our users have asked us to support, so we are pleased to announce that beginning with pkgsrc-2013Q1 you will be able to use the &lt;code&gt;gccgo&lt;/code&gt; front-end to compile and run Go applications on SmartOS.&lt;/p&gt;

&lt;p&gt;You simply compile the go source code as you would for any other language that GCC supports, for example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; pkgin -y install gcc47

&lt;span class='go'&gt;: /opt/pkg for the illumos package set, /opt/local for SmartOS datasets..&lt;/span&gt;
&lt;span class='gp'&gt;#&lt;/span&gt; &lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/opt/pkg/gcc47/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;

&lt;span class='gp'&gt;#&lt;/span&gt; gccgo app.go -o app
&lt;span class='gp'&gt;#&lt;/span&gt; ./app
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='networking_utilities_on_smartos'&gt;Networking utilities on SmartOS&lt;/h3&gt;

&lt;p&gt;Thanks to initial work by &lt;a href='http://twitter.com/postwait'&gt;@postwait&lt;/a&gt; there is now proper Zone support in libpcap, which has opened up the possibility to run a number of networking utilities in Joyent SmartMachines.&lt;/p&gt;

&lt;p&gt;Yes, this means you can finally run &lt;code&gt;tcpdump&lt;/code&gt; instead of &lt;code&gt;snoop&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One of my favourites is &lt;code&gt;trafshow&lt;/code&gt; which is a top-like interface for network, and looks like this:&lt;/p&gt;
&lt;div class='postimg'&gt;
  &lt;img alt='trafshow screenshot' src='/files/images/trafshow.png' /&gt;
&lt;/div&gt;
&lt;p&gt;Alternatively you can try &lt;code&gt;nicstat&lt;/code&gt; for a more &lt;code&gt;{io,mp,vm}stat&lt;/code&gt; style display.&lt;/p&gt;

&lt;h3 id='major_package_versions'&gt;Major package versions&lt;/h3&gt;

&lt;p&gt;As usual there was also a slew of version updates, and the most notable package versions are listed below. These of course are not exhaustive lists.&lt;/p&gt;

&lt;p&gt;Development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clang 3.2&lt;/li&gt;

&lt;li&gt;GCC 4.7.2&lt;/li&gt;

&lt;li&gt;Git 1.8.1.5&lt;/li&gt;

&lt;li&gt;Mercurial 2.5.2&lt;/li&gt;

&lt;li&gt;Subversion 1.6.20, 1.7.8&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Languages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lua 5.1.15&lt;/li&gt;

&lt;li&gt;Node.js 0.8.23, 0.10.2&lt;/li&gt;

&lt;li&gt;Ocaml 4.00.1&lt;/li&gt;

&lt;li&gt;Oracle JRE/JDK 6.0.37, 7.0.15&lt;/li&gt;

&lt;li&gt;Perl 5.16.2&lt;/li&gt;

&lt;li&gt;PHP 5.3.23, 5.4.13&lt;/li&gt;

&lt;li&gt;Python 2.6.8, 2.7.3, 3.1.5, 3.2.3, 3.3.0&lt;/li&gt;

&lt;li&gt;R 2.15.1&lt;/li&gt;

&lt;li&gt;Ruby 1.8.7.371, 1.9.3p392&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Web Stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apache 1.3.42, 2.0.64, 2.2.24, 2.4.4&lt;/li&gt;

&lt;li&gt;CouchDB 1.2.1&lt;/li&gt;

&lt;li&gt;MongoDB 2.2.2&lt;/li&gt;

&lt;li&gt;MySQL 5.0.96, 5.1.67, 5.5.30, 5.6.10&lt;/li&gt;

&lt;li&gt;Nginx 1.2.7, 1.3.14&lt;/li&gt;

&lt;li&gt;PostgreSQL 8.3.23, 8.4.17, 9.0.13, 9.1.9, 9.2.4&lt;/li&gt;

&lt;li&gt;Riak 1.2.1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Desktop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;evilwm 1.1.0&lt;/li&gt;

&lt;li&gt;GNOME 2.32.1, 3.6.2&lt;/li&gt;

&lt;li&gt;KDE 3.5.10, 4.8.4&lt;/li&gt;

&lt;li&gt;XFCE 4.6.1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Installing SVR4 packages on SmartOS</title>
      <link>http://www.perkin.org.uk/posts/installing-svr4-packages-on-smartos.html</link>
      <pubDate>Tue, 19 Mar 2013 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/installing-svr4-packages-on-smartos.html</guid>
      <description>&lt;p&gt;Up until and including Solaris 10 the default packaging tools on Solaris were the historical SVR4 &lt;code&gt;pkg*&lt;/code&gt; commands. First written in the early 1980s they were standard across commercial Unix systems and provided a simplistic interface to installing and removing binary packages.&lt;/p&gt;

&lt;p&gt;With the introduction of IPS in OpenSolaris and beyond they have been mostly consigned to history, however there is still software provided for Solaris which is only available in the &lt;code&gt;.pkg&lt;/code&gt; format, and thus it is useful to still be able to handle them.&lt;/p&gt;

&lt;p&gt;Whilst the &lt;code&gt;pkg*&lt;/code&gt; tools continue to be maintained in illumos and are provided by various distributions, they are not all provided in SmartOS. There are a few reasons for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;SmartOS has a different design to other illumos distributions, and some key differences such as a read-only /usr mean that some packages will simply break in unexpected ways.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;SmartOS is designed to be a slimmed-down distribution providing only that which is necessary for the majority of our users and use cases. Including the SVR4 tools and metadata would bloat the system.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;SVR4 packages are often available only for older versions of Solaris, and whilst the excellent ABI compatability in Solaris means that the binaries themselves will often function correctly, the package may not support newer features such as SMF, or again make assumptions about the system which could result in irrevocable damage.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;SmartOS uses pkgsrc to manage third-party software, and we believe it is better to convert SVR4 packages to pkgsrc format so that all packages on the system can be managed with a single toolset.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, we do continue to ship the &lt;code&gt;pkgtrans&lt;/code&gt; utility with SmartOS, and this is our gateway into converting SVR4 packages into more useful formats. The rest of this post will explore how we can do that.&lt;/p&gt;

&lt;h2 id='unpacking_svr4_packages'&gt;Unpacking SVR4 packages&lt;/h2&gt;

&lt;p&gt;Let&amp;#8217;s start with an example SVR4 package and unpack it to see what it contains. I&amp;#8217;m going to use Riak, a popular open source database as the example package.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;: Download the Solaris 10 SVR4 package from http://docs.basho.com/riak/latest/downloads/&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; curl -Os http://s3.amazonaws.com/downloads.basho.com/riak/1.3/1.3.0/solaris/10/BASHOriak-1.3.0-1-Solaris10-i386.pkg.gz

&lt;span class='go'&gt;: Decompress it&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; gzip -d BASHOriak-1.3.0-1-Solaris10-i386.pkg.gz

&lt;span class='go'&gt;: Use pkgtrans to unpack it into /var/tmp/BASHOriak&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgtrans BASHOriak-1.3.0-1-Solaris10-i386.pkg /var/tmp all
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;SVR4 packages can contain multiple sub-packages, and so the &amp;#8216;all&amp;#8217; is necessary to unpack everything in the archive. If we didn&amp;#8217;t specify &amp;#8216;all&amp;#8217;, we would have seen:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkgtrans BASHOriak-1.3.0-1-Solaris10-i386.pkg /var/tmp

&lt;span class='go'&gt;The following packages are available:&lt;/span&gt;
&lt;span class='go'&gt;  1  BASHOriak     riak&lt;/span&gt;
&lt;span class='go'&gt;                   (i386) 1.3.0-1&lt;/span&gt;

&lt;span class='go'&gt;Select package(s) you wish to process (or &amp;#39;all&amp;#39; to process&lt;/span&gt;
&lt;span class='go'&gt;all packages). (default: all) [?,??,q]:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So whilst we could have specified &amp;#8216;riak&amp;#8217;, we can always use &amp;#8216;all&amp;#8217; to avoid having to first look at the package to see what sub-packages it contains.&lt;/p&gt;

&lt;p&gt;We now have an unpacked package, let&amp;#8217;s go through what it contains.&lt;/p&gt;

&lt;h3 id='_subdirectory'&gt;&lt;code&gt;install&lt;/code&gt; sub-directory&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;install/&lt;/code&gt; directory contains some files and scripts:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; ls -l install/
&lt;span class='go'&gt;total 29&lt;/span&gt;
&lt;span class='go'&gt;-rw-------   1 admin    deniedssh   10175 Feb 19 15:17 copyright&lt;/span&gt;
&lt;span class='go'&gt;-rw-------   1 admin    deniedssh     214 Feb 19 15:17 depend&lt;/span&gt;
&lt;span class='go'&gt;-rwx------   1 admin    deniedssh     438 Feb 19 15:17 i.preserve&lt;/span&gt;
&lt;span class='go'&gt;-rwx------   1 admin    deniedssh     339 Feb 19 15:17 preinstall&lt;/span&gt;
&lt;span class='go'&gt;-rwx------   1 admin    deniedssh     469 Feb 19 15:17 r.preserve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;copyright&lt;/code&gt; is self-explanatory, and is normally displayed when using the &lt;code&gt;pkgadd&lt;/code&gt; command to let the admin know what they are agreeing to.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;code&gt;depend&lt;/code&gt; is a list of other SVR4 packages that this one depends upon. In this case they are:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; cat install/depend
&lt;span class='gp'&gt;#&lt;/span&gt; Same dependencies as Erlang
&lt;span class='go'&gt;P SUNWlibmsr    Math &amp;amp; Microtasking Libraries (Root)&lt;/span&gt;
&lt;span class='go'&gt;P SUNWlibms     Math &amp;amp; Microtasking Libraries (Usr)&lt;/span&gt;
&lt;span class='go'&gt;P SUNWopensslr  OpenSSL (Root)&lt;/span&gt;
&lt;span class='go'&gt;P SUNWopenssl-libraries OpenSSL Libraries (Usr)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As this package is originally from Solaris 10 there is a chance that dependencies could cause issues. For example, in SmartOS we have updated OpenSSL to 1.0.x. Additionally, if a third-party dependency was required (i.e. one not beginning with &lt;code&gt;SUNW&lt;/code&gt;) then naturally you would need to recursively apply this entire procedure to each dependency.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;i.preserve&lt;/code&gt; and &lt;code&gt;r.preserve&lt;/code&gt; are scripts executed during install (&lt;code&gt;i.&lt;/code&gt;) and removal (&lt;code&gt;r.&lt;/code&gt;). The ones for Riak simply try to retain modified files from an existing install, so we will ignore these as pkgsrc handles that by default.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;code&gt;preinstall&lt;/code&gt; is, as the name suggests, a script which is executed prior to installing the package. In Riak&amp;#8217;s case it is used to create the &amp;#8216;riak&amp;#8217; user and group if they do not already exist.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='id1'&gt;&lt;code&gt;pkginfo&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;This provides some basic metadata about the package. The main bits we care about are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ARCH=i386&lt;/code&gt;. As long as the package only depends upon libraries provided by the base OS (&lt;code&gt;SUNW*&lt;/code&gt;) then it shouldn&amp;#8217;t matter whether &lt;code&gt;ARCH&lt;/code&gt; is 32-bit or 64-bit. However, if it requires third-party dependencies then you need to ensure that the correct ABI is provided.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;code&gt;BASEDIR=/opt&lt;/code&gt;. This is where the package would be installed by the &lt;code&gt;pkgadd&lt;/code&gt; tool.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;code&gt;DESC=...&lt;/code&gt;. This would be output by the legacy &lt;code&gt;pkginfo&lt;/code&gt; command, and we will re-use this text for our &lt;code&gt;pkg_info&lt;/code&gt; description.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;code&gt;VERSION=1.3.0-1&lt;/code&gt;. Self-explanatory.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='id2'&gt;&lt;code&gt;pkgmap&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;This is somewhat equivalent to the pkgsrc &lt;code&gt;PLIST&lt;/code&gt; file and is a record of all the files the package provides, however it also includes file permissions and a basic checksum:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; less pkgmap
&lt;span class='go'&gt;: 1 112659&lt;/span&gt;
&lt;span class='go'&gt;1 i copyright 10175 24223 1361287043&lt;/span&gt;
&lt;span class='go'&gt;1 i depend 214 18268 1361287043&lt;/span&gt;
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;span class='go'&gt;1 d none riak 0700 riak riak&lt;/span&gt;
&lt;span class='go'&gt;1 d none riak/bin 0700 riak riak&lt;/span&gt;
&lt;span class='go'&gt;1 f none riak/bin/riak 0755 riak riak 9041 51698 1361286795&lt;/span&gt;
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;span class='go'&gt;1 e preserve riak/etc/app.config 0600 riak riak 14214 8625 1361286647&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The last two lines, the important fields are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;i&lt;/code&gt; is an SVR4 metadata file, &lt;code&gt;f&lt;/code&gt; or &lt;code&gt;d&lt;/code&gt; denote whether it is a file or a directory, &lt;code&gt;e&lt;/code&gt; are configuration files.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;code&gt;none&lt;/code&gt; means no special handling, &lt;code&gt;preserve&lt;/code&gt; does just that, and the next field is the full path relative to &lt;code&gt;reloc/&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;code&gt;0700&lt;/code&gt; and &lt;code&gt;0755&lt;/code&gt; are the file/directory permissions&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;code&gt;riak riak&lt;/code&gt; are the user and group ownership&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will need to ensure at least the file entries are handled correctly.&lt;/p&gt;

&lt;h3 id='_subdirectory'&gt;&lt;code&gt;reloc/&lt;/code&gt; sub-directory&lt;/h3&gt;

&lt;p&gt;This directory contains the binaries etc. which make up the actual package. The contents of this directory would normally be installed under &lt;code&gt;BASEDIR&lt;/code&gt; from the &lt;code&gt;pkginfo&lt;/code&gt; file, so in Riak&amp;#8217;s case:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;: This..&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; ls reloc
&lt;span class='go'&gt;riak&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; ls reloc/riak
&lt;span class='go'&gt;bin         erts-5.9.1  etc         lib         releases&lt;/span&gt;

&lt;span class='go'&gt;: ..would result in this&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; ls /opt/riak
&lt;span class='go'&gt;bin         erts-5.9.1  etc         lib         releases&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This concludes the examination of the SVR4 package. Let&amp;#8217;s turn it into a useful pkgsrc package.&lt;/p&gt;

&lt;h2 id='creating_pkgsrc_binary_package'&gt;Creating pkgsrc binary package&lt;/h2&gt;

&lt;p&gt;For more information on creating binary pkgsrc packages from scratch, see &lt;a href='/posts/creating-local-smartos-packages.html'&gt;this post&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id='pkgsrc_metadata'&gt;pkgsrc metadata&lt;/h3&gt;

&lt;p&gt;Create the necessary pkgsrc metadata files.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; mkdir /var/tmp/pkgsrc-riak
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /var/tmp/pkgsrc-riak

&lt;span class='go'&gt;: Standard build-info section.  Change MACHINE_ARCH to x86_64 if you are&lt;/span&gt;
&lt;span class='go'&gt;: using a base64 image.&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; cat &amp;gt;build-info &amp;lt;&amp;lt;EOF
&lt;span class='go'&gt;MACHINE_ARCH=i386&lt;/span&gt;
&lt;span class='go'&gt;OPSYS=SunOS&lt;/span&gt;
&lt;span class='go'&gt;OS_VERSION=5.11&lt;/span&gt;
&lt;span class='go'&gt;PKGTOOLS_VERSION=20091115&lt;/span&gt;
&lt;span class='go'&gt;EOF&lt;/span&gt;

&lt;span class='go'&gt;: Generate comment file directly from the DESC field in pkginfo&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; awk -F&lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/DESC/ {print $2}&amp;#39;&lt;/span&gt; &amp;lt; /var/tmp/BASHOriak/pkginfo &amp;gt;comment

&lt;span class='go'&gt;: Generate PLIST directly from pkgmap&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; awk &lt;span class='s1'&gt;&amp;#39;$2 ~ /[ef]/ {print $4}&amp;#39;&lt;/span&gt; &amp;lt; /var/tmp/BASHOriak/pkgmap &amp;gt;plist

&lt;span class='go'&gt;: For now just re-use DESC for the description file, however it would normally&lt;/span&gt;
&lt;span class='go'&gt;: be longer&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; cp comment descr
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='pkgsrc_install_script'&gt;pkgsrc INSTALL script&lt;/h3&gt;

&lt;p&gt;To handle the Riak preinstall script, we will create a pkgsrc &lt;code&gt;INSTALL&lt;/code&gt; script.&lt;/p&gt;

&lt;p&gt;The existing script can be mostly used as-is, we just need to put the entire contents of &lt;code&gt;preinstall&lt;/code&gt; inside a &lt;code&gt;PRE-INSTALL&lt;/code&gt; case statement so that it is executed prior to installing the package:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;: Start with the existing preinstall script&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; cp /var/tmp/BASHOriak/install/preinstall inst

&lt;span class='go'&gt;: Alter the script to create the &amp;#39;riak&amp;#39; user/group during PRE-INSTALL, and&lt;/span&gt;
&lt;span class='go'&gt;: after install to chown everything to &amp;#39;riak&amp;#39; (which &lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; vi inst

&lt;span class='go'&gt;PKGNAME=&amp;quot;$1&amp;quot;&lt;/span&gt;
&lt;span class='go'&gt;STAGE=&amp;quot;$2&amp;quot;&lt;/span&gt;

&lt;span class='go'&gt;case ${STAGE} in&lt;/span&gt;
&lt;span class='go'&gt;PRE-INSTALL)&lt;/span&gt;
&lt;span class='go'&gt;	# Existing preinstall script goes here, changing /opt references&lt;/span&gt;
&lt;span class='go'&gt;	# to $PKG_PREFIX&lt;/span&gt;
&lt;span class='go'&gt;	;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If we recall from the &lt;code&gt;pkgmap&lt;/code&gt; file, the entries there contained a user/group that each file should be owned by, and we can handle that in the &lt;code&gt;INSTALL&lt;/code&gt; script too with a &lt;code&gt;POST-INSTALL&lt;/code&gt; action:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;POST-INSTALL)&lt;/span&gt;
&lt;span class='go'&gt;	chown -R riak:riak ${PKG_PREFIX}/riak&lt;/span&gt;
&lt;span class='go'&gt;	;;&lt;/span&gt;
&lt;span class='go'&gt;esac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='pkgsrc_files'&gt;pkgsrc files&lt;/h3&gt;

&lt;p&gt;First we simply copy everything from the &lt;code&gt;reloc/&lt;/code&gt; directory to a &lt;code&gt;files/&lt;/code&gt; directory we will use for pkgsrc:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; mkdir files
&lt;span class='gp'&gt;$&lt;/span&gt; rsync -a /var/tmp/BASHOriak/reloc/ files/
&lt;span class='gp'&gt;$&lt;/span&gt; chown -R root:root files
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Next we can use the &lt;code&gt;pkgmap&lt;/code&gt; file to ensure that the file modes are set correctly with a quick and dirty script:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='k'&gt;while &lt;/span&gt;&lt;span class='nb'&gt;read &lt;/span&gt;line
&lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; -- &lt;span class='nv'&gt;$line&lt;/span&gt;
    &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;$3&amp;quot;&lt;/span&gt; in
    &lt;span class='o'&gt;[&lt;/span&gt;def&lt;span class='o'&gt;])&lt;/span&gt;
        chmod &lt;span class='nv'&gt;$5&lt;/span&gt; files/&lt;span class='nv'&gt;$4&lt;/span&gt;
        ;;
    &lt;span class='k'&gt;esac&lt;/span&gt;
&lt;span class='k'&gt;done&lt;/span&gt; &amp;lt; /var/tmp/BASHOriak/pkgmap
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='create_the_package'&gt;Create the package&lt;/h3&gt;

&lt;p&gt;We should now have everything necessary to create a binary package, taking the version from the &lt;code&gt;pkgmap&lt;/code&gt; file.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkg_create -B build-info -c comment -d descr -f plist -I /opt/local -i inst -p files -U riak-1.3.0.tgz
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='testing'&gt;Testing&lt;/h2&gt;

&lt;p&gt;If all went well then we should be able to install the package:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkg_add riak-1.3.0.tgz
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and we will find it under &lt;code&gt;/opt/local/riak&lt;/code&gt; as expected. If we try to run the binary, we get:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; /opt/local/riak/bin/riak
&lt;span class='go'&gt;/opt/local/riak/bin/riak: line 30: whoami: not found&lt;/span&gt;
&lt;span class='go'&gt;sudo doesn&amp;#39;t appear to be installed and your EUID isn&amp;#39;t riak&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This nicely proves my earlier point about packages often not working unmodified on SmartOS, in this case because &lt;code&gt;whoami&lt;/code&gt; is no longer provided. Thankfully this is an easy fix, and we can simply change &lt;code&gt;whoami&lt;/code&gt; to &lt;code&gt;id -un&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Making that change and trying again, but this time as the riak user:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; su - riak
&lt;span class='gp'&gt;$&lt;/span&gt; /opt/local/riak/bin/riak
&lt;span class='go'&gt;!!!!&lt;/span&gt;
&lt;span class='go'&gt;!!!! WARNING: ulimit -n is 1024; 4096 is the recommended minimum.&lt;/span&gt;
&lt;span class='go'&gt;!!!!&lt;/span&gt;
&lt;span class='go'&gt;Usage: riak {start|stop|restart|reboot|ping|console|attach|chkconfig|escript|version|getpid}&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; /opt/local/riak/bin/riak start
&lt;span class='go'&gt;!!!!&lt;/span&gt;
&lt;span class='go'&gt;!!!! WARNING: ulimit -n is 1024; 4096 is the recommended minimum.&lt;/span&gt;
&lt;span class='go'&gt;!!!!&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pgrep -fl riak
&lt;span class='go'&gt;20628 /opt/local/riak/erts-5.9.1/bin/epmd -daemon&lt;/span&gt;
&lt;span class='go'&gt;20650 /opt/local/riak/erts-5.9.1/bin/beam.smp -K true -A 64 -W w -- -root /opt/local/&lt;/span&gt;
&lt;span class='go'&gt;20648 /opt/local/riak/erts-5.9.1/bin/run_erl -daemon /tmp//opt/local/riak/ /opt/local&lt;/span&gt;
&lt;span class='go'&gt;20718 /opt/local/riak/lib/os_mon-2.2.9/priv/bin/cpu_sup&lt;/span&gt;
&lt;span class='go'&gt;20716 /opt/local/riak/lib/os_mon-2.2.9/priv/bin/memsup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This seems to work about as well as one can hope, and concludes my basic example.&lt;/p&gt;

&lt;h2 id='further_work'&gt; Further work&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;ve covered the basics here, but there are additional things you could do to tidy up the conversion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Fold the &lt;code&gt;whoami&lt;/code&gt; fix back into the source file and re-generate the package.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Turn this into a real pkgsrc package, which would simplify some areas such as metadata and user creation.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Come up with a script to automate a lot of this work.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Turn the &lt;code&gt;riak&lt;/code&gt; script into an SMF service.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also note that Basho very helpfully already provide a native SmartOS package on their download page, so this example is somewhat pointless, however I hope it has still proven useful ;)&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>SmartOS is Not GNU/Linux</title>
      <link>http://www.perkin.org.uk/posts/smartos-is-not-gnu-linux.html</link>
      <pubDate>Wed, 27 Feb 2013 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/smartos-is-not-gnu-linux.html</guid>
      <description>&lt;p&gt;One of the requests we get from time to time is for SmartOS to look more like GNU/Linux in layout and behaviour. For example, config files in &lt;code&gt;/etc&lt;/code&gt; instead of &lt;code&gt;/opt/local/etc&lt;/code&gt;, binaries under &lt;code&gt;/usr&lt;/code&gt; instead of &lt;code&gt;/opt/local/{s,}bin&lt;/code&gt;, GNU userland by default, etc.&lt;/p&gt;

&lt;p&gt;Whilst we believe in the technical merits of our current implementation and the clean separation and upgrade possibilities it provides, we do recognise that some users just don&amp;#8217;t care about those things and would prefer a system which looks as close to the GNU/Linux environments they are used to.&lt;/p&gt;

&lt;p&gt;Ordinarily this simply wouldn&amp;#8217;t be possible given that &lt;code&gt;/usr&lt;/code&gt; is a read-only mount from the &lt;a href='/posts/smartos-and-the-global-zone.html'&gt;global zone&lt;/a&gt;, however with the highly flexible SmartOS &lt;a href='http://wiki.smartos.org/display/DOC/Zones'&gt;Zones&lt;/a&gt; architecture, coupled with Joyent employing Zones guru &lt;a href='http://wiki.smartos.org/display/DOC/Jerry+Jelinek'&gt;Jerry Jelinek&lt;/a&gt;, we are able to provide you with an option to do exactly this. As Jerry says, at Sun there was even a native Linux brand, so pretty much anything is possible!&lt;/p&gt;

&lt;p&gt;We call it &amp;#8216;SNGL&amp;#8217; (pronounced &amp;#8216;snuggle&amp;#8217;), which is an acronym for &amp;#8216;SmartOS is Not GNU/Linux&amp;#8217;. Currently it is somewhat experimental, but we&amp;#8217;d love for people to try it out and provide feedback.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s how you can get it running.&lt;/p&gt;

&lt;h2 id='install_the_latest_platform'&gt;Install the latest platform&lt;/h2&gt;

&lt;p&gt;You need to be running SmartOS 20130222 or later. Older platforms can be coerced into working, you will just need to work around the lack of &lt;a href='https://github.com/joyent/illumos-joyent/commit/c6920fb1d0f6cd852da06e049631f1ee274b5b9d'&gt;this commit&lt;/a&gt; by creating an empty &lt;code&gt;sngl_base.tar.gz&lt;/code&gt; or so.&lt;/p&gt;

&lt;p&gt;As usual, follow the instructions &lt;a href='http://wiki.smartos.org/display/DOC/Remotely+Upgrading+A+USB+Key+Based+Deployment'&gt;here&lt;/a&gt; to upgrade an existing install.&lt;/p&gt;

&lt;h2 id='get_the_sngl_dataset'&gt;Get the SNGL dataset&lt;/h2&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;: Fetch the dataset image and manifest files.  The image is 107MB.&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; mkdir -p /usbkey/images
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /usbkey/images
&lt;span class='gp'&gt;$&lt;/span&gt; curl -O http://pkgsrc.smartos.org/datasets/sngl-0.99.0.dsmanifest
&lt;span class='gp'&gt;$&lt;/span&gt; curl -O http://pkgsrc.smartos.org/datasets/sngl-0.99.0.zfs.bz2

&lt;span class='go'&gt;: Import it&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; imgadm install -m sngl-0.99.0.dsmanifest -f sngl-0.99.0.zfs.bz2
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='create_a_new_dataset'&gt;Create a new dataset&lt;/h2&gt;

&lt;p&gt;The important point to note here is that &lt;code&gt;brand&lt;/code&gt; is set to &lt;code&gt;sngl&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;: Create a new zone using the dataset (change your json to suit).&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; vmadm create &amp;lt;&amp;lt;EOF
&lt;span class='go'&gt;{&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;brand&amp;quot;: &amp;quot;sngl&amp;quot;,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;image_uuid&amp;quot;: &amp;quot;4bf9530a-7ae5-11e2-bb4e-3bad5fbc3de9&amp;quot;,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;ram&amp;quot;: 256,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;quota&amp;quot;: 10,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;alias&amp;quot;: &amp;quot;sngl-0.99.0&amp;quot;,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;nics&amp;quot;: [&lt;/span&gt;
&lt;span class='go'&gt;    {&lt;/span&gt;
&lt;span class='go'&gt;      &amp;quot;nic_tag&amp;quot;: &amp;quot;admin&amp;quot;,&lt;/span&gt;
&lt;span class='go'&gt;      &amp;quot;ip&amp;quot;: &amp;quot;dhcp&amp;quot;&lt;/span&gt;
&lt;span class='go'&gt;    }&lt;/span&gt;
&lt;span class='go'&gt;  ]&lt;/span&gt;
&lt;span class='go'&gt;}&lt;/span&gt;
&lt;span class='go'&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;At this point you should be able to log in and start using &lt;code&gt;pkgin&lt;/code&gt; etc to install new software (there are over 2,000 packages available) as normal, but notice that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;binaries are running from &lt;code&gt;/usr/bin&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;configuration files are in &lt;code&gt;/etc&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;the default userland tools are GNU variants (&lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt;, &lt;code&gt;awk&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, etc.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For those that are interested, here is some further detail on how this is all implemented.&lt;/p&gt;

&lt;h2 id='brand_configuration'&gt;Brand configuration&lt;/h2&gt;

&lt;p&gt;The main setup is in &lt;code&gt;/usr/lib/brand/sngl&lt;/code&gt;. Firstly, &lt;code&gt;platform.xml&lt;/code&gt; defines the mount points to be used inside the zone, and here you can see how we are able to use &lt;code&gt;/usr&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='xml'&gt;        &lt;span class='nt'&gt;&amp;lt;global_mount&lt;/span&gt; &lt;span class='na'&gt;special=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;/lib&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;directory=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;/system/lib&amp;quot;&lt;/span&gt;
            &lt;span class='na'&gt;opt=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;ro,nodevices&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;lofs&amp;quot;&lt;/span&gt; &lt;span class='nt'&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;global_mount&lt;/span&gt; &lt;span class='na'&gt;special=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;/sbin&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;directory=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;/system/sbin&amp;quot;&lt;/span&gt;
            &lt;span class='na'&gt;opt=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;ro,nodevices&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;lofs&amp;quot;&lt;/span&gt; &lt;span class='nt'&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;global_mount&lt;/span&gt; &lt;span class='na'&gt;special=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;/usr&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;directory=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;/system/usr&amp;quot;&lt;/span&gt;
            &lt;span class='na'&gt;opt=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;ro,nodevices&amp;quot;&lt;/span&gt; &lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;lofs&amp;quot;&lt;/span&gt; &lt;span class='nt'&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We are transplanting the main system directories and mounting them under &lt;code&gt;/system&lt;/code&gt;. This leaves &lt;code&gt;/usr&lt;/code&gt; free for us to write packages to.&lt;/p&gt;

&lt;p&gt;In order to support having the OS under &lt;code&gt;/system&lt;/code&gt; there is some additional configuration in &lt;code&gt;config.xml&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='xml'&gt;        &lt;span class='nt'&gt;&amp;lt;initname&amp;gt;&lt;/span&gt;/system/sbin/init&lt;span class='nt'&gt;&amp;lt;/initname&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;login_cmd&amp;gt;&lt;/span&gt;/system/usr/bin/login -z %Z %u&lt;span class='nt'&gt;&amp;lt;/login_cmd&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;forcedlogin_cmd&amp;gt;&lt;/span&gt;/system/usr/bin/login -z %Z -f %u&lt;span class='nt'&gt;&amp;lt;/forcedlogin_cmd&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;user_cmd&amp;gt;&lt;/span&gt;/system/usr/bin/getent passwd %u&lt;span class='nt'&gt;&amp;lt;/user_cmd&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is where the flexibility of Zones really shines. We are able to redefine the path to init(1M) and others so that the zone can boot correctly.&lt;/p&gt;

&lt;p&gt;In addition, we copy in the &lt;code&gt;crle&lt;/code&gt; configuration files &lt;code&gt;ld.sys.config&lt;/code&gt; and &lt;code&gt;ld.sys64.config&lt;/code&gt; so that binaries will look in &lt;code&gt;/system/usr/lib&lt;/code&gt; for their runtime libraries.&lt;/p&gt;

&lt;h2 id='runtime_and_packages'&gt;Runtime and packages&lt;/h2&gt;

&lt;p&gt;The brand configuration is enough to set the zone up, but in order to make it boot we need additional files available under &lt;code&gt;/usr&lt;/code&gt;, there are simply too many hardcoded paths. For this we just symlink back to &lt;code&gt;/system/usr&lt;/code&gt; from &lt;code&gt;/usr&lt;/code&gt; any files required.&lt;/p&gt;

&lt;p&gt;Finally, we are able to perform a full pkgsrc bulk build with &lt;code&gt;LOCALBASE&lt;/code&gt; set to &lt;code&gt;/usr&lt;/code&gt; within a chroot which emulates this layout, and when those packages are installed they overwrite the compatability symlinks we have configured and replace them with files from the packages.&lt;/p&gt;

&lt;p&gt;Not all symlinks will be overwritten, though, which is why standard SmartOS utilities such as &lt;code&gt;prstat(1M)&lt;/code&gt; are still available, as the symlink for it still exists.&lt;/p&gt;

&lt;h2 id='reporting_issues'&gt;Reporting issues&lt;/h2&gt;

&lt;p&gt;As I mentioned, this is currently experimental, and there will be plenty of problems. However, at least from some initial testing, a reasonable amount of things appear to work fine, and for users who want this particular layout it may be good enough.&lt;/p&gt;

&lt;p&gt;Please feel free to give it a try and report issues against &lt;a href='https://github.com/joyent/pkgsrc/issues'&gt;our GitHub project&lt;/a&gt;. Once we have it working with a reasonable amount of stability we may be able to offer it as an option in the &lt;a href='http://www.joyent.com/'&gt;Joyent Public Cloud&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>SmartOS development preview dataset</title>
      <link>http://www.perkin.org.uk/posts/smartos-development-preview-dataset.html</link>
      <pubDate>Mon, 18 Feb 2013 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/smartos-development-preview-dataset.html</guid>
      <description>&lt;p&gt;The datasets we produce for SmartOS are usually released on a quarterly cadence, matching the upstream pkgsrc release branches. This is often enough to ensure that people can get up-to-date software with all the usual improvements and bug fixes.&lt;/p&gt;

&lt;p&gt;Occasionally though, users want the very latest and don&amp;#8217;t really want to wait for 3 months to get it, and so to satisfy those users who crave the bleeding edge I have produced a new dataset which is based upon pkgsrc trunk.&lt;/p&gt;

&lt;p&gt;The package repository for this dataset will be constantly updated with the very latest that pkgsrc has to offer, and so you will occasionally see breakage as we integrate updates for core libraries and add new features. Think of it as being similar to Debian &amp;#8216;unstable&amp;#8217;, you get the very latest stuff but you may need to do some maintenance every so often.&lt;/p&gt;

&lt;p&gt;Here are some reasons why you may want to use this dataset:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It is based upon the &lt;a href='/posts/multiarch-package-support-in-smartos.html'&gt;multiarch&lt;/a&gt; code, so only one image is necessary. No more needing to decide between the 32-bit or 64-bit options.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;It is a full bulk build, so there are in the region of 9,000 packages to choose from (depending on the current state of pkgsrc trunk).&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;It has all the Joyent specific changes integrated, so that means SMF support for many packages which we have written manifests for, static UID/GID allocation, various improvements, and uses the standard &lt;code&gt;/opt/local&lt;/code&gt; prefix.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;There are some nice improvements only available in pkgsrc trunk, for example OpenSSL 1.0.1e with proper AES-NI support, and libpcap fixes from &lt;a href='http://twitter.com/postwait'&gt;@postwait&lt;/a&gt; with a slew of networking utilities now available and working (these will be documented in a future post).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='how_to_install'&gt;How to install&lt;/h2&gt;

&lt;p&gt;Here is a quick start guide to getting the preview dataset up and running:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;: Fetch the dataset image and manifest files.  The image is 82MB.&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; mkdir -p /usbkey/images
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /usbkey/images
&lt;span class='gp'&gt;$&lt;/span&gt; curl -O http://pkgsrc.smartos.org/datasets/trunk-0.99.0.dsmanifest
&lt;span class='gp'&gt;$&lt;/span&gt; curl -O http://pkgsrc.smartos.org/datasets/trunk-0.99.0.zfs.bz2

&lt;span class='go'&gt;: Import it&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; imgadm install -m trunk-0.99.0.dsmanifest -f trunk-0.99.0.zfs.bz2

&lt;span class='go'&gt;: Create a new zone using the dataset (change your json to suit).&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; vmadm create &amp;lt;&amp;lt;EOF
&lt;span class='go'&gt;{&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;brand&amp;quot;: &amp;quot;joyent&amp;quot;,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;image_uuid&amp;quot;: &amp;quot;c91b3752-79c5-11e2-ad33-67667b9ee2c2&amp;quot;,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;max_physical_memory&amp;quot;: 256,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;alias&amp;quot;: &amp;quot;trunk-0.99.0&amp;quot;,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;nics&amp;quot;: [&lt;/span&gt;
&lt;span class='go'&gt;    {&lt;/span&gt;
&lt;span class='go'&gt;      &amp;quot;nic_tag&amp;quot;: &amp;quot;admin&amp;quot;,&lt;/span&gt;
&lt;span class='go'&gt;      &amp;quot;ip&amp;quot;: &amp;quot;dhcp&amp;quot;&lt;/span&gt;
&lt;span class='go'&gt;    }&lt;/span&gt;
&lt;span class='go'&gt;  ]&lt;/span&gt;
&lt;span class='go'&gt;}&lt;/span&gt;
&lt;span class='go'&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;then login and start using it as you would with any other dataset.&lt;/p&gt;

&lt;h2 id='known_issues'&gt;Known issues&lt;/h2&gt;

&lt;p&gt;With this being a bleeding-edge distribution, there will undoubtedly be problems.The main one I am currently aware of is dependencies upon the GCC runtime from the &lt;code&gt;/opt/pbulk&lt;/code&gt; prefix used to build the packages, which looks like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; pkgin in samba
&lt;span class='go'&gt;calculating dependencies... done.&lt;/span&gt;
&lt;span class='go'&gt;/opt/pbulk/gcc47/lib/./libgcc_s.so.1, needed by samba-3.6.12nb1 is not present in this system.&lt;/span&gt;
&lt;span class='go'&gt;/opt/pbulk/gcc47/lib/./libgcc_s.so.1, needed by tdb-1.2.11 is not present in this system.&lt;/span&gt;
&lt;span class='go'&gt;[...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We are actively working on fixing these dependencies, but in the meantime if you require a package which is broken in this way you can work around it by installing the &lt;code&gt;/opt/pbulk&lt;/code&gt; bootstrap like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; curl http://pkgsrc.smartos.org/packages/SmartOS/bootstrap/bootstrap-pbulk.tar.gz &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='go'&gt;    | gtar -zxf - -C /&lt;/span&gt;
&lt;span class='gp'&gt;#&lt;/span&gt; /opt/pbulk/bin/pkgin -y install gcc47
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The other issue to note is that not all packages have been converted to multiarch. Again we are actively working on this, but it will take some time to go through all of the 12,000 or so packages in pkgsrc.&lt;/p&gt;

&lt;p&gt;If you find any other problems, please feel free to raise them against our GitHub project &lt;a href='https://github.com/joyent/pkgsrc/issues'&gt;here&lt;/a&gt;. Or, even better, follow my guides on &lt;a href='/posts/pkgsrc-on-smartos-zone-creation-and-basic-builds.html'&gt;building&lt;/a&gt; &lt;a href='/posts/pkgsrc-on-smartos-fixing-broken-builds.html'&gt;pkgsrc&lt;/a&gt; (you will want the &lt;code&gt;joyent/release/trunk&lt;/code&gt; branch) and have a go at fixing things yourself, we very much welcome patches and pull requests!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>pkgsrc on SmartOS - fixing broken builds</title>
      <link>http://www.perkin.org.uk/posts/pkgsrc-on-smartos-fixing-broken-builds.html</link>
      <pubDate>Thu, 17 Jan 2013 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/pkgsrc-on-smartos-fixing-broken-builds.html</guid>
      <description>&lt;p&gt;This is the second in a series of posts looking at pkgsrc on SmartOS. In the &lt;a href='/posts/pkgsrc-on-smartos-zone-creation-and-basic-builds.html'&gt;previous post&lt;/a&gt; I got us up and running with building packages. This post will focus on what to do when the build fails.&lt;/p&gt;

&lt;p&gt;Currently pkgsrc is able to build around 9,500 packages on SmartOS, however pkgsrc carries over 12,000 packages in total, so there is a reasonable chance that you will come across a package which will not produce a binary package.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s have a look at some of the most common failure modes and the facilities pkgsrc provides for them to be fixed.&lt;/p&gt;

&lt;h2 id='adjusting_the_environment'&gt;Adjusting the environment&lt;/h2&gt;

&lt;p&gt;Probably the most common failures on Solaris are those caused by incorrect compiler or linker flags, where the author of the software has not taken into account differences across Unix platforms. Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;the usage of &lt;strong&gt;&lt;code&gt;u_int*&lt;/code&gt;&lt;/strong&gt; types (e.g. &lt;strong&gt;&lt;code&gt;u_int32_t&lt;/code&gt;&lt;/strong&gt;) instead of the portable &lt;strong&gt;&lt;code&gt;uint*&lt;/code&gt;&lt;/strong&gt; C99 types (e.g. &lt;strong&gt;&lt;code&gt;uint32_t&lt;/code&gt;&lt;/strong&gt;).&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;missing &lt;strong&gt;&lt;code&gt;-lsocket -lnsl&lt;/code&gt;&lt;/strong&gt; when using the socket interface.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;pkgsrc provides an easy way to pass &lt;strong&gt;&lt;code&gt;CFLAGS&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;LDFLAGS&lt;/code&gt;&lt;/strong&gt; and other common environment variables to the build, and these are often enough to resolve such issues.&lt;/p&gt;

&lt;p&gt;Taking &lt;code&gt;net/nsd&lt;/code&gt; as an example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; &lt;span class='nb'&gt;cd &lt;/span&gt;net/nsd
&lt;span class='gp'&gt;#&lt;/span&gt; bmake package
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;span class='go'&gt;gcc -I/opt/local/include -I/opt/local/include -I. -I. -O -I/opt/local/include -c ./util.c&lt;/span&gt;
&lt;span class='go'&gt;./util.c:745:1: error: unknown type name &amp;#39;u_int32_t&amp;#39;&lt;/span&gt;
&lt;span class='go'&gt;*** [util.o] Error code 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If we edit the Makefile and add the following line below &lt;strong&gt;&lt;code&gt;CONFIGURE_ARGS&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='make'&gt;&lt;span class='nv'&gt;CFLAGS.SunOS&lt;/span&gt;&lt;span class='o'&gt;+=&lt;/span&gt;	-Du_int32_t&lt;span class='o'&gt;=&lt;/span&gt;uint32_t
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;then a rebuild resolves the problem and results in a binary package:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; bmake clean
&lt;span class='gp'&gt;#&lt;/span&gt; bmake package
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;span class='go'&gt;=&amp;gt; Creating binary package /content/packages/All/nsd-3.2.14.tgz&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;By using &lt;code&gt;CFLAGS.SunOS&lt;/code&gt; rather than the global &lt;code&gt;CFLAGS&lt;/code&gt; this is only performed on systems where &lt;code&gt;uname&lt;/code&gt; is &lt;code&gt;SunOS&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can resolve missing libraries in a similar way, taking &lt;code&gt;net/rootprobe&lt;/code&gt; as an example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; &lt;span class='nb'&gt;cd &lt;/span&gt;net/rootprobe
&lt;span class='gp'&gt;#&lt;/span&gt; bmake package
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;span class='go'&gt;gcc -Wl,-R/opt/local/lib  rootprobe.o -o rootprobe&lt;/span&gt;
&lt;span class='go'&gt;Undefined                       first referenced&lt;/span&gt;
&lt;span class='go'&gt; symbol                             in file&lt;/span&gt;
&lt;span class='go'&gt;recv                                rootprobe.o&lt;/span&gt;
&lt;span class='go'&gt;send                                rootprobe.o&lt;/span&gt;
&lt;span class='go'&gt;getsockname                         rootprobe.o&lt;/span&gt;
&lt;span class='go'&gt;socket                              rootprobe.o&lt;/span&gt;
&lt;span class='go'&gt;getdomainname                       rootprobe.o&lt;/span&gt;
&lt;span class='go'&gt;connect                             rootprobe.o&lt;/span&gt;
&lt;span class='go'&gt;recvfrom                            rootprobe.o&lt;/span&gt;
&lt;span class='go'&gt;inet_aton                           rootprobe.o&lt;/span&gt;
&lt;span class='go'&gt;inet_ntoa                           rootprobe.o&lt;/span&gt;
&lt;span class='go'&gt;shutdown                            rootprobe.o&lt;/span&gt;
&lt;span class='go'&gt;ld: fatal: symbol referencing errors. No output written to rootprobe&lt;/span&gt;
&lt;span class='go'&gt;collect2: error: ld returned 1 exit status&lt;/span&gt;
&lt;span class='go'&gt;*** [rootprobe] Error code 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Add the following to the Makefile:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='make'&gt;&lt;span class='nv'&gt;LDFLAGS.SunOS&lt;/span&gt;&lt;span class='o'&gt;+=&lt;/span&gt;	-lsocket -lnsl
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and hey presto, out comes a binary package:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; bmake clean
&lt;span class='gp'&gt;#&lt;/span&gt; bmake package
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;span class='go'&gt;gcc -lsocket -lnsl -Wl,-R/opt/local/lib  rootprobe.o -o rootprobe&lt;/span&gt;
&lt;span class='go'&gt;/bin/rm -f cctldprobe;  ln rootprobe cctldprobe&lt;/span&gt;
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;span class='go'&gt;=&amp;gt; Creating binary package /content/packages/All/rootprobe-200301.tgz&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Not all packages can be fixed directly like this, only those which obey the normal &lt;code&gt;${CC}&lt;/code&gt; and &lt;code&gt;${LD}&lt;/code&gt; environment variables, as pkgsrc creates wrappers for those commands where it can insert these alterations. For packages which directly call e.g. &lt;code&gt;gcc&lt;/code&gt;, some additional digging will be required to see how the arguments can be passed.&lt;/p&gt;

&lt;p&gt;Taking &lt;code&gt;net/3proxy&lt;/code&gt; as an example, the build fails with missing socket libraries:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; &lt;span class='nb'&gt;cd &lt;/span&gt;net/3proxy
&lt;span class='gp'&gt;#&lt;/span&gt; bmake package
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;span class='go'&gt;gcc -opop3p -Wall -O2 -pthread  sockmap.o pop3p.o sockgetchar.o myalloc.o common.o  &lt;/span&gt;
&lt;span class='go'&gt;Undefined                       first referenced&lt;/span&gt;
&lt;span class='go'&gt; symbol                             in file&lt;/span&gt;
&lt;span class='go'&gt;bind                                pop3p.o&lt;/span&gt;
&lt;span class='go'&gt;send                                sockgetchar.o&lt;/span&gt;
&lt;span class='go'&gt;getsockname                         common.o&lt;/span&gt;
&lt;span class='go'&gt;accept                              pop3p.o&lt;/span&gt;
&lt;span class='go'&gt;listen                              pop3p.o&lt;/span&gt;
&lt;span class='go'&gt;gethostbyname                       common.o&lt;/span&gt;
&lt;span class='go'&gt;sendto                              sockmap.o&lt;/span&gt;
&lt;span class='go'&gt;socket                              pop3p.o&lt;/span&gt;
&lt;span class='go'&gt;setsockopt                          pop3p.o&lt;/span&gt;
&lt;span class='go'&gt;connect                             common.o&lt;/span&gt;
&lt;span class='go'&gt;recvfrom                            sockmap.o&lt;/span&gt;
&lt;span class='go'&gt;shutdown                            sockmap.o&lt;/span&gt;
&lt;span class='go'&gt;ld: fatal: symbol referencing errors. No output written to pop3p&lt;/span&gt;
&lt;span class='go'&gt;collect2: error: ld returned 1 exit status&lt;/span&gt;
&lt;span class='go'&gt;*** [pop3p] Error code 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;but adding &lt;code&gt;LDFLAGS.SunOS+= -lsocket -lnsl&lt;/code&gt; to the Makefile as before does not resolve the problem. Delving further into the Makefile we can see that the build is driven from a custom Makefile rather than through autoconf/automake:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='make'&gt;&lt;span class='nv'&gt;MAKE_FILE&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;      Makefile.unix
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and it is there we will need to perform the changes. First, let&amp;#8217;s find the work area, which we can get from the &lt;code&gt;WRKSRC&lt;/code&gt; variable:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; bmake show-var &lt;span class='nv'&gt;VARNAME&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;WRKSRC
&lt;span class='go'&gt;/var/tmp/pkgsrc-build/net/3proxy/work&lt;/span&gt;
&lt;span class='gp'&gt;#&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /var/tmp/pkgsrc-build/net/3proxy/work
&lt;span class='gp'&gt;#&lt;/span&gt; ls -l Makefile.unix 
&lt;span class='go'&gt;-rw-r--r-- 1 11001 10512 675 Apr 30  2005 Makefile.unix&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Picking out the relevant bits from &lt;code&gt;Makefile.unix&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='make'&gt;&lt;span class='nv'&gt;CC&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; gcc
...
&lt;span class='nv'&gt;CFLAGS&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; -Wall -g -O2 -c -pthread -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DWITH_STD_MALLOC -DFD_SETSIZE&lt;span class='o'&gt;=&lt;/span&gt;4096 -DWITH_POLL
...
&lt;span class='nv'&gt;LDFLAGS&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; -Wall -O2 -pthread
...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here, the author has provided no functionality for adding to the environment, and has instead chosen to hardcode a specific compiler and build flags, significantly reducing the portability of their software - good luck to Clang/LLVM or SunStudio users!&lt;/p&gt;

&lt;p&gt;If the author had provided a way in to add to these flags, for example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='make'&gt;&lt;span class='nv'&gt;LDFLAGS&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; -Wall -O2 -pthread &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;USER_LDFLAGS&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;then we could have fixed that in the main pkgsrc &lt;code&gt;Makefile&lt;/code&gt; with&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='make'&gt;&lt;span class='nv'&gt;MAKE_ENV&lt;/span&gt;&lt;span class='o'&gt;+=&lt;/span&gt;	&lt;span class='nv'&gt;USER_LDFLAGS&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-lsocket -lnsl&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;or similar, however we now have no choice but to directly edit &lt;code&gt;Makefile.unix&lt;/code&gt;. Thankfully, pkgsrc provides a couple of ways to easily do this, which we will look at over the next few sections.&lt;/p&gt;

&lt;h2 id='the_substitution_framework'&gt;The substitution framework&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;subst&lt;/code&gt; framework allows basic editing of files within the work area. I will show the solution for the above problem, and then discuss it:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='make'&gt;&lt;span class='cp'&gt;.include &amp;quot;../../mk/bsd.prefs.mk&amp;quot;&lt;/span&gt;
&lt;span class='cp'&gt;.if ${OPSYS} == &amp;quot;SunOS&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;SUBST_CLASSES&lt;/span&gt;&lt;span class='o'&gt;+=&lt;/span&gt;		libs
SUBST_STAGE.libs&lt;span class='o'&gt;=&lt;/span&gt;	pre-build
SUBST_MESSAGE.libs&lt;span class='o'&gt;=&lt;/span&gt;	Adding SunOS socket libraries
SUBST_FILES.libs&lt;span class='o'&gt;=&lt;/span&gt;	Makefile.unix
SUBST_SED.libs&lt;span class='o'&gt;=&lt;/span&gt;		-e &lt;span class='s1'&gt;&amp;#39;/^LDFLAGS/s/$$/ -lsocket -lnsl/&amp;#39;&lt;/span&gt;
&lt;span class='cp'&gt;.endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Firstly, we need to limit this to SunOS systems, else we would break platforms which do not have &lt;code&gt;libsocket&lt;/code&gt; or &lt;code&gt;libnsl&lt;/code&gt;. Including &lt;code&gt;../../mk/bsd.prefs.mk&lt;/code&gt; gives us access to the &lt;code&gt;OPSYS&lt;/code&gt; variable so we can test the platform we are running on.&lt;/p&gt;

&lt;p&gt;Next we set up the substitution framework:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;SUBST_CLASSES&lt;/code&gt;&lt;/strong&gt; creates a new class, which I have named &lt;code&gt;libs&lt;/code&gt;. This class name is then appended to the remaining &lt;code&gt;SUBST_*&lt;/code&gt; variables to assign them to that class.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;SUBST_STAGE&lt;/code&gt;&lt;/strong&gt; defines the make stage when the substitution will be run, and should almost always be &lt;code&gt;pre-build&lt;/code&gt;, to ensure it is done after any configuration stage which could rewrite files itself.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;SUBST_MESSAGE&lt;/code&gt;&lt;/strong&gt; is optional, and is simply a line which will be printed to the user when the substitution takes places.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;SUBST_FILES&lt;/code&gt;&lt;/strong&gt; is a list of files the substitution operates on.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;SUBST_SED&lt;/code&gt;&lt;/strong&gt; is the actual substitution, in the form of a &lt;code&gt;sed(1)&lt;/code&gt; operation. Here we append &lt;code&gt;-lsocket -lnsl&lt;/code&gt; to any line beginning with &lt;code&gt;LDFLAGS&lt;/code&gt;. Note &lt;code&gt;$$&lt;/code&gt; is required to get &lt;code&gt;make&lt;/code&gt; to escape a &lt;code&gt;$&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; bmake clean
&lt;span class='gp'&gt;#&lt;/span&gt; bmake package
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;span class='go'&gt;===&amp;gt; Building for 3proxy-0.5.3.11nb1&lt;/span&gt;
&lt;span class='go'&gt;=&amp;gt; Adding SunOS socket libraries&lt;/span&gt;
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;span class='go'&gt;=&amp;gt; Creating binary package /content/packages/All/3proxy-0.5.3.11nb1.tgz&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Two other &lt;code&gt;subst&lt;/code&gt; features you may want are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;SUBST_VARS.foo= VARNAME&lt;/code&gt;&lt;/strong&gt; is a shortcut for the &lt;code&gt;-e &amp;#39;s,@VARNAME@,${VARNAME},g&amp;#39;&lt;/code&gt; operation, common with autoconf-based packages.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;SUBST_FILTER_CMD.foo= &amp;lt;cmd&amp;gt;&lt;/code&gt;&lt;/strong&gt; allows you to run an arbitrary command, rather than the default of &lt;code&gt;sed&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more information, see the implementation in &lt;code&gt;pkgsrc/mk/subst.mk&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='patches'&gt; Patches&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;CFLAGS&lt;/code&gt;, &lt;code&gt;LDFLAGS&lt;/code&gt; and the substitution framework allow for simple one-liner fixes, often more significant changes are required, and in those cases the only sensible option is to create patches. Thankfully, there are some tools provided in pkgsrc to make this a relatively easy process.&lt;/p&gt;

&lt;p&gt;First, let&amp;#8217;s take a broken package, &lt;code&gt;devel/bglibs&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; &lt;span class='nb'&gt;cd &lt;/span&gt;devel/bglibs
&lt;span class='gp'&gt;#&lt;/span&gt; bmake package
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;span class='go'&gt;./ltcompile net/cork.c&lt;/span&gt;
&lt;span class='go'&gt;net/cork.c: In function &amp;#39;socket_cork&amp;#39;:&lt;/span&gt;
&lt;span class='go'&gt;net/cork.c:39:27: error: &amp;#39;SOL_TCP&amp;#39; undeclared (first use in this function)&lt;/span&gt;
&lt;span class='go'&gt;net/cork.c:39:27: note: each undeclared identifier is reported only once for each function it appears in&lt;/span&gt;
&lt;span class='go'&gt;*** [net/cork.lo] Error code 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;which comes from the following function:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;&lt;span class='cm'&gt;/*&lt;/span&gt;
&lt;span class='cm'&gt; * ..It is known to work on Linux (with the TCP_CORK option) and to at least&lt;/span&gt;
&lt;span class='cm'&gt; * compile on BSD (with the TCP_NOPUSH option).  On OS&amp;#39;s which lack either of&lt;/span&gt;
&lt;span class='cm'&gt; * these two options, this function is essentially a no-op.&lt;/span&gt;
&lt;span class='cm'&gt; */&lt;/span&gt;
&lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='nf'&gt;socket_cork&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;sock&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='p'&gt;{&lt;/span&gt;
&lt;span class='cp'&gt;#if defined(TCP_CORK)&lt;/span&gt;
  &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;flag&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;setsockopt&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sock&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;SOL_TCP&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;TCP_CORK&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;flag&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;sizeof&lt;/span&gt; &lt;span class='n'&gt;flag&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='cp'&gt;#elif defined(TCP_NOPUSH)&lt;/span&gt;
  &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;flag&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;setsockopt&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sock&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;SOL_SOCKET&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;TCP_NOPUSH&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;flag&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;sizeof&lt;/span&gt; &lt;span class='n'&gt;flag&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='cp'&gt;#else&lt;/span&gt;
  &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='cp'&gt;#endif&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Unfortunately, while SmartOS provides the &lt;code&gt;TCP_CORK&lt;/code&gt; flag, it does not understand &lt;code&gt;SOL_TCP&lt;/code&gt;, and so we need to modify the test and add an additional one.&lt;/p&gt;

&lt;p&gt;Before doing this, we should install the &lt;code&gt;pkgtools/pkgdiff&lt;/code&gt; package, which contains a &lt;code&gt;pkgvi&lt;/code&gt; wrapper. This allows you to edit a file, and if you make changes, it will save the resulting diff in the pkgsrc &lt;code&gt;patches&lt;/code&gt; directory ready for use. Much easier than delving into the work area and creating patches yourself.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;: Install via pkgin..&lt;/span&gt;
&lt;span class='gp'&gt;#&lt;/span&gt; pkgin in pkgdiff

&lt;span class='go'&gt;: ..or through pkgsrc&lt;/span&gt;
&lt;span class='gp'&gt;#&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cd&lt;/span&gt; ../../pkgtools/pkgdiff &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; bmake install&lt;span class='o'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now edit the offending file:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; pkgvi &lt;span class='k'&gt;$(&lt;/span&gt;bmake show-var &lt;span class='nv'&gt;VARNAME&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;WRKSRC&lt;span class='k'&gt;)&lt;/span&gt;/net/cork.c
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is what I changed the function to:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;&lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='nf'&gt;socket_cork&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;sock&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='p'&gt;{&lt;/span&gt;
&lt;span class='cp'&gt;#if defined(TCP_CORK) &amp;amp;&amp;amp; defined(SOL_TCP)&lt;/span&gt;
  &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;flag&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;setsockopt&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sock&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;SOL_TCP&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;TCP_CORK&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;flag&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;sizeof&lt;/span&gt; &lt;span class='n'&gt;flag&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='cp'&gt;#elif defined(TCP_CORK) &amp;amp;&amp;amp; defined(SOL_SOCKET)&lt;/span&gt;
  &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;flag&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;setsockopt&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sock&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;SOL_SOCKET&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;TCP_CORK&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;flag&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;sizeof&lt;/span&gt; &lt;span class='n'&gt;flag&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='cp'&gt;#elif defined(TCP_NOPUSH)&lt;/span&gt;
  &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;flag&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
  &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;setsockopt&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sock&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;SOL_SOCKET&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;TCP_NOPUSH&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;flag&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;sizeof&lt;/span&gt; &lt;span class='n'&gt;flag&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='cp'&gt;#else&lt;/span&gt;
  &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='cp'&gt;#endif&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This still isn&amp;#8217;t ideal, and would be better converted to a proper autoconf test where we can test functionality instead of definitions, but it will do for example purposes.&lt;/p&gt;

&lt;p&gt;After writing, you should get output such as:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;pkgvi: File was modified. For a diff, type:&lt;/span&gt;
&lt;span class='go'&gt;pkgdiff &amp;quot;/var/tmp/pkgsrc-build/devel/bglibs/work/bglibs-1.106/net/cork.c&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and running the &lt;code&gt;pkgdiff&lt;/code&gt; command will show you the diff.&lt;/p&gt;

&lt;p&gt;The final step is storing the diff into a patch file, and that is accomplished with:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; mkpatches
&lt;span class='gp'&gt;#&lt;/span&gt; bmake mps
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;mkpatches&lt;/code&gt; command creates a new file in the &lt;code&gt;patches&lt;/code&gt; directory called &lt;code&gt;patch-net_cork.c&lt;/code&gt;, and the &lt;code&gt;bmake mps&lt;/code&gt; (short for the &lt;code&gt;makepatchsum&lt;/code&gt; target) regenerates the &lt;code&gt;distinfo&lt;/code&gt; file with the correct checksum for that patch.&lt;/p&gt;

&lt;p&gt;Finally, you can rebuild&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; bmake clean
&lt;span class='gp'&gt;#&lt;/span&gt; bmake package
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and, hey presto .. another failure!&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;--- net/uncork.lo ---&lt;/span&gt;
&lt;span class='go'&gt;net/uncork.c: In function &amp;#39;socket_uncork&amp;#39;:&lt;/span&gt;
&lt;span class='go'&gt;net/uncork.c:30:27: error: &amp;#39;SOL_TCP&amp;#39; undeclared (first use in this function)&lt;/span&gt;
&lt;span class='go'&gt;net/uncork.c:30:27: note: each undeclared identifier is reported only once for each function it appears in&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now that you know how to fix this, I&amp;#8217;ll leave it to you to come up with a patch ;)&lt;/p&gt;

&lt;p&gt;One final word on this, you will perhaps notice during the build some warnings:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;=&amp;gt; Applying pkgsrc patches for bglibs-1.106nb1&lt;/span&gt;
&lt;span class='go'&gt;=&amp;gt; Ignoring patchfile /content/pkgsrc/devel/bglibs/patches/patch-ab.orig&lt;/span&gt;
&lt;span class='go'&gt;=&amp;gt; Ignoring patchfile /content/pkgsrc/devel/bglibs/patches/patch-ac.orig&lt;/span&gt;
&lt;span class='go'&gt;=&amp;gt; Ignoring patchfile /content/pkgsrc/devel/bglibs/patches/patch-net_cork.c.orig&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;These files are left by &lt;code&gt;mkpatches&lt;/code&gt;, and to remove them you can run&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; mkpatches -c
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Also note that both &lt;code&gt;patch-ab&lt;/code&gt; and &lt;code&gt;patch-ac&lt;/code&gt; changed, even though we only modified the &lt;code&gt;net/cork.c&lt;/code&gt; file. This is due to differences in &lt;code&gt;diff(1)&lt;/code&gt; output, and is ultimately harmless.&lt;/p&gt;

&lt;h2 id='summary'&gt;Summary&lt;/h2&gt;

&lt;p&gt;pkgsrc provides a number of ways to fix up broken software:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;CFLAGS&lt;/code&gt;, &lt;code&gt;LDFLAGS&lt;/code&gt;, and other environment variables.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;The &lt;code&gt;subst.mk&lt;/code&gt; framework for simple file changes.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Patch files for more substantial changes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important thing, after using any of these features, is to feed back your changes so that we can integrate them into pkgsrc and everyone can benefit. Probably the easiest way to do that is simply raise an issue against &lt;a href='https://github.com/joyent/pkgsrc/issues'&gt;our GitHub pkgsrc fork&lt;/a&gt;, and either myself or Filip can commit the patch upstream.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>pkgsrc on SmartOS - zone creation and basic builds</title>
      <link>http://www.perkin.org.uk/posts/pkgsrc-on-smartos-zone-creation-and-basic-builds.html</link>
      <pubDate>Tue, 15 Jan 2013 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/pkgsrc-on-smartos-zone-creation-and-basic-builds.html</guid>
      <description>&lt;p&gt;Our goal at &lt;a href='http://www.joyent.com/'&gt;Joyent&lt;/a&gt; is that our binary packages for &lt;a href='http://smartos.org/'&gt;SmartOS&lt;/a&gt; fulfill all of our users&amp;#8217; needs. This isn&amp;#8217;t always possible, however - users may want packages we do not yet provide, or build with different options.&lt;/p&gt;

&lt;p&gt;To satisfy those demands, it should instead be reasonably straight-forward for users to build their own packages, and this guide hopefully provides all the information for them to do just that.&lt;/p&gt;

&lt;p&gt;This is the first in a series of posts, and will focus on getting pkgsrc set up in a clean SmartOS zone and then building some packages. Other posts currently available in the series are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='/posts/pkgsrc-on-smartos-fixing-broken-builds.html'&gt;How to fix build failures&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='create_a_build_machine'&gt;Create a build machine&lt;/h2&gt;

&lt;p&gt;For this guide I use a &lt;code&gt;base:1.8.1&lt;/code&gt; SmartMachine, but any recent dataset should be fine, and it shouldn&amp;#8217;t matter whether it&amp;#8217;s 32-bit or 64-bit.&lt;/p&gt;

&lt;p&gt;If you are a Joyent customer:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;: Fill in your SDC details.  You can use the web interface too, if you prefer.&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;export &lt;/span&gt;&lt;span class='nv'&gt;SDC_CLI_ACCOUNT&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;account name
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;export &lt;/span&gt;&lt;span class='nv'&gt;SDC_CLI_IDENTITY&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/path/to/ssh/key
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;export &lt;/span&gt;&lt;span class='nv'&gt;SDC_CLI_KEY_ID&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;key identifier
&lt;span class='go'&gt;: .. or us-west-1 or us-sw-1 or eu-ams-1&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;export &lt;/span&gt;&lt;span class='nv'&gt;SDC_CLI_URL&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;https://us-east-1.api.joyentcloud.com

&lt;span class='go'&gt;: You really really want json(1), it&amp;#39;s awesome&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; sudo npm -g install jsontool

&lt;span class='go'&gt;: Get list of &amp;#39;base&amp;#39; datasets, we&amp;#39;ll use the latest&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; sdc-listdatasets | json -a urn id | grep :base: | head -1
&lt;span class='go'&gt;sdc:sdc:base:1.8.1 55330ab4-066f-11e2-bd0f-434f2462fada&lt;/span&gt;

&lt;span class='go'&gt;: You can use sdc-listpackages to show available machine types.  I want one&lt;/span&gt;
&lt;span class='go'&gt;: with good CPU performance.&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; sdc-createmachine --dataset 55330ab4-066f-11e2-bd0f-434f2462fada &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='gp'&gt;&amp;gt;&lt;/span&gt;   --name &lt;span class='s2'&gt;&amp;quot;pkgsrc-build-machine&amp;quot;&lt;/span&gt; --package &lt;span class='s2'&gt;&amp;quot;XL  8GB High CPU&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you are using SmartOS:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='json'&gt;&lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;brand&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;joyent&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;image_uuid&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;55330ab4-066f-11e2-bd0f-434f2462fada&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;max_physical_memory&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;quota&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='mi'&gt;24&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;alias&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;pkgsrc-build-machine&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;hostname&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;pkgsrc-build-machine&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;nics&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;quot;nic_tag&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;admin&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;quot;ip&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;dhcp&amp;quot;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='p'&gt;]&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Put the above json into a file, you may want to tweak some values, then&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; imgadm update
&lt;span class='gp'&gt;#&lt;/span&gt; imgadm import 55330ab4-066f-11e2-bd0f-434f2462fada
&lt;span class='gp'&gt;#&lt;/span&gt; vmadm create -f /path/to/json/file
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, log into the freshly-created zone.&lt;/p&gt;

&lt;h2 id='install_dependencies'&gt;Install dependencies&lt;/h2&gt;

&lt;p&gt;First thing you&amp;#8217;ll need in the zone are build tools, so:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; pkgin -y up
&lt;span class='gp'&gt;#&lt;/span&gt; pkgin -y in gcc47 scmgit-base
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='fetch_pkgsrc'&gt;Fetch pkgsrc&lt;/h2&gt;

&lt;p&gt;We maintain a fork of pkgsrc on github, which includes some additional SmartOS fixes and improvements, so we recommend using that rather than upstream.&lt;/p&gt;

&lt;p&gt;I put everything under &lt;code&gt;/content&lt;/code&gt;, adjust to your own tastes.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; mkdir /content
&lt;span class='gp'&gt;#&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /content
&lt;span class='gp'&gt;#&lt;/span&gt; git clone git://github.com/joyent/pkgsrc.git
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Next, check out the latest stable branch. Our naming scheme is &lt;code&gt;joyent/release/YYYYQQ&lt;/code&gt;, and the latest branch at time of writing is &lt;code&gt;pkgsrc_2012Q4&lt;/code&gt;, so:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; &lt;span class='nb'&gt;cd &lt;/span&gt;pkgsrc
&lt;span class='gp'&gt;#&lt;/span&gt; git checkout joyent/release/2012Q4
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you want to be particularly adventurous, you could checkout &lt;code&gt;trunk&lt;/code&gt; and get the very latest pkgsrc code, however pkgsrc is a very fast-moving target and you may run into unexpected breakages, and you will certainly end up rebuilding packages very often.&lt;/p&gt;

&lt;h2 id='fetch_pkgsrcwip'&gt;Fetch pkgsrc-wip&lt;/h2&gt;

&lt;p&gt;&lt;a href='http://pkgsrc-wip.sourceforge.net/'&gt;pkgsrc-wip&lt;/a&gt; is a set of additional work-in-progress packages for pkgsrc, and can be useful for trying out the latest packages. It is designed to be extracted directly into pkgsrc, and we maintain a git submodule of it in our release trees, so all you need to do, assuming you are using a &lt;code&gt;joyent/release/*&lt;/code&gt; tree, is:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; git submodule init
&lt;span class='gp'&gt;#&lt;/span&gt; git submodule update
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This will also get you a &lt;code&gt;joyent/&lt;/code&gt; directory which is a module of our &lt;a href='http://github.com/joyent/pkgsrc-joyent/'&gt;pkgsrc-joyent&lt;/a&gt; tree of additional packages.&lt;/p&gt;

&lt;p&gt;If you are on &lt;code&gt;trunk&lt;/code&gt; or another tree which does not have the &lt;code&gt;wip&lt;/code&gt; submodule, you can fetch it manually with:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; git clone git://github.com/joyent/pkgsrc-wip.git wip
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_mkconf'&gt;Configure mk.conf&lt;/h2&gt;

&lt;p&gt;The primary method of configuring pkgsrc is through the &lt;code&gt;/opt/local/etc/mk.conf&lt;/code&gt; file. The base image comes with one populated to handle the basic layout, but there are some additional basic variables you may want to set prior to building your first package:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;DISTDIR&lt;/code&gt;&lt;/strong&gt; determines where source tarballs are stored, default &lt;code&gt;pkgsrc/distfiles&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;PACKAGES&lt;/code&gt;&lt;/strong&gt; is where pkgsrc will store binary packages it has built, default &lt;code&gt;pkgsrc/packages&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;WRKOBJDIR&lt;/code&gt;&lt;/strong&gt; is where pkgsrc performs the builds, default &lt;code&gt;pkgsrc/&amp;lt;category&amp;gt;/&amp;lt;package&amp;gt;/work&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;ALLOW_VULNERABLE_PACKAGES&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;SKIP_LICENSE_CHECK&lt;/code&gt;&lt;/strong&gt; should both be set to &lt;code&gt;yes&lt;/code&gt; if you just want the package to be built, and don&amp;#8217;t care whether it is currently vulnerable to security issues or is released under a specific license.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;MAKE_JOBS&lt;/code&gt;&lt;/strong&gt; determines the argument to &lt;code&gt;make -j&lt;/code&gt;, i.e. the number of concurrent make threads, default 1.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;FETCH_USING&lt;/code&gt;&lt;/strong&gt; sets the default program to use for fetching source code, defaulting to an in-tree version of NetBSD&amp;#8217;s ftp program. Setting this to &lt;code&gt;curl&lt;/code&gt; on SmartOS, which is included in the base platform, will avoid any dependencies.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;BINPKG_SITES&lt;/code&gt;&lt;/strong&gt; is a URL pointing to binary packages which can be used by this tree rather than building everything from source, and settings &lt;strong&gt;&lt;code&gt;DEPENDS_TARGET&lt;/code&gt;&lt;/strong&gt; to &lt;code&gt;bin-install&lt;/code&gt; enables using these binary packages as dependencies.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus, this is how I would configure &lt;code&gt;mk.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; mkdir -p /content/&lt;span class='o'&gt;{&lt;/span&gt;distfiles,packages&lt;span class='o'&gt;}&lt;/span&gt;
&lt;span class='gp'&gt;#&lt;/span&gt; vi /opt/local/etc/mk.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='make'&gt;&lt;span class='nv'&gt;DISTDIR&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;	/content/distfiles
&lt;span class='nv'&gt;PACKAGES&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;	/content/packages
&lt;span class='nv'&gt;WRKOBJDIR&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;	/var/tmp/pkgsrc-build
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='nv'&gt;ALLOW_VULNERABLE_PACKAGES&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;	yes
&lt;span class='nv'&gt;SKIP_LICENSE_CHECK&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;		yes
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='nv'&gt;MAKE_JOBS&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;	8
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='nv'&gt;FETCH_USING&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;	curl
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Adjust BINPKG_SITES, depending upon the dataset chosen, it should be the URL&lt;/span&gt;
&lt;span class='c'&gt;# from /opt/local/etc/pkgin/repositories.conf without the trailing &amp;#39;All&amp;#39;.&lt;/span&gt;
&lt;span class='nv'&gt;BINPKG_SITES&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;	http://pkgsrc.joyent.com/sdc6/2012Q2/i386/
&lt;span class='nv'&gt;DEPENDS_TARGET&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;	bin-install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='building_a_package'&gt;Building a package&lt;/h2&gt;

&lt;p&gt;Ok, let&amp;#8217;s get started and build a package. pkgsrc is organised into categories, with all packages following the &lt;code&gt;pkgsrc/&amp;lt;category&amp;gt;/&amp;lt;package&amp;gt;&lt;/code&gt; layout, and everything is driven with &lt;code&gt;bmake&lt;/code&gt;, the BSD implementation of &lt;code&gt;make(1)&lt;/code&gt;. I&amp;#8217;m going to choose &lt;code&gt;nmap&lt;/code&gt; as an example, as it will show a couple of things I want to cover.&lt;/p&gt;

&lt;p&gt;First, finding it. I tend to just do a simple:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; ls -d */*nmap*
&lt;span class='go'&gt;net/nmap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you want a more featured search, you can do:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; bmake search &lt;span class='nv'&gt;key&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;nmap
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;though the first time you run this it creates the &lt;code&gt;INDEX&lt;/code&gt; file it requires, and that can take a long time. Another option is to use the &lt;a href='http://pkgsrc.se/'&gt;pkgsrc.se&lt;/a&gt; web interface.&lt;/p&gt;

&lt;p&gt;Once you have found the package, &lt;code&gt;cd&lt;/code&gt; into the package directory.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; &lt;span class='nb'&gt;cd &lt;/span&gt;net/nmap
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Next, let&amp;#8217;s look at any options the package supports.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; bmake show-options
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If the package supports build options, as &lt;code&gt;net/nmap&lt;/code&gt; does, you&amp;#8217;ll see something like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;Any of the following general options may be selected:
	inet6	 Enable support for IPv6.
	ndiff	 Enable tool to compare Nmap scans.
	zenmap	 Enable nmap GUI frontend.

These options are enabled by default:
	inet6

These options are currently enabled:
	inet6

You can select which build options to use by setting PKG_DEFAULT_OPTIONS
or PKG_OPTIONS.nmap.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The place to configure these options is again in &lt;code&gt;/opt/local/etc/mk.conf&lt;/code&gt;, so if you want to enable ndiff support for example, then you&amp;#8217;d add this to &lt;code&gt;mk.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='make'&gt;&lt;span class='nv'&gt;PKG_OPTIONS.nmap&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;	ndiff
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Re-running the &lt;code&gt;show-options&lt;/code&gt; command should now print:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;...
These options are currently enabled:
        inet6 ndiff
...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And finally, we can go ahead and build the package. The output from this will be long, so you may want to &lt;code&gt;tee&lt;/code&gt; it to a file for reviewing:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; bmake install 2&amp;gt;&amp;amp;1 | tee /var/tmp/nmap.log
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Assuming this completes ok, you should note the main stages that make up a package build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;bootstrap-depends&lt;/code&gt;&lt;/strong&gt; comes first, and installs all the dependencies required for pkgsrc to get started. &lt;code&gt;pkgtools/digest&lt;/code&gt; is required to calculate the &lt;code&gt;SHA1&lt;/code&gt; and &lt;code&gt;RMD160&lt;/code&gt; checksums of the source tarball. If we hadn&amp;#8217;t specified &lt;code&gt;FETCH_USING=curl&lt;/code&gt; in our &lt;code&gt;mk.conf&lt;/code&gt; then it&amp;#8217;s likely that &lt;code&gt;net/tnftp&lt;/code&gt; would have been pulled in during this stage too and used to fetch the source.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;=&amp;gt; Bootstrap dependency digest&amp;gt;=20010302: NOT found
=&amp;gt; Verifying bin-install for ../../pkgtools/digest
===&amp;gt; Binary install for digest&amp;gt;=20010302
=&amp;gt; Installing digest&amp;gt;=20010302 from /content/packages/All;http://pkgsrc.joyent.com/sdc6/2012Q2/i386//All
pkg_add: Can&amp;#39;t process file:///content/packages/All/digest*: No such file or directory
digest-20111104 successfully installed.
...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;fetch&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;checksum&lt;/code&gt;&lt;/strong&gt; then run to download the source tarball for this particular package, and then verify the checksum matches that stored by pkgsrc, to ensure it was downloaded from a good source:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;=&amp;gt; Fetching nmap-6.01.tar.bz2
=&amp;gt; Total size: 21640157 bytes
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 20.6M  100 20.6M    0     0   699k      0  0:00:30  0:00:30 --:--:--  721k
=&amp;gt; Checksum SHA1 OK for nmap-6.01.tar.bz2
=&amp;gt; Checksum RMD160 OK for nmap-6.01.tar.bz2
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;depends&lt;/code&gt;&lt;/strong&gt; then installs all packages required for both build and runtime for the package in question:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;=&amp;gt; Build dependency libtool-base&amp;gt;=2.2.6bnb3: NOT found
=&amp;gt; Verifying bin-install for ../../devel/libtool-base
===&amp;gt; Binary install for libtool-base&amp;gt;=2.2.6bnb3
=&amp;gt; Installing libtool-base&amp;gt;=2.2.6bnb3 from /content/packages/All;http://pkgsrc.joyent.com/sdc6/2012Q2/i386//All
libtool-base-2.2.6bnb6 successfully installed.
...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;extract&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;patch&lt;/code&gt;&lt;/strong&gt; then unpack the source and apply any pkgsrc patches to the package. The patches are located in the &lt;code&gt;patches/&lt;/code&gt; sub-directory for each package:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;===&amp;gt; Extracting for nmap-6.01nb5
===&amp;gt; Patching for nmap-6.01nb5
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;The bulk of the build is performed by &lt;strong&gt;&lt;code&gt;configure&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;build&lt;/code&gt;&lt;/strong&gt; which for most software will consist of &lt;code&gt;./configure &amp;amp;&amp;amp; make&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;===&amp;gt; Configuring for nmap-6.01nb5
...
checking whether NLS is requested... yes
...
Configuration complete.  Type make (or gmake on some *BSD machines) to compile.
...
===&amp;gt; Building for nmap-6.01nb5
...
gmake[1]: Leaving directory `/var/tmp/pkgsrc-build/net/nmap/work/nmap-6.01&amp;#39;
=&amp;gt; Unwrapping files-to-be-installed.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;The final steps are &lt;strong&gt;&lt;code&gt;package&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;install&lt;/code&gt;&lt;/strong&gt;, firstly &lt;code&gt;package&lt;/code&gt; does a fake install of the package to a temporary install directory and creates a binary package from that, and then &lt;code&gt;install&lt;/code&gt; installs that binary package into place:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;===&amp;gt; Building binary package for nmap-6.01nb5
=&amp;gt; Creating binary package /content/packages/All/nmap-6.01nb5.tgz
===&amp;gt; Install binary package of nmap-6.01nb5
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can now verify it is installed, and start using your new software:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; &lt;span class='nb'&gt;type &lt;/span&gt;nmap
&lt;span class='go'&gt;nmap is /opt/local/bin/nmap&lt;/span&gt;

&lt;span class='gp'&gt;#&lt;/span&gt; nmap -p 22 localhost

&lt;span class='go'&gt;Starting Nmap 6.01 ( http://nmap.org ) at 2013-01-15 15:36 UTC&lt;/span&gt;
&lt;span class='go'&gt;Nmap scan report for localhost (127.0.0.1)&lt;/span&gt;
&lt;span class='go'&gt;Host is up (0.00012s latency).&lt;/span&gt;
&lt;span class='go'&gt;PORT   STATE SERVICE&lt;/span&gt;
&lt;span class='go'&gt;22/tcp open  ssh&lt;/span&gt;

&lt;span class='go'&gt;Nmap done: 1 IP address (1 host up) scanned in 0.11 seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='cleanup'&gt;Cleanup&lt;/h2&gt;

&lt;p&gt;Once everything is working, you may want to clean up the build areas. The pkgsrc way of doing this is:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; bmake clean clean-depends
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;However, if you just want to blow everything away without prejudice, you can simply remove everything under &lt;code&gt;WRKOBJDIR&lt;/code&gt;, so in my case:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; rm -rf /var/tmp/pkgsrc-build/*
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This should hopefully be enough to get you started. Over the next few posts we&amp;#8217;ll investigate some more advanced topics. Stay tuned!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Multi-architecture package support in SmartOS</title>
      <link>http://www.perkin.org.uk/posts/multiarch-package-support-in-smartos.html</link>
      <pubDate>Thu, 10 Jan 2013 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/multiarch-package-support-in-smartos.html</guid>
      <description>&lt;p&gt;&lt;em&gt;[Updated on 2013-01-16 to use the 12.4.1 dataset which fixes some issues.]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ever since the release of Solaris 7 back in 1998, Solaris has had the ability to run both 32-bit and 64-bit binaries on the same machine. Even now, 15 years later, with much of the world 64-bit only, there are still reasons to retain 32-bit support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;32-bit binaries can be faster in many cases, and if you do not need the additional address space afforded by the 64-bit version then there may be no advantage to running it.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Some software you depend upon may only provide a 32-bit version, or may have better compatability in that mode.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;It&amp;#8217;s sometimes nice to have a hard 4GB memory limit on a runaway process instead of it completely trashing your machine ;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unfortunately, while the base &lt;a href='http://smartos.org/'&gt;SmartOS&lt;/a&gt; platform is set up to provide both 32-bit and 64-bit binaries, the packaging infrastructure we use, &lt;a href='http://www.pkgsrc.org/'&gt;pkgsrc&lt;/a&gt;, has not traditionally supported building multi-architecture packages. This has meant we have needed to provide both 32-bit and 64-bit versions of each dataset, which is not ideal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It&amp;#8217;s confusing to customers and users, who may think it applies to the kernel and platform version.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Users want the choice to be able to run 32-bit for some applications and 64-bit for others, all on the same machine.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;It is additional work and maintenance for us.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In order to resolve this, I have been working on providing multi-architecture support to pkgsrc, and this work is now available for preview testing.&lt;/p&gt;

&lt;h2 id='getting_started'&gt;Getting started&lt;/h2&gt;

&lt;p&gt;Here is a quick start guide to getting the multi-architecture dataset up and running:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;: Fetch the dataset image and manifest files.  The image is 85MB.&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; mkdir -p /usbkey/images
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /usbkey/images
&lt;span class='gp'&gt;$&lt;/span&gt; curl -O http://pkgsrc.smartos.org/datasets/multiarch-12.4.1.dsmanifest
&lt;span class='gp'&gt;$&lt;/span&gt; curl -O http://pkgsrc.smartos.org/datasets/multiarch-12.4.1.zfs.bz2

&lt;span class='go'&gt;: Import it&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; imgadm install -m multiarch-12.4.1.dsmanifest -f multiarch-12.4.1.zfs.bz2

&lt;span class='go'&gt;: Create a new zone using the dataset (change your json to suit).&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; vmadm create &amp;lt;&amp;lt;EOF
&lt;span class='go'&gt;{&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;brand&amp;quot;: &amp;quot;joyent&amp;quot;,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;image_uuid&amp;quot;: &amp;quot;ee1fb198-5fe1-11e2-9cce-e319fd47df7b&amp;quot;,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;max_physical_memory&amp;quot;: 256,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;alias&amp;quot;: &amp;quot;multiarch-12.4.1&amp;quot;,&lt;/span&gt;
&lt;span class='go'&gt;  &amp;quot;nics&amp;quot;: [&lt;/span&gt;
&lt;span class='go'&gt;    {&lt;/span&gt;
&lt;span class='go'&gt;      &amp;quot;nic_tag&amp;quot;: &amp;quot;admin&amp;quot;,&lt;/span&gt;
&lt;span class='go'&gt;      &amp;quot;ip&amp;quot;: &amp;quot;dhcp&amp;quot;&lt;/span&gt;
&lt;span class='go'&gt;    }&lt;/span&gt;
&lt;span class='go'&gt;  ]&lt;/span&gt;
&lt;span class='go'&gt;}&lt;/span&gt;
&lt;span class='go'&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;then login and start using it as you would with any other dataset.&lt;/p&gt;

&lt;h2 id='multiarchitecture_libraries'&gt;Multi-architecture libraries&lt;/h2&gt;

&lt;p&gt;Libraries are reasonably straight-forward. For most packages which provide shared libraries, you should find both 32-bit and 64-bit libraries are included, for example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkg_info -L sqlite3 | grep &lt;span class='s1'&gt;&amp;#39;so$&amp;#39;&lt;/span&gt;
&lt;span class='go'&gt;/opt/local/lib/libsqlite3.so&lt;/span&gt;
&lt;span class='go'&gt;/opt/local/lib/amd64/libsqlite3.so&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Other directories under &lt;code&gt;lib/&lt;/code&gt; should be handled correctly too, such as &lt;code&gt;.pc&lt;/code&gt; files for &lt;code&gt;pkg-config&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkg_info -L sqlite3 | grep &lt;span class='s1'&gt;&amp;#39;pc$&amp;#39;&lt;/span&gt;
&lt;span class='go'&gt;/opt/local/lib/pkgconfig/sqlite3.pc&lt;/span&gt;
&lt;span class='go'&gt;/opt/local/lib/amd64/pkgconfig/sqlite3.pc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='multiarchitecture_binaries'&gt;Multi-architecture binaries&lt;/h2&gt;

&lt;p&gt;Binaries are similar, but follow a different layout scheme, and have additional controls to allow the user to select which architecture to use.&lt;/p&gt;

&lt;p&gt;The basic layout is:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkg_info -L sqlite3 | grep bin
&lt;span class='go'&gt;/opt/local/bin/i86/sqlite3&lt;/span&gt;
&lt;span class='go'&gt;/opt/local/bin/amd64/sqlite3&lt;/span&gt;
&lt;span class='go'&gt;/opt/local/bin/sqlite3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In order to explain this, let us look at how the base platform supports multi-architecture binaries, using &lt;code&gt;dtrace&lt;/code&gt; as an example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; ls -li /usr/sbin/*/dtrace /usr/sbin/dtrace /usr/lib/isaexec
&lt;span class='go'&gt;4255 -r-xr-xr-x 72 root bin 12776 Dec 28 02:38 /usr/lib/isaexec&lt;/span&gt;
&lt;span class='go'&gt;6330 -r-xr-xr-x  1 root bin 52728 Dec 28 02:38 /usr/sbin/amd64/dtrace&lt;/span&gt;
&lt;span class='go'&gt;4255 -r-xr-xr-x 72 root bin 12776 Dec 28 02:38 /usr/sbin/dtrace&lt;/span&gt;
&lt;span class='go'&gt;6640 -r-xr-xr-x  1 root bin 41544 Dec 28 02:38 /usr/sbin/i86/dtrace&lt;/span&gt;

&lt;span class='gp'&gt;$&lt;/span&gt; file /usr/sbin/*/dtrace /usr/lib/isaexec
&lt;span class='go'&gt;/usr/sbin/amd64/dtrace: ELF 64-bit LSB executable AMD64 Version 1, dynamically linked, not stripped, no debugging information available&lt;/span&gt;
&lt;span class='go'&gt;/usr/sbin/i86/dtrace:   ELF 32-bit LSB executable 80386 Version 1, dynamically linked, not stripped, no debugging information available&lt;/span&gt;
&lt;span class='go'&gt;/usr/lib/isaexec:       ELF 32-bit LSB executable 80386 Version 1, dynamically linked, not stripped, no debugging information available&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;i86&lt;/code&gt; and &lt;code&gt;amd64&lt;/code&gt; hold the per-architecture binaries, and the main &lt;code&gt;/usr/sbin/dtrace&lt;/code&gt; command is a hardlink to the &lt;code&gt;/usr/lib/isaexec&lt;/code&gt; wrapper (as shown by the inode being identical). This wrapper detects whether the running kernel is 32-bit or 64-bit, and calls the appropriate native binary, which nowadays will almost certainly be the 64-bit version.&lt;/p&gt;

&lt;p&gt;For the pkgsrc implementation, I needed a way to override this behaviour so that users could select to run the 32-bit version if so desired, without having to munge their &lt;code&gt;$PATH&lt;/code&gt;. To do this I took a copy of &lt;code&gt;isaexec&lt;/code&gt; and added it to pkgsrc, with additional support for an &lt;code&gt;ABI&lt;/code&gt; environment variable.&lt;/p&gt;

&lt;p&gt;You can see the behaviour below with the calls to &lt;code&gt;execve()&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Default is to run 64-bit&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; truss -t execve sqlite3 -version
&lt;span class='go'&gt;execve(&amp;quot;/opt/local/bin/sqlite3&amp;quot;, 0x08047DA8, 0x08047DB4)  argc = 2&lt;/span&gt;
&lt;span class='go'&gt;execve(&amp;quot;/opt/local/bin/amd64/sqlite3&amp;quot;, 0x08047DA8, 0x08047DB4)  argc = 2&lt;/span&gt;
&lt;span class='go'&gt;3.7.15 2012-12-12 13:36:53 cd0b37c52658bfdf992b1e3dc467bae1835a94ae&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Set ABI=32 or ABI=i86 to run the 32-bit version&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;ABI&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;32 truss -t execve sqlite3 -version
&lt;span class='go'&gt;execve(&amp;quot;/opt/local/bin/sqlite3&amp;quot;, 0x08047D9C, 0x08047DA8)  argc = 2&lt;/span&gt;
&lt;span class='go'&gt;execve(&amp;quot;/opt/local/bin/i86/sqlite3&amp;quot;, 0x08047D9C, 0x08047DA8)  argc = 2&lt;/span&gt;
&lt;span class='go'&gt;3.7.15 2012-12-12 13:36:53 cd0b37c52658bfdf992b1e3dc467bae1835a94ae&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Note that not all binaries have been converted to multi-architecture. In fact, the majority have been left as plain 32-bit binaries. While all libraries ultimately have to be provided for both architectures so that users can choose to compile their own software against either, 64-bit binaries only make sense for certain classes of software:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Databases such as SQLite, and other servers which may require &amp;gt;4GB address space.&lt;/li&gt;

&lt;li&gt;Language interpreters.&lt;/li&gt;

&lt;li&gt;Software which provides a &lt;code&gt;foo-config&lt;/code&gt; script with hardcoded references to &lt;code&gt;libdir&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='compiler_support'&gt;Compiler support&lt;/h2&gt;

&lt;p&gt;The GCC 4.7.2 package provided has been made aware of this layout, and will add the correct library paths depending upon the ABI you target. For example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; cat &amp;gt;test.c &amp;lt;&amp;lt;EOF
&lt;span class='go'&gt;int main(){}&lt;/span&gt;
&lt;span class='go'&gt;EOF&lt;/span&gt;

&lt;span class='gp'&gt;$&lt;/span&gt; gcc -m32 test.c -o test32 -lsqlite3
&lt;span class='gp'&gt;$&lt;/span&gt; ldd test32 | grep libsqlite3
&lt;span class='go'&gt;        libsqlite3.so.0 =&amp;gt;       /opt/local/lib/libsqlite3.so.0&lt;/span&gt;

&lt;span class='gp'&gt;$&lt;/span&gt; gcc -m64 test.c -o test64 -lsqlite3
&lt;span class='gp'&gt;$&lt;/span&gt; ldd test64 | grep libsqlite3
&lt;span class='go'&gt;        libsqlite3.so.0 =&amp;gt;       /opt/local/lib/amd64/libsqlite3.so.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;No additional flags or linker settings should be required (if they are, let me know!)&lt;/p&gt;

&lt;h2 id='interpreter_support'&gt;Interpreter support&lt;/h2&gt;

&lt;p&gt;For those interpreters which have been converted, their respective module systems should be multi-architecture aware:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perl already had reasonable support for multi-architecture files, and all perl modules provided should be enabled, for example:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkgin -y in p5-Digest-SHA1
&lt;span class='gp'&gt;$&lt;/span&gt; pkg_info -L p5-Digest-SHA1 | grep &lt;span class='s1'&gt;&amp;#39;so$&amp;#39;&lt;/span&gt;
&lt;span class='go'&gt;/opt/local/lib/perl5/vendor_perl/5.16.0/i386-solaris-thread-multi/auto/Digest/SHA1/SHA1.so&lt;/span&gt;
&lt;span class='go'&gt;/opt/local/lib/perl5/vendor_perl/5.16.0/x86_64-solaris-thread-multi-64/auto/Digest/SHA1/SHA1.so&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;ABI&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;32 perl -MDigest::SHA1 -e &lt;span class='s1'&gt;&amp;#39;print&amp;#39;&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;ABI&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;64 perl -MDigest::SHA1 -e &lt;span class='s1'&gt;&amp;#39;print&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Python is similar to Perl, but needed a lot more work to support multi-architecture modules. Modules provided by pkgin should work fine, but there may be issues with locally-built modules - let me know!&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;node is built as a multi-architecture binary, but &lt;code&gt;npm&lt;/code&gt; has received no special handling. This means you need to be careful not to mix-and-match modules. I don&amp;#8217;t perceive this to be too much of an issue, as the node community appears to have settled on having one &lt;code&gt;node_modules&lt;/code&gt; per application, but again let me know if there are better ways to handle this.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='coverage'&gt;Coverage&lt;/h2&gt;

&lt;p&gt;This work is incomplete, hence it not being available in the default datasets yet, but a large number of packages have been converted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pretty much every package which provides shared libraries.&lt;/li&gt;

&lt;li&gt;Python, Perl, Lua and node.js interpreters (and a significant number of modules).&lt;/li&gt;

&lt;li&gt;MySQL 5.5, PostgreSQL, SQLite and DB4 databases, Apache 2.2.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notable exceptions currently are Ruby and PHP, and I will be working on those in due course. There may also be a number of packages which should include multi-architecture binaries, please let me know if I have missed any obvious candidates.&lt;/p&gt;

&lt;p&gt;You can raise issues against our GitHub project &lt;a href='https://github.com/joyent/pkgsrc/issues'&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Solaris portability - cfmakeraw()</title>
      <link>http://www.perkin.org.uk/posts/solaris-portability-cfmakeraw.html</link>
      <pubDate>Wed, 09 Jan 2013 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/solaris-portability-cfmakeraw.html</guid>
      <description>&lt;p&gt;Converting from &lt;a href='http://www.perkin.org.uk/posts/solaris-portability-flock.html'&gt;&lt;code&gt;flock()&lt;/code&gt; to &lt;code&gt;fcntl()&lt;/code&gt;&lt;/a&gt; unfortunately wasn&amp;#8217;t enough to get tmux to build on Solaris, there was one additional failure:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;client.c: In function &amp;#39;client_main&amp;#39;:
client.c:246:3: warning: implicit declaration of function &amp;#39;cfmakeraw&amp;#39; [-Wimplicit-function-declaration]

...

Undefined                       first referenced
 symbol                             in file
cfmakeraw                           client.o
ld: fatal: symbol referencing errors. No output written to tmux
collect2: error: ld returned 1 exit status
*** [tmux] Error code 1
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Let&amp;#8217;s look at the code:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;	&lt;span class='k'&gt;struct&lt;/span&gt; &lt;span class='n'&gt;termios&lt;/span&gt; &lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;...&lt;/span&gt;
	&lt;span class='n'&gt;cfmakeraw&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
	&lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;c_iflag&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;ICRNL&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;IXANY&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;c_oflag&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;OPOST&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ONLCR&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Running &lt;code&gt;man cfmakeraw&lt;/code&gt; on my OSX laptop I can read what this function does, and where it is implemented (edited for brevity):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;SYNOPSIS
     void
     cfmakeraw(struct termios *termios_p);

DESCRIPTION
     The cfmakeraw() function sets the flags stored in the termios structure
     to a state disabling all input and output processing, giving a ``raw I/O
     path&amp;#39;&amp;#39;.

STANDARDS
     The cfmakeraw() and cfsetspeed() functions, as well as the TCSASOFT option
     to the tcsetattr() function are extensions to the IEEE Std 1003.1-1988
     (``POSIX.1&amp;#39;&amp;#39;) specification.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ok, so all it&amp;#8217;s doing is setting some additional flags in the &lt;code&gt;tio&lt;/code&gt; structure, and a quick search in the &lt;a href='http://opengrok.netbsd.org/xref/src/lib/libc/termios/cfmakeraw.c'&gt;NetBSD OpenGrok&lt;/a&gt; gives us their implementation (again edited for brevity):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;&lt;span class='kt'&gt;void&lt;/span&gt;
&lt;span class='nf'&gt;cfmakeraw&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;struct&lt;/span&gt; &lt;span class='n'&gt;termios&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='p'&gt;{&lt;/span&gt;
&lt;span class='p'&gt;...&lt;/span&gt;
	&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;c_iflag&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;=&lt;/span&gt; &lt;span class='o'&gt;~&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;IMAXBEL&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;IGNBRK&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;BRKINT&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;PARMRK&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ISTRIP&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;INLCR&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;IGNCR&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ICRNL&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;IXON&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
	&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;c_oflag&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;=&lt;/span&gt; &lt;span class='o'&gt;~&lt;/span&gt;&lt;span class='n'&gt;OPOST&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;c_lflag&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;=&lt;/span&gt; &lt;span class='o'&gt;~&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;ECHO&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ECHONL&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ICANON&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ISIG&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;IEXTEN&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
	&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;c_cflag&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;=&lt;/span&gt; &lt;span class='o'&gt;~&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;CSIZE&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;PARENB&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
	&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='n'&gt;c_cflag&lt;/span&gt; &lt;span class='o'&gt;|=&lt;/span&gt; &lt;span class='n'&gt;CS8&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;...&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;All that&amp;#8217;s left is to patch the tmux code to set those flags. A good patch would add a feature test to the tmux autoconf setup and/or provide a compatability macro, but in this case I simply add a Solaris-specific section to the code:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;	&lt;span class='k'&gt;struct&lt;/span&gt; &lt;span class='n'&gt;termios&lt;/span&gt; &lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;...&lt;/span&gt;
&lt;span class='cp'&gt;#ifdef __sun&lt;/span&gt;
	&lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;c_iflag&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;=&lt;/span&gt; &lt;span class='o'&gt;~&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;IMAXBEL&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;IGNBRK&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;BRKINT&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;PARMRK&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ISTRIP&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;INLCR&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;IGNCR&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ICRNL&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;IXON&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
	&lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;c_oflag&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;=&lt;/span&gt; &lt;span class='o'&gt;~&lt;/span&gt;&lt;span class='n'&gt;OPOST&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;c_lflag&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;=&lt;/span&gt; &lt;span class='o'&gt;~&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;ECHO&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ECHONL&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ICANON&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ISIG&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;IEXTEN&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
	&lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;c_cflag&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;=&lt;/span&gt; &lt;span class='o'&gt;~&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;CSIZE&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;PARENB&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
	&lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;c_cflag&lt;/span&gt; &lt;span class='o'&gt;|=&lt;/span&gt; &lt;span class='n'&gt;CS8&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='cp'&gt;#else&lt;/span&gt;
	&lt;span class='n'&gt;cfmakeraw&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='cp'&gt;#endif&lt;/span&gt;
	&lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;c_iflag&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;ICRNL&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;IXANY&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;tio&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;c_oflag&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;OPOST&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ONLCR&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='summary'&gt;Summary&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;cfmakeraw()&lt;/code&gt; is an extension to POSIX and thus not fully portable. If you use it, please consider including a compatability version for systems which do not implement it.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Solaris portability - flock()</title>
      <link>http://www.perkin.org.uk/posts/solaris-portability-flock.html</link>
      <pubDate>Tue, 08 Jan 2013 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/solaris-portability-flock.html</guid>
      <description>&lt;p&gt;This is the first of what I hope will be a regular series of posts looking at software portability when it comes to Solarish (Solaris, illumos, SmartOS etc.) systems. We will begin with &lt;code&gt;flock()&lt;/code&gt;, as it&amp;#8217;s what I happen to have been fixing today.&lt;/p&gt;

&lt;p&gt;The most recent version of &lt;a href='tmux.sourceforge.net/'&gt;tmux&lt;/a&gt; fails with the following errors:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;client.c: In function &amp;#39;client_get_lock&amp;#39;:
client.c:81:2: warning: implicit declaration of function &amp;#39;flock&amp;#39; [-Wimplicit-function-declaration]
client.c:81:20: error: &amp;#39;LOCK_EX&amp;#39; undeclared (first use in this function)
client.c:81:20: note: each undeclared identifier is reported only once for each function it appears in
client.c:81:28: error: &amp;#39;LOCK_NB&amp;#39; undeclared (first use in this function)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;from this section of code:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;&lt;span class='kt'&gt;int&lt;/span&gt;
&lt;span class='nf'&gt;client_get_lock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;char&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;lockfile&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;open&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfile&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;O_WRONLY&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;O_CREAT&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mo'&gt;0600&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
                &lt;span class='n'&gt;fatal&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;open failed&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;flock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;LOCK_EX&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;LOCK_NB&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;errno&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;EWOULDBLOCK&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
                &lt;span class='k'&gt;while&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;flock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;LOCK_EX&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;errno&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;EINTR&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
                        &lt;span class='cm'&gt;/* nothing */&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
                &lt;span class='n'&gt;close&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
                &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='p'&gt;}&lt;/span&gt;

        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This code is reasonably straight-forward, trying to create a lock on a file descriptor, and if it isn&amp;#8217;t able to waits until the lock is released then fails, ready for the calling function to retry.&lt;/p&gt;

&lt;p&gt;However, the &lt;code&gt;flock()&lt;/code&gt; routine is of BSD heritage and does not exist on Solaris. There used to be a compatability version as part of the &lt;code&gt;/usr/ucb&lt;/code&gt; environment, but that no longer exists in newer versions.&lt;/p&gt;

&lt;p&gt;Thankfully, there is an alternative interface which has existed for as long as &lt;code&gt;flock()&lt;/code&gt; but with the added benefit of being standardised by POSIX and thus much more portable - enter &lt;code&gt;fcntl()&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s look at how the two are similar-but-different, and then show how we can change this code to be more portable.&lt;/p&gt;

&lt;h2 id='flock_implementation'&gt;flock() implementation&lt;/h2&gt;

&lt;p&gt;As we can see from the NetBSD manual page below, &lt;code&gt;flock()&lt;/code&gt; is very simple, and this is probably the main reason why people choose to use it over &lt;code&gt;fcntl()&lt;/code&gt; for file locking.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;NAME
     flock -- apply or remove an advisory lock on an open file

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include &amp;lt;fcntl.h&amp;gt;

     #define   LOCK_SH   1    /* shared lock */
     #define   LOCK_EX   2    /* exclusive lock */
     #define   LOCK_NB   4    /* don&amp;#39;t block when locking */
     #define   LOCK_UN   8    /* unlock */

     int
     flock(int fd, int operation);
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;There isn&amp;#8217;t much to it, you call &lt;code&gt;flock()&lt;/code&gt; specifying either a shared or exclusive lock, with an option to make the call non-blocking. Afterwards you unlock the previously held lock.&lt;/p&gt;

&lt;p&gt;The tmux code in question uses &lt;code&gt;LOCK_NB&lt;/code&gt; for the initial call, then if that fails reverts to the default blocking operation so that the client can retry as soon as the lock is released.&lt;/p&gt;

&lt;h2 id='use_fcntl_instead'&gt;Use fcntl() instead!&lt;/h2&gt;

&lt;p&gt;In contrast to &lt;code&gt;flock()&lt;/code&gt;, setting up &lt;code&gt;fcntl()&lt;/code&gt; is a bit more involved as it allows finer-grained control over the locking.&lt;/p&gt;

&lt;h3 id='set_up_struct_flock'&gt;Set up struct flock&lt;/h3&gt;

&lt;p&gt;There is a &lt;code&gt;flock&lt;/code&gt; structure which controls the lock, defined as:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;&lt;span class='k'&gt;struct&lt;/span&gt; &lt;span class='n'&gt;flock&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='kt'&gt;off_t&lt;/span&gt;       &lt;span class='n'&gt;l_start&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;    &lt;span class='cm'&gt;/* starting offset */&lt;/span&gt;
        &lt;span class='kt'&gt;off_t&lt;/span&gt;       &lt;span class='n'&gt;l_len&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;      &lt;span class='cm'&gt;/* len = 0 means until end of file */&lt;/span&gt;
        &lt;span class='n'&gt;pid_t&lt;/span&gt;       &lt;span class='n'&gt;l_pid&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;      &lt;span class='cm'&gt;/* lock owner */&lt;/span&gt;
        &lt;span class='kt'&gt;short&lt;/span&gt;       &lt;span class='n'&gt;l_type&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;     &lt;span class='cm'&gt;/* lock type: read/write, etc. */&lt;/span&gt;
        &lt;span class='kt'&gt;short&lt;/span&gt;       &lt;span class='n'&gt;l_whence&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;   &lt;span class='cm'&gt;/* type of l_start */&lt;/span&gt;
&lt;span class='p'&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So, let&amp;#8217;s set that up:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;&lt;span class='kt'&gt;int&lt;/span&gt;
&lt;span class='nf'&gt;client_get_lock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;char&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;lockfile&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='p'&gt;{&lt;/span&gt;
	&lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='k'&gt;struct&lt;/span&gt; &lt;span class='n'&gt;flock&lt;/span&gt; &lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

	&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_start&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_len&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_type&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;F_WRLCK&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_whence&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;SEEK_SET&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Setting &lt;code&gt;l_start&lt;/code&gt; and &lt;code&gt;l_len&lt;/code&gt; both to 0 means &amp;#8216;lock the entire file&amp;#8217;, &lt;code&gt;l_whence&lt;/code&gt; of &lt;code&gt;SEEK_SET&lt;/code&gt; means we are setting absolute values rather than relative, and we set &lt;code&gt;l_type&lt;/code&gt; to be a write lock. If we wanted a read lock, we&amp;#8217;d use &lt;code&gt;F_RDLCK&lt;/code&gt; here instead.&lt;/p&gt;

&lt;p&gt;Note that &lt;code&gt;l_pid&lt;/code&gt; is only used for a &lt;code&gt;F_GETLK&lt;/code&gt; operation - we are only interested in attempting to set a lock, so it is left unset.&lt;/p&gt;

&lt;h3 id='add_fcntl_calls'&gt;Add fcntl() calls&lt;/h3&gt;

&lt;p&gt;The synopsis for &lt;code&gt;fcntl()&lt;/code&gt; is:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;&lt;span class='n'&gt;SYNOPSIS&lt;/span&gt;
     &lt;span class='cp'&gt;#include &amp;lt;fcntl.h&amp;gt;&lt;/span&gt;

     &lt;span class='kt'&gt;int&lt;/span&gt;
     &lt;span class='n'&gt;fcntl&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;fd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;cmd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and the commands available for file locking are (from BSD):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;&lt;span class='cp'&gt;#define F_GETLK         7               &lt;/span&gt;&lt;span class='cm'&gt;/* get record locking information */&lt;/span&gt;&lt;span class='cp' /&gt;
&lt;span class='cp'&gt;#define F_SETLK         8               &lt;/span&gt;&lt;span class='cm'&gt;/* set record locking information */&lt;/span&gt;&lt;span class='cp' /&gt;
&lt;span class='cp'&gt;#define F_SETLKW        9               &lt;/span&gt;&lt;span class='cm'&gt;/* F_SETLK; wait if blocked */&lt;/span&gt;&lt;span class='cp' /&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Note there is no &amp;#8216;clear lock&amp;#8217; command. To clear a lock, you use the &lt;code&gt;F_GETLK&lt;/code&gt; command with &lt;code&gt;l_type&lt;/code&gt; set to &lt;code&gt;F_UNLCK&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, to show how we would rewrite the &lt;code&gt;flock()&lt;/code&gt; instances to &lt;code&gt;fcntl()&lt;/code&gt; instead, I&amp;#8217;ve put them together below:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;&lt;span class='cp'&gt;#ifdef __sun&lt;/span&gt;
	&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fcntl&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;F_SETLK&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;errno&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;EAGAIN&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
		&lt;span class='k'&gt;while&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fcntl&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;F_SETLKW&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;errno&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;EINTR&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
			&lt;span class='cm'&gt;/* nothing */&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
		&lt;span class='n'&gt;close&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
		&lt;span class='k'&gt;return&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
	&lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='cp'&gt;#else&lt;/span&gt;
	&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;flock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;LOCK_EX&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;LOCK_NB&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;errno&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;EWOULDBLOCK&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
		&lt;span class='k'&gt;while&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;flock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;LOCK_EX&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;errno&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;EINTR&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
			&lt;span class='cm'&gt;/* nothing */&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
		&lt;span class='n'&gt;close&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
		&lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
	&lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='cp'&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As you can see, they are very similar, making it relatively straight-forward to rewrite code to use the more portable &lt;code&gt;fcntl()&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='an_important_note_on_semantics'&gt;An important note on semantics&lt;/h2&gt;

&lt;p&gt;There are two important difference between &lt;code&gt;flock()&lt;/code&gt; and &lt;code&gt;fcntl()&lt;/code&gt; you need to be aware of which may affect a simple conversion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;fcntl()&lt;/code&gt; locks are not held across a &lt;code&gt;fork()&lt;/code&gt;, so you cannot pass locks down to child processes.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;The semantics of &lt;code&gt;fcntl()&lt;/code&gt; are such that &lt;strong&gt;any&lt;/strong&gt; closure of a file descriptor in your application will release the locks held against that file. This is best illustrated with a lock on &lt;code&gt;/etc/passwd&lt;/code&gt; that gets released if you call &lt;code&gt;getpwname()&lt;/code&gt; as that opens and closes the &lt;code&gt;/etc/passwd&lt;/code&gt; file.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Generally such semantics do not apply, but you should be aware of them, and it always pays to carefully read the manual pages, preferably those from BSD.&lt;/p&gt;

&lt;h2 id='flock__fcntl_cheat_sheet'&gt;flock() -&amp;gt; fcntl() cheat sheet&lt;/h2&gt;

&lt;p&gt;To aid your own conversions, here are some further examples (without error checking for clarity) of &lt;code&gt;flock()&lt;/code&gt; and &lt;code&gt;fcntl()&lt;/code&gt; equivalents.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;&lt;span class='cp'&gt;#if defined(USING_FLOCK)&lt;/span&gt;

	&lt;span class='cm'&gt;/* Blocking */&lt;/span&gt;
	&lt;span class='n'&gt;flock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;LOCK_SH&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;  &lt;span class='c1'&gt;// Shared (read) lock&lt;/span&gt;
	&lt;span class='n'&gt;flock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;LOCK_EX&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;  &lt;span class='c1'&gt;// Exclusive (write) lock&lt;/span&gt;

	&lt;span class='cm'&gt;/* Non-blocking */&lt;/span&gt;
	&lt;span class='n'&gt;flock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;LOCK_SH&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;LOCK_NB&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;  &lt;span class='c1'&gt;// Shared (read) lock&lt;/span&gt;
	&lt;span class='n'&gt;flock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;LOCK_EX&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;LOCK_NB&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;  &lt;span class='c1'&gt;// Exclusive (write) lock&lt;/span&gt;

	&lt;span class='cm'&gt;/* Release */&lt;/span&gt;
	&lt;span class='n'&gt;flock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;LOCK_UN&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;

&lt;span class='cp'&gt;#elif defined(USING_FCNTL)&lt;/span&gt;

	&lt;span class='k'&gt;struct&lt;/span&gt; &lt;span class='n'&gt;flock&lt;/span&gt; &lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

	&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_start&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_len&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_whence&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;SEEK_SET&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

	&lt;span class='cm'&gt;/* Blocking */&lt;/span&gt;
	&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_type&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;F_RDLCK&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;fcntl&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;F_SETLKW&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;  &lt;span class='c1'&gt;// Shared (read) lock&lt;/span&gt;
	&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_type&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;F_WRLCK&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;fcntl&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;F_SETLKW&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;  &lt;span class='c1'&gt;// Exclusive (write) lock&lt;/span&gt;

	&lt;span class='cm'&gt;/* Non-blocking */&lt;/span&gt;
	&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_type&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;F_RDLCK&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;fcntl&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;F_SETLK&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;  &lt;span class='c1'&gt;// Shared (read) lock&lt;/span&gt;
	&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_type&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;F_WRLCK&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;fcntl&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;F_SETLK&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;  &lt;span class='c1'&gt;// Exclusive (write) lock&lt;/span&gt;

	&lt;span class='cm'&gt;/* Release */&lt;/span&gt;
	&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_type&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;F_UNLCK&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;fcntl&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lockfd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;F_GETLK&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;lock&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

&lt;span class='cp'&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='flock_wrapper'&gt;flock() wrapper&lt;/h2&gt;

&lt;p&gt;Alternatively, there is a &lt;code&gt;flock()&lt;/code&gt; wrapper which is used by the NetBSD toolchain, which you could include in a compatability library or so:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='c'&gt;&lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='nf'&gt;flock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;fd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;op&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
	&lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='n'&gt;rc&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

&lt;span class='cp'&gt;#if defined(F_SETLK) &amp;amp;&amp;amp; defined(F_SETLKW)&lt;/span&gt;
	&lt;span class='k'&gt;struct&lt;/span&gt; &lt;span class='n'&gt;flock&lt;/span&gt; &lt;span class='n'&gt;fl&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;};&lt;/span&gt;

	&lt;span class='k'&gt;switch&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;op&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;LOCK_EX&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;LOCK_SH&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;LOCK_UN&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
	&lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='n'&gt;LOCK_EX&lt;/span&gt;:
		&lt;span class='n'&gt;fl&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_type&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;F_WRLCK&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
		&lt;span class='k'&gt;break&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

	&lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='n'&gt;LOCK_SH&lt;/span&gt;:
		&lt;span class='n'&gt;fl&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_type&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;F_RDLCK&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
		&lt;span class='k'&gt;break&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

	&lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='n'&gt;LOCK_UN&lt;/span&gt;:
		&lt;span class='n'&gt;fl&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_type&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;F_UNLCK&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
		&lt;span class='k'&gt;break&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

	&lt;span class='nl'&gt;default:&lt;/span&gt;
		&lt;span class='n'&gt;errno&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;EINVAL&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
		&lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='p'&gt;}&lt;/span&gt;

	&lt;span class='n'&gt;fl&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;l_whence&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;SEEK_SET&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='n'&gt;rc&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;fcntl&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;op&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;LOCK_NB&lt;/span&gt; &lt;span class='o'&gt;?&lt;/span&gt; &lt;span class='n'&gt;F_SETLK&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;F_SETLKW&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;fl&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

	&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;rc&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;errno&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;EAGAIN&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
		&lt;span class='n'&gt;errno&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;EWOULDBLOCK&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='cp'&gt;#endif&lt;/span&gt;

	&lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;rc&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It might be handy if the illumos folks merged this, it would immediate fix at least 19 packages in the pkgsrc collection :)&lt;/p&gt;

&lt;h2 id='summary'&gt;Summary&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;flock()&lt;/code&gt; is simpler, and retains locks across &lt;code&gt;fork()&lt;/code&gt; and concurrent access boundaries, but at the cost of portability. Please try to use &lt;code&gt;fcntl()&lt;/code&gt; where possible, it isn&amp;#8217;t much harder to use, and makes your software run on more platforms.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>pkgsrc-2012Q4 illumos packages now available</title>
      <link>http://www.perkin.org.uk/posts/pkgsrc-2012Q4-packages-for-illumos.html</link>
      <pubDate>Sun, 06 Jan 2013 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/pkgsrc-2012Q4-packages-for-illumos.html</guid>
      <description>&lt;p&gt;In keeping with the regular quarterly pkgsrc releases, I&amp;#8217;m pleased to announce that packages from the pkgsrc-2012Q4 branch are now available for general illumos platforms.&lt;/p&gt;

&lt;p&gt;As usual, the quick start instructions are:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; curl -s http://pkgsrc.smartos.org/packages/illumos/bootstrap/bootstrap-2012Q4-illumos.tar.gz &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='go'&gt;    | gtar -zxf - -C /&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/opt/pkg/sbin:/opt/pkg/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin -y up
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin avail | wc -l
&lt;span class='go'&gt;    9518&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin search &amp;lt;package&amp;gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin -y install &amp;lt;package&amp;gt; &amp;lt;package...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;For those interested in helping to increase the number of packages available, the bulk build report for this set is available &lt;a href='http://pkgsrc.smartos.org/reports/2012Q4-illumos/20130106.1305/meta/report.html'&gt;here&lt;/a&gt;. It would be great to get past the 10,000 mark!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>SmartOS and the global zone</title>
      <link>http://www.perkin.org.uk/posts/smartos-and-the-global-zone.html</link>
      <pubDate>Fri, 23 Nov 2012 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/smartos-and-the-global-zone.html</guid>
      <description>&lt;p&gt;One of the most common issues new users of SmartOS face is understanding the role and design of the global zone. Often they will download SmartOS and try to start using it as they would any other Unix operating system, but quickly run into basic problems such as installing packages or adding users. However, SmartOS is not your usual operating system, and it is imperative that you understand two key principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SmartOS is specifically designed as an OS for running Virtual Machines&lt;/strong&gt;, not as a general purpose OS.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The global zone is effectively a read-only hypervisor&lt;/strong&gt;, and should only be used for creating and managing Virtual Machines. Everything else should be performed inside Virtual Machines.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I should be clear at this point that &lt;em&gt;I am specifically addressing the issue of downloading and running your own SmartOS installation&lt;/em&gt;. If you provision a SmartMachine from Joyent, then you are running inside a Virtual Machine, and this post does not apply - you are free to start serving up awesome applications!&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s look at a few aspects of the global zone which make it a great fit for its intended purpose, and help explain why it doesn&amp;#8217;t work as you might expect.&lt;/p&gt;

&lt;h2 id='the_global_zone_is_a_ramdisk'&gt;The global zone is a ramdisk&lt;/h2&gt;

&lt;p&gt;This is the key reason why things don&amp;#8217;t work as you might expect. SmartOS does not install to disk like other operating systems, instead it boots directly from USB/CD/PXE into a mostly read-only environment.&lt;/p&gt;

&lt;p&gt;Why is it done this way? There are a number of good reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Upgrades are trivial.&lt;/strong&gt; No more patching, just reboot into a new image!&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Increased disk space.&lt;/strong&gt; No wasted space on disk to hold the OS, all the space is dedicated to VMs and user data.&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Increased disk performance.&lt;/strong&gt; It&amp;#8217;s common with other systems to have your OS installed to a pair of mirrored disks and then pool the remaining disks for data. With SmartOS you can have all your disks in the same RAIDZ pool, increasing performance.&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Additional security.&lt;/strong&gt; Most of the system files are read-only, and &lt;code&gt;/etc&lt;/code&gt; is re-created on each boot, making it much harder to exploit.&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Increased stability.&lt;/strong&gt; Ever had your root disks start to fail and system commands no longer run? This doesn&amp;#8217;t happen on SmartOS.&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Much simpler to install and provision&lt;/strong&gt;, especially when you have a large number of machines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, what does this look like, and what are the implications?&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; zonename
&lt;span class='go'&gt;global&lt;/span&gt;
&lt;span class='gp'&gt;#&lt;/span&gt; df -h / /usr
&lt;span class='go'&gt;Filesystem             size   used  avail capacity  Mounted on&lt;/span&gt;
&lt;span class='go'&gt;/devices/ramdisk:a     264M   219M    45M    83%    /&lt;/span&gt;
&lt;span class='go'&gt;/devices/pseudo/lofi@0:1&lt;/span&gt;
&lt;span class='go'&gt;                       376M   354M    22M    95%    /usr&lt;/span&gt;
&lt;span class='gp'&gt;#&lt;/span&gt; lofiadm
&lt;span class='go'&gt;Block Device             File                           Options&lt;/span&gt;
&lt;span class='go'&gt;/dev/lofi/1              /usr.lgz                       Compressed(gzip)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The root file system is a ramdisk, and &lt;code&gt;/usr&lt;/code&gt; is a read-only loopback mount of a single compressed file held on the ramdisk.&lt;/p&gt;

&lt;p&gt;Apart from a few specific files and directories listed below, this means that &lt;strong&gt;you cannot change the global zone&lt;/strong&gt;. To emphasise this point further:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;You cannot add users.&lt;/strong&gt;&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;You cannot write anywhere under /usr.&lt;/strong&gt;&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;You cannot permanently store or change files under &lt;code&gt;/etc&lt;/code&gt;, &lt;code&gt;/root&lt;/code&gt;, ..&lt;/strong&gt;&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Changes to SMF services will be reset each reboot.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are plenty of other things you cannot do, but hopefully this gives you some idea of the restricted nature of the global zone environment.&lt;/p&gt;

&lt;p&gt;If you are looking for a general purpose OS to serve as a NAS etc, then you can do worse than give &lt;a href='http://omnios.omniti.com/'&gt;OmniOS&lt;/a&gt; a spin - it has most of the same features as SmartOS, but in a normal install-to-disk configuration.&lt;/p&gt;

&lt;p&gt;Having said all that, let&amp;#8217;s look at some ways you can manage the global zone, if you have settled on running SmartOS.&lt;/p&gt;

&lt;h2 id='so_what_can_i_do'&gt;So what &lt;strong&gt;can&lt;/strong&gt; I do?&lt;/h2&gt;

&lt;p&gt;Firstly, let&amp;#8217;s look at the key writeable areas:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;Filesystem             size   used  avail capacity  Mounted on&lt;/span&gt;
&lt;span class='go'&gt;zones                  2.0T   143M   1.8T     1%    /zones&lt;/span&gt;
&lt;span class='go'&gt;zones/var              2.0T   4.0G   1.8T     1%    /var&lt;/span&gt;
&lt;span class='go'&gt;zones/opt              2.0T    55K   1.8T     1%    /opt&lt;/span&gt;
&lt;span class='go'&gt;zones/usbkey           2.0T   154K   1.8T     1%    /usbkey&lt;/span&gt;
&lt;span class='go'&gt;/usbkey/shadow         1.8T   154K   1.8T     1%    /etc/shadow&lt;/span&gt;
&lt;span class='go'&gt;/usbkey/ssh            1.8T   154K   1.8T     1%    /etc/ssh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;zones&lt;/code&gt; is the big zpool which is spread across all your disks, and SmartOS will create a number of file systems on it for use in the global zone:&lt;/p&gt;

&lt;h3 id='zones'&gt;/zones&lt;/h3&gt;

&lt;p&gt;This is where your Virtual Machines are stored, the datasets used to create them, and some other key files related to zones. Don&amp;#8217;t mess around in here unless you know what you are doing.&lt;/p&gt;

&lt;h3 id='var'&gt;/var&lt;/h3&gt;

&lt;p&gt;We all like logs, so those are retained in &lt;code&gt;/var&lt;/code&gt; as normal, as well as various state files such as the current list of &lt;code&gt;imgadm&lt;/code&gt; datasets and the SSH host keys.&lt;/p&gt;

&lt;h3 id='opt'&gt;/opt&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;/opt&lt;/code&gt; is your main hook into more advanced setup of the global zone. SmartOS will import any SMF manifests it finds in &lt;code&gt;/opt/custom/smf&lt;/code&gt;, which allows you to implement &lt;code&gt;rc.local&lt;/code&gt; functionality as demonstrated in &lt;a href='https://gist.github.com/2606370'&gt;this gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As &lt;code&gt;/opt&lt;/code&gt; is writeable you can also install packages as per &lt;a href='http://wiki.smartos.org/display/DOC/Installing+pkgin'&gt;this wiki page&lt;/a&gt;, however you need to bear in mind that, as explained earlier, things such as adding users are not possible, so you may see various errors.&lt;/p&gt;

&lt;h3 id='usbkey'&gt;/usbkey&lt;/h3&gt;

&lt;p&gt;When you first boot SmartOS and go through the rudimentary installer the details you provide are stored in &lt;code&gt;/usbkey/config&lt;/code&gt;, which is used during boot to configure the machine. If you need to change any of those variables, this is the file you should edit.&lt;/p&gt;

&lt;p&gt;There are also some variables which aren&amp;#8217;t set up by default, so if you want to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install an &lt;code&gt;authorized_keys&lt;/code&gt; file for the root user.&lt;/li&gt;

&lt;li&gt;Set a keyboard map.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;then have a read of &lt;a href='/posts/smartos-global-zone-tweaks.html'&gt;this post&lt;/a&gt; I wrote a while ago to find out how to configure those.&lt;/p&gt;

&lt;h3 id='etcshadow_and_etcssh'&gt;/etc/shadow and /etc/ssh&lt;/h3&gt;

&lt;p&gt;In order to support some very basic configuration, a few &lt;code&gt;/etc&lt;/code&gt; files are their own mount points onto /usbkey so that changes to them are saved.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/etc/shadow&lt;/code&gt; so that you can change the root password.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;/etc/ssh&lt;/code&gt; is initially where the SSH host keys were stored, however they are now stored under /var/ssh so don&amp;#8217;t be surprised if this mount point disappears at some point.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='implementation'&gt;Implementation&lt;/h2&gt;

&lt;p&gt;While we&amp;#8217;re on the subject, let&amp;#8217;s complete this post with a look at how the global zone is implemented, for interested readers.&lt;/p&gt;

&lt;h3 id='grub'&gt;GRUB&lt;/h3&gt;

&lt;p&gt;There is a &lt;a href='http://wiki.smartos.org/display/DOC/Remotely+Upgrading+A+USB+Key+Based+Deployment'&gt;good wiki guide&lt;/a&gt; which describes how to mount the USB key. Once you have done that you can take a look at the GRUB configuration:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;: Assumes your current working directory is the USB key mountpoint.&lt;/span&gt;
&lt;span class='gp'&gt;#&lt;/span&gt; less boot/grub/menu.lst
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;span class='go'&gt;title Live 64-bit (text)&lt;/span&gt;
&lt;span class='go'&gt;   kernel /platform/i86pc/kernel/amd64/unix -B console=text,root_shadow=&amp;#39;&amp;lt;crypt&amp;gt;&amp;#39;,smartos=true&lt;/span&gt;
&lt;span class='go'&gt;   module /platform/i86pc/amd64/boot_archive&lt;/span&gt;

&lt;span class='go'&gt;title Live 64-bit (noinstall)&lt;/span&gt;
&lt;span class='go'&gt;   kernel /platform/i86pc/kernel/amd64/unix -B console=text,root_shadow=&amp;#39;&amp;lt;crypt&amp;gt;&amp;#39;,standalone=true,noimport=true&lt;/span&gt;
&lt;span class='go'&gt;   module /platform/i86pc/amd64/boot_archive&lt;/span&gt;
&lt;span class='go'&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;There are a few boot configuration variables which alter how the system is started, and you can see how they are used by grepping for them in the SMF init scripts under &lt;code&gt;/lib/svc&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id='root_shadowcrypt_string'&gt;root_shadow=&amp;#8217;crypt string&amp;#8217;&lt;/h4&gt;

&lt;p&gt;This configures the default root password prior to /etc/shadow being mounted, and changes for each release. If you need to know what it is, then browse &lt;a href='https://download.joyent.com/pub/iso/'&gt;the download site&lt;/a&gt; and look at the SINGLE_USER_ROOT_PASSWORD.release.txt which correlates with your &lt;code&gt;uname -v&lt;/code&gt; output, or if you wish you could generate your own password and paste the new crypted string in here.&lt;/p&gt;

&lt;p&gt;Alternatively as a convenience you can find the default root password inside the &lt;code&gt;platform&lt;/code&gt; directory:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; cat platform/root.password
&lt;span class='go'&gt;seitee3oome4aiPh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 id='smartostrue'&gt;smartos=true&lt;/h4&gt;

&lt;p&gt;This variable defines whether to perform the normal SmartOS global zone initialisation, such as mounting &lt;code&gt;/usbkey&lt;/code&gt; and configuring the system from the &lt;code&gt;/usbkey/config&lt;/code&gt; file (see &lt;code&gt;/lib/svc/method/fs-joyent&lt;/code&gt; and &lt;code&gt;/lib/svc/method/smartdc-config&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If left unset (like in the &amp;#8216;Live 64-bit (noinstall)&amp;#8217; boot option), these will not be performed. &lt;code&gt;standalone=true&lt;/code&gt; should be set in those cases to avoid trying to be a Joyent compute node.&lt;/p&gt;

&lt;h4 id='noimporttrue'&gt;noimport=true&lt;/h4&gt;

&lt;p&gt;Setting this will skip any configuration and mounting of zpools, and is useful for if you have issues during the first installation and need to check disks, etc.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s likely that you do not need to change any of these variables, and if you hit problems simply use the &lt;code&gt;noinstall&lt;/code&gt; boot option and figure things out from there.&lt;/p&gt;

&lt;h3 id='platform_image'&gt;Platform image&lt;/h3&gt;

&lt;p&gt;The only other files on the USB key are:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; find platform -type f
&lt;span class='go'&gt;platform/i86pc/kernel/amd64/unix&lt;/span&gt;
&lt;span class='go'&gt;platform/i86pc/amd64/boot_archive&lt;/span&gt;
&lt;span class='go'&gt;platform/i86pc/amd64/boot_archive.gitstatus&lt;/span&gt;
&lt;span class='go'&gt;platform/i86pc/amd64/boot_archive.manifest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;These are mostly self-explanatory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;unix&lt;/code&gt; is the SmartOS kernel.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;boot_archive&lt;/code&gt; is the ramdisk image containing the entire OS.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;boot_archive.gitstatus&lt;/code&gt; contains the tip revisions of the &lt;a href='https://github.com/joyent/'&gt;github repositories&lt;/a&gt; used to build that particular image.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;boot_archive.manifest&lt;/code&gt; contains MD5 checksums of the OS files.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='upgrades'&gt;Upgrades&lt;/h2&gt;

&lt;p&gt;Given we have just explained about the &lt;code&gt;platform&lt;/code&gt; directory, it is also worth pointing out that you do not have to reflash your USB key every time, which is great if your server is inaccessible. Instead, assuming your USB key is big enough, you can simply download the newest &lt;a href='https://download.joyent.com/pub/iso/platform-latest.tgz'&gt;platform-latest.tgz&lt;/a&gt; file, move the existing &lt;code&gt;platform&lt;/code&gt; directory out of the way, and unpack &lt;code&gt;platform-latest.tgz&lt;/code&gt; there instead. Doing this as an atomic operation is preferred, for example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;: As of writing this is 20121115T191935Z&lt;/span&gt;
&lt;span class='gp'&gt;#&lt;/span&gt; gtar zxf ~/platform-latest.tgz
&lt;span class='gp'&gt;#&lt;/span&gt; mv platform platform-&lt;span class='k'&gt;$(&lt;/span&gt;uname -v&lt;span class='k'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; mv platform-20121115T191935Z platform
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This avoids having no &lt;code&gt;platform&lt;/code&gt; directory, just in case you have a power cut at that exact point in time!&lt;/p&gt;

&lt;h2 id='summary'&gt;Summary&lt;/h2&gt;

&lt;p&gt;If you want to set up a file server or similar, then SmartOS is probably not for you. However, if you are interested in running Virtual Machines and are able to do all of your work inside them, then SmartOS is perfect for that purpose, and has a number of advantages over other operating systems.&lt;/p&gt;

&lt;p&gt;Hopefully this has been useful, even if it is to deter you from using SmartOS!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Setting up Samba on SmartOS</title>
      <link>http://www.perkin.org.uk/posts/setting-up-samba-on-smartos.html</link>
      <pubDate>Wed, 24 Oct 2012 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/setting-up-samba-on-smartos.html</guid>
      <description>&lt;p&gt;A frequent question on #smartos IRC is how to set up SmartOS as a file server. Due to the architecture of SmartOS and its focus on virtualisation, this isn&amp;#8217;t as easy as on other systems, and some parts are simply not supported at this time (e.g. NFS).&lt;/p&gt;

&lt;p&gt;This guide, therefore, is a simple way to get Samba up and running so that you can at least use a SmartOS machine as a file server, even if it&amp;#8217;s perhaps not the protocol you would initially choose.&lt;/p&gt;

&lt;h2 id='create_new_virtual_machine'&gt;Create new virtual machine&lt;/h2&gt;

&lt;p&gt;Let&amp;#8217;s start by creating a VM, here is what I use locally, you may want to tweak the settings for your environment. If you already have a suitable VM configured you can just skip this step.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Import the base1.8.1 image, though any base image will suffice.&lt;/span&gt;
&lt;span class='nv'&gt;$ &lt;/span&gt;imgadm update
&lt;span class='nv'&gt;$ &lt;/span&gt;imgadm import 55330ab4-066f-11e2-bd0f-434f2462fada

&lt;span class='c'&gt;# I store all my VM configs in this directory&lt;/span&gt;
&lt;span class='nv'&gt;$ &lt;/span&gt;mkdir /usbkey/vmcfg

&lt;span class='c'&gt;# vmadm configuration for &amp;#39;store&amp;#39; VM&lt;/span&gt;
&lt;span class='nv'&gt;$ &lt;/span&gt;vi /usbkey/vmcfg/store.json
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='json'&gt;&lt;span class='p'&gt;{&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;brand&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;joyent&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;zfs_io_priority&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='mi'&gt;30&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;image_uuid&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;55330ab4-066f-11e2-bd0f-434f2462fada&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;max_physical_memory&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='mi'&gt;256&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;quota&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='mi'&gt;750&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;alias&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;store&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;hostname&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;store&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;resolvers&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;193.178.223.141&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;208.72.84.24&amp;quot;&lt;/span&gt;
  &lt;span class='p'&gt;],&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;dns_domain&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;adsl.perkin.org.uk&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;quot;nics&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;
    &lt;span class='p'&gt;{&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;quot;nic_tag&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;admin&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;quot;ip&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;192.168.1.11&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;quot;netmask&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;255.255.255.0&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
      &lt;span class='nt'&gt;&amp;quot;gateway&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;192.168.1.1&amp;quot;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
  &lt;span class='p'&gt;]&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Create the VM&lt;/span&gt;
&lt;span class='nv'&gt;$ &lt;/span&gt;vmadm create -f /usbkey/vmcfg/store.json
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='install_samba_package'&gt;Install Samba package&lt;/h2&gt;

&lt;p&gt;Next, log in to the VM and install the required packages. These are not currently available from the default repository, so we will use the generic illumos package set:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nv'&gt;$ &lt;/span&gt;zlogin &amp;lt;uuid&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Download and unpack bootstrap kit&lt;/span&gt;
&lt;span class='nv'&gt;$ &lt;/span&gt;curl -s http://pkgsrc.smartos.org/packages/illumos/bootstrap/bootstrap-2012Q3-illumos.tar.gz &lt;span class='se'&gt;\&lt;/span&gt;
    | gtar -zxf - -C /
&lt;span class='nv'&gt;$ PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/opt/pkg/sbin:/opt/pkg/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;

&lt;span class='c'&gt;# Install latest Samba package (others are available if necessary)&lt;/span&gt;
&lt;span class='nv'&gt;$ &lt;/span&gt;pkgin -y up
&lt;span class='nv'&gt;$ &lt;/span&gt;pkgin -y install samba-3.6
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_samba'&gt;Configure Samba&lt;/h2&gt;

&lt;p&gt;This part will differ based on your requirements, here are a couple of simple examples.&lt;/p&gt;

&lt;h4 id='shared_guest_mount_with_full_readwrite_access'&gt;Shared guest mount with full read/write access&lt;/h4&gt;

&lt;p&gt;For if you just want somewhere to share stuff on a local network with no security.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Create shared mount user and mountpoint.&lt;/span&gt;
&lt;span class='nv'&gt;$ &lt;/span&gt;groupadd -g 500 store
&lt;span class='nv'&gt;$ &lt;/span&gt;useradd -u 500 -g 500 -c &lt;span class='s2'&gt;&amp;quot;Store user&amp;quot;&lt;/span&gt; -s /usr/bin/false -d /store store
&lt;span class='nv'&gt;$ &lt;/span&gt;mkdir /store
&lt;span class='nv'&gt;$ &lt;/span&gt;chown store:store /store
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Configure Samba&lt;/span&gt;
&lt;span class='nv'&gt;$ &lt;/span&gt;vi /etc/opt/pkg/samba/smb.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ini'&gt;&lt;span class='k'&gt;[global]&lt;/span&gt;
  &lt;span class='na'&gt;security&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;share&lt;/span&gt;
&lt;span class='s'&gt;  load printers = no&lt;/span&gt;
&lt;span class='s'&gt;  guest account = store&lt;/span&gt;

&lt;span class='c'&gt;; Comment out [homes] section&lt;/span&gt;

&lt;span class='k'&gt;[store]&lt;/span&gt;
  &lt;span class='na'&gt;path&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;/store&lt;/span&gt;
&lt;span class='s'&gt;  public = yes&lt;/span&gt;
&lt;span class='s'&gt;  only guest = yes&lt;/span&gt;
&lt;span class='s'&gt;  writable = yes&lt;/span&gt;
&lt;span class='s'&gt;  printable = no&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 id='shared_mount_with_peruser_access'&gt;Shared mount with per-user access&lt;/h4&gt;

&lt;p&gt;For a bit more fine-grained control.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Create per-user accounts and mountpoint.&lt;/span&gt;
&lt;span class='nv'&gt;$ &lt;/span&gt;groupadd -g 1000 alice
&lt;span class='nv'&gt;$ &lt;/span&gt;useradd -u 1000 -g 1000 -c &lt;span class='s2'&gt;&amp;quot;Alice&amp;quot;&lt;/span&gt; -s /usr/bin/false -d /store alice
&lt;span class='nv'&gt;$ &lt;/span&gt;groupadd -g 1001 bob
&lt;span class='nv'&gt;$ &lt;/span&gt;useradd -u 1001 -g 1001 -c &lt;span class='s2'&gt;&amp;quot;Bob&amp;quot;&lt;/span&gt; -s /usr/bin/false -d /store bob
&lt;span class='nv'&gt;$ &lt;/span&gt;mkdir /store
&lt;span class='nv'&gt;$ &lt;/span&gt;chmod 1777 /store
&lt;span class='nv'&gt;$ &lt;/span&gt;/opt/pkg/bin/smbpasswd -a alice
&lt;span class='nv'&gt;$ &lt;/span&gt;/opt/pkg/bin/smbpasswd -a bob
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Configure Samba&lt;/span&gt;
&lt;span class='nv'&gt;$ &lt;/span&gt;vi /etc/opt/pkg/samba/smb.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ini'&gt;&lt;span class='k'&gt;[global]&lt;/span&gt;
  &lt;span class='na'&gt;security&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;user&lt;/span&gt;
&lt;span class='s'&gt;  load printers = no&lt;/span&gt;

&lt;span class='c'&gt;; Comment out [homes] section&lt;/span&gt;

&lt;span class='k'&gt;[store]&lt;/span&gt;
  &lt;span class='na'&gt;path&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;/store&lt;/span&gt;
&lt;span class='s'&gt;  valid users = alice bob&lt;/span&gt;
&lt;span class='s'&gt;  public = no&lt;/span&gt;
&lt;span class='s'&gt;  writable = yes&lt;/span&gt;
&lt;span class='s'&gt;  printable = no&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Access will be via username and the password set with &lt;code&gt;smbpasswd&lt;/code&gt;. Users will be able to create files and read other user files, but will only be able to modify files they created.&lt;/p&gt;

&lt;h2 id='startup_scripts'&gt;Startup scripts&lt;/h2&gt;

&lt;p&gt;Okay, so I&amp;#8217;m lazy and whilst I should provide some SMF scripts and manifests for this, it&amp;#8217;s simpler to just write an &lt;code&gt;rc.d&lt;/code&gt; script! :-)&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nv'&gt;$ &lt;/span&gt;vi /etc/rc2.d/S99samba
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;$1&amp;quot;&lt;/span&gt; in
start&lt;span class='o'&gt;)&lt;/span&gt;
	&lt;span class='c'&gt;# Start up Samba daemons&lt;/span&gt;
	/opt/pkg/sbin/nmbd -D
	/opt/pkg/sbin/smbd -D
	;;
stop&lt;span class='o'&gt;)&lt;/span&gt;
	pkill -9 nmbd
	pkill -9 smbd
	;;
reload&lt;span class='o'&gt;)&lt;/span&gt;
	pkill -HUP nmbd
	pkill -HUP smbd
	;;
&lt;span class='k'&gt;esac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, start it up!&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nv'&gt;$ &lt;/span&gt;chmod +x /etc/rc2.d/S99samba
&lt;span class='nv'&gt;$ &lt;/span&gt;/etc/rc2.d/S99samba start
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='multicast_dns'&gt;Multicast DNS&lt;/h2&gt;

&lt;p&gt;In order for shares to automatically show up in e.g. the OSX Finder, you will need to be running some kind of mDNS service on the server.&lt;/p&gt;

&lt;p&gt;The easiest solution is to simply enable &lt;code&gt;dns/multicast&lt;/code&gt; in the zone, i.e.:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nv'&gt;$ &lt;/span&gt;svcadm &lt;span class='nb'&gt;enable &lt;/span&gt;dns/multicast
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This will then show up based on the hostname of the server, and clicking on it should show the &lt;code&gt;store&lt;/code&gt; mount we created.&lt;/p&gt;

&lt;h2 id='all_done'&gt;All done&lt;/h2&gt;

&lt;p&gt;I hope this proves useful!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>pkgsrc-2012Q3 packages for illumos</title>
      <link>http://www.perkin.org.uk/posts/pkgsrc-2012Q3-packages-for-illumos.html</link>
      <pubDate>Wed, 10 Oct 2012 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/pkgsrc-2012Q3-packages-for-illumos.html</guid>
      <description>&lt;p&gt;Continuing from my &lt;a href='/posts/9000-packages-for-smartos-and-illumos.html'&gt;previous bulk build for pkgsrc-2012Q2&lt;/a&gt; I&amp;#8217;m pleased to announce that packages from the pkgsrc-2012Q3 branch are now available.&lt;/p&gt;

&lt;p&gt;Quick start:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; curl -s http://pkgsrc.smartos.org/packages/illumos/bootstrap/bootstrap-2012Q3-illumos.tar.gz &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='go'&gt;    | gtar -zxf - -C /&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/opt/pkg/sbin:/opt/pkg/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin -y up
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin avail | wc -l
&lt;span class='go'&gt;    9542&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin search &amp;lt;package&amp;gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin -y install &amp;lt;package&amp;gt; &amp;lt;package...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As usual there have been many hundreds of updates since the previous branch, and hopefully the software you need is included. If not, please get involved! We welcome new contributors.&lt;/p&gt;

&lt;p&gt;The bootstrap kit and a number of packages have been tested successfully on OpenIndiana 151a and OmniOS.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Creating local SmartOS packages</title>
      <link>http://www.perkin.org.uk/posts/creating-local-smartos-packages.html</link>
      <pubDate>Thu, 23 Aug 2012 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/creating-local-smartos-packages.html</guid>
      <description>&lt;p&gt;Ok, so you have a &lt;a href='http://smartos.org/'&gt;SmartOS&lt;/a&gt; machine set up, and are using &lt;code&gt;pkgin&lt;/code&gt; to install packages. Now you may want to also handle your local software using the same tools, so that you can take advantage of easily installing and upgrading packages. This post describes how you can do this.&lt;/p&gt;

&lt;p&gt;We will be creating a hypothetical package &lt;code&gt;meminfo&lt;/code&gt;, containing a script of the same name which prints basic memory information, and just enough metadata for it to be understood by the packaging tools. This guide assumes you are running a standard dataset which includes packaging tools in &lt;code&gt;/opt/local/sbin&lt;/code&gt;, that is:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; /opt/local/sbin/pkg_info
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;should give you a list of currently installed packages.&lt;/p&gt;

&lt;h3 id='files_to_install'&gt;Files to install&lt;/h3&gt;

&lt;p&gt;First, let&amp;#8217;s start in a clean directory, and then create a &lt;code&gt;files&lt;/code&gt; sub-directory which will hold the files we want to package. The files in this directory will be installed relative to the packaging prefix, which for most SmartOS installs will be &lt;code&gt;/opt/local&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; mkdir package
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd &lt;/span&gt;package
&lt;span class='gp'&gt;$&lt;/span&gt; mkdir -p files/bin
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now we create the &lt;code&gt;meminfo&lt;/code&gt; script. You will probably just copy your binaries into place at this stage.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; vi files/bin/meminfo
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/usr/bin/bash&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# This is just a subset of &amp;#39;sm-summary&amp;#39; from the &amp;#39;smtools&amp;#39; package.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='nv'&gt;SM_UUID&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;zonename&lt;span class='k'&gt;)&lt;/span&gt;;
&lt;span class='nv'&gt;SM_ID&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;zoneadm list -p | awk -F: &lt;span class='s1'&gt;&amp;#39;{ print $1 }&amp;#39;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;;
&lt;span class='nv'&gt;SM_MEMCAP&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;kstat -p -c zone_caps -n lockedmem_zone_&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;SM_ID&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -s value | awk &lt;span class='s1'&gt;&amp;#39;{print $2/1024/1024 }&amp;#39;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;;
&lt;span class='nv'&gt;SM_MEMUSED&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;prstat -Z -s rss 1 1 | awk -v &lt;span class='nv'&gt;zone&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;SM_UUID&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;$8 ~ zone { printf(&amp;quot;%d&amp;quot;, $4 ) }&amp;#39;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;;
&lt;span class='nv'&gt;SM_MEMFREE&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;${SM_MEMCAP}-${SM_MEMUSED}&amp;quot;&lt;/span&gt; | bc&lt;span class='k'&gt;)&lt;/span&gt;;
cat &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;Memory (RSS) Cap    ${SM_MEMCAP}M&lt;/span&gt;
&lt;span class='s'&gt;Memory (RSS) Used   ${SM_MEMUSED}M&lt;/span&gt;
&lt;span class='s'&gt;Memory (RSS) Free   ${SM_MEMFREE}M&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ensure the script is executable!&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; chmod +x files/bin/meminfo
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally for this part, generate a &lt;code&gt;packlist&lt;/code&gt; file which simply contains a list of files we want packaged, relative to the &lt;code&gt;files&lt;/code&gt; directory:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cd &lt;/span&gt;files; find * -type f | sort&lt;span class='o'&gt;)&lt;/span&gt; &amp;gt;packlist
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;packlist&lt;/code&gt; file supports many directives which are lines beginning with &lt;code&gt;@&amp;lt;cmd&amp;gt;&lt;/code&gt;. These let you do things such as change file permissions once the file has been installed. See the &amp;#8216;PACKING LIST DETAILS&amp;#8217; section of &lt;a href='http://netbsd.gw.com/cgi-bin/man-cgi?pkg_create'&gt;&lt;code&gt;pkg_create(1)&lt;/code&gt;&lt;/a&gt; for more information.&lt;/p&gt;

&lt;h3 id='package_metadata'&gt;Package metadata&lt;/h3&gt;

&lt;p&gt;In order to successfully create a package, we need a few metadata files which describe the package.&lt;/p&gt;

&lt;h4 id='buildinfo'&gt;build-info&lt;/h4&gt;

&lt;p&gt;This file contains basic information about the package, and is primarily used to ensure that the package can be installed on the target machine. The minimum information required is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MACHINE_ARCH&lt;/code&gt;. On SmartOS this is either &lt;code&gt;i386&lt;/code&gt; or &lt;code&gt;x86_64&lt;/code&gt; depending upon whether you chose a &lt;code&gt;base/smartos&lt;/code&gt; or &lt;code&gt;base64/smartos64&lt;/code&gt; dataset. Attempting to install a package intended for one architecture with package tools built for a different architecture will work due to SmartOS being able to run both 32-bit and 64-bit applications, but you will get warnings when installing.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;OPSYS&lt;/code&gt;. On SmartOS this is &lt;code&gt;SunOS&lt;/code&gt;, i.e. the output of &lt;code&gt;uname -s&lt;/code&gt;.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;OS_VERSION&lt;/code&gt;. On SmartOS this is &lt;code&gt;5.11&lt;/code&gt;, i.e. the output of &lt;code&gt;uname -r&lt;/code&gt;.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;PKGTOOLS_VERSION&lt;/code&gt;. An integer describing the version of the &lt;code&gt;pkg_install&lt;/code&gt; tools required to understand this package. At the current time pkgsrc sets a base version of &lt;code&gt;20091115&lt;/code&gt; so just use this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The easiest way to generate this file is simply to get it from an existing package, for example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkg_info -X pkg_install &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='go'&gt;  | egrep &amp;#39;^(MACHINE_ARCH|OPSYS|OS_VERSION|PKGTOOLS_VERSION)&amp;#39; &amp;gt;build-info&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; cat build-info
&lt;span class='go'&gt;MACHINE_ARCH=i386&lt;/span&gt;
&lt;span class='go'&gt;OPSYS=SunOS&lt;/span&gt;
&lt;span class='go'&gt;OS_VERSION=5.11&lt;/span&gt;
&lt;span class='go'&gt;PKGTOOLS_VERSION=20091115&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 id='comment'&gt;comment&lt;/h4&gt;

&lt;p&gt;This is a short string describing the package which is shown in the default &lt;code&gt;pkg_info&lt;/code&gt; or &lt;code&gt;pkgin list&lt;/code&gt; output. Keep this short, preferably under 60 characters, so that it displays correctly in 80-column terminals.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Show basic memory information on SmartOS&amp;quot;&lt;/span&gt; &amp;gt;comment
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h4 id='description'&gt;description&lt;/h4&gt;

&lt;p&gt;This is a longer multi-line description of the package which is output by &lt;code&gt;pkg_info &amp;lt;package name&amp;gt;&lt;/code&gt; or &lt;code&gt;pkgin pkg-descr &amp;lt;package name&amp;gt;&lt;/code&gt;. Format this to 80-columns.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; cat &amp;gt;description &amp;lt;&amp;lt;EOF
&lt;span class='go'&gt;meminfo prints basic information about available memory on a SmartOS machine,&lt;/span&gt;
&lt;span class='go'&gt;listing the total memory size, used, and free.  The information provided&lt;/span&gt;
&lt;span class='go'&gt;should be understood in light of how memory is used and reported on SmartOS,&lt;/span&gt;
&lt;span class='go'&gt;for more information refer to:&lt;/span&gt;

&lt;span class='go'&gt;http://wiki.smartos.org/display/DOC/About+Memory+Usage+and+Capping&lt;/span&gt;
&lt;span class='go'&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So we should now have:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;build-info          # basic package information&lt;/span&gt;
&lt;span class='go'&gt;comment             # one-line comment&lt;/span&gt;
&lt;span class='go'&gt;description         # multi-line comment&lt;/span&gt;
&lt;span class='go'&gt;files/bin/meminfo   # the file we wish to package&lt;/span&gt;
&lt;span class='go'&gt;packlist            # package listing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='create_the_package'&gt;Create the package&lt;/h3&gt;

&lt;p&gt;We now have enough information to create a basic package. The magic invocation to perform the operation is:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkg_create -B build-info -c comment -d description -f packlist &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='go'&gt;  -I /opt/local -p files -U meminfo-1.0.tgz&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;-B&lt;/code&gt;, &lt;code&gt;-c&lt;/code&gt;, &lt;code&gt;-d&lt;/code&gt; and &lt;code&gt;-f&lt;/code&gt; arguments simply pull in the metadata files we&amp;#8217;ve written.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-I&lt;/code&gt; argument specifies the destination prefix. As we are creating a package outside of this prefix we need to tell &lt;code&gt;pkg_create&lt;/code&gt; of the ultimate destination.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-p&lt;/code&gt; argument is used in conjunction with &lt;code&gt;-I&lt;/code&gt; to tell pkg_create where our files to be packaged can be found.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-U&lt;/code&gt; argument means we should just create the package, and not register it.&lt;/p&gt;

&lt;p&gt;And finally, we provide the package file. The packaging tools understand version numbers, so we can just provide the file name and it will determine the package name and version from that.&lt;/p&gt;

&lt;p&gt;To verify the package, you can run:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkg_info -X meminfo-1.0.tgz
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nv'&gt;PKGNAME&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;meminfo-1.0
&lt;span class='nv'&gt;COMMENT&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;Show basic memory information on SmartOS
&lt;span class='nv'&gt;MACHINE_ARCH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;i386
&lt;span class='nv'&gt;OPSYS&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;SunOS
&lt;span class='nv'&gt;OS_VERSION&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;5.11
&lt;span class='nv'&gt;PKGTOOLS_VERSION&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;20091115
&lt;span class='nv'&gt;FILE_NAME&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;meminfo-1.0.tgz
&lt;span class='nv'&gt;FILE_SIZE&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;922
&lt;span class='nv'&gt;DESCRIPTION&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;meminfo prints basic information about available memory on a SmartOS machine,
&lt;span class='nv'&gt;DESCRIPTION&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;listing the total memory size, used, and free.  The information provided
&lt;span class='nv'&gt;DESCRIPTION&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;should be understood in light of how memory is used and reported on SmartOS,
&lt;span class='nv'&gt;DESCRIPTION&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;for &lt;/span&gt;more information refer to:
&lt;span class='nv'&gt;DESCRIPTION&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;
&lt;span class='nv'&gt;DESCRIPTION&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;http://wiki.smartos.org/display/DOC/About+Memory+Usage+and+Capping
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='installing'&gt;Installing&lt;/h3&gt;

&lt;p&gt;For a single machine, you can now simply install the package with:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkg_add meminfo-1.0.tgz
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you want to publish the package so that it is available to &lt;code&gt;pkgin&lt;/code&gt; you need to create a &lt;code&gt;pkg_summary&lt;/code&gt; file and put it alongside the package for download. This file is usually compressed to speed things up, and &lt;code&gt;pkgin&lt;/code&gt; supports both &lt;code&gt;.gz&lt;/code&gt; and &lt;code&gt;.bz2&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkg_info -X meminfo-1.0.tgz | gzip -9 &amp;gt;pkg_summary.gz
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;For example purposes I will simply use file://, but of course you can use http:// instead if you put the packages and pkg_summary file somewhere accessible:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; mkdir /var/tmp/packages
&lt;span class='gp'&gt;$&lt;/span&gt; cp meminfo-1.0.tgz pkg_summary.gz /var/tmp/packages
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Add this repository to &lt;code&gt;pkgin&lt;/code&gt; and reload:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;file:///var/tmp/packages&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt;/opt/local/etc/pkgin/repositories.conf
&lt;span class='gp'&gt;$&lt;/span&gt; sudo pkgin -fy up
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now the package should show up:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkgin avail | grep meminfo
&lt;span class='go'&gt;meminfo-1.0          Show basic memory information on SmartOS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and be installable:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo pkgin -y install meminfo
&lt;span class='gp'&gt;$&lt;/span&gt; /opt/local/bin/meminfo
&lt;span class='go'&gt;Memory (RSS) Cap    8192M&lt;/span&gt;
&lt;span class='go'&gt;Memory (RSS) Used   92M&lt;/span&gt;
&lt;span class='go'&gt;Memory (RSS) Free   8100M&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This covers the basics and should be enough to get started. As mentioned, there are many other options available, and I suggest that if you need additional functionality you take a look at the &lt;a href='http://netbsd.gw.com/cgi-bin/man-cgi?pkg_create'&gt;&lt;code&gt;pkg_create&lt;/code&gt;&lt;/a&gt; manual page, or simply use &lt;code&gt;pkg_info -X&lt;/code&gt; on more complicated packages to see what they do.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>7,000 binary packages for OSX Lion</title>
      <link>http://www.perkin.org.uk/posts/7000-packages-for-osx-lion.html</link>
      <pubDate>Tue, 10 Jul 2012 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/7000-packages-for-osx-lion.html</guid>
      <description>&lt;p&gt;For my &lt;a href='http://www.perkin.org.uk/posts/goodbye-oracle-hello-joyent.html'&gt;day job&lt;/a&gt; I build packages for our &lt;a href='http://smartos.org/'&gt;SmartOS&lt;/a&gt; operating system using pkgsrc. pkgsrc is a cross-platform package manager which began life as the FreeBSD ports system and was ported to NetBSD back in 1997. Since then it has been ported to many other different systems, 19 at the current count, one of which is OSX/Darwin.&lt;/p&gt;

&lt;p&gt;For the recent pkgsrc-2012Q2 release, I have performed a full bulk build on OSX Lion, and the result is 7,374 binary packages for you to use as an alternative to brew/macports/etc.&lt;/p&gt;

&lt;p&gt;To use them, run the following:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; curl http://pkgsrc.smartos.org/packages/Darwin/2012Q2/bootstrap.tar.gz &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='go'&gt;    | (cd /; sudo gnutar -zxpf -)&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/usr/pkg/sbin:/usr/pkg/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; sudo pkgin -y update
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin avail | wc -l
&lt;span class='go'&gt;    7374&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin search ...
&lt;span class='gp'&gt;$&lt;/span&gt; sudo pkgin -y install ...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;pkgin&lt;/code&gt; is a tool similar to &lt;code&gt;apt-get&lt;/code&gt; and allows you to easily search for and install/upgrade packages.&lt;/p&gt;

&lt;p&gt;Please let me know if you find them useful, and if you have any feedback.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>9,000 packages for SmartOS and illumos</title>
      <link>http://www.perkin.org.uk/posts/9000-packages-for-smartos-and-illumos.html</link>
      <pubDate>Mon, 09 Jul 2012 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/9000-packages-for-smartos-and-illumos.html</guid>
      <description>&lt;p&gt;At &lt;a href='http://www.joyent.com/'&gt;Joyent&lt;/a&gt;, we provide &lt;a href='http://smartos.org/'&gt;SmartOS&lt;/a&gt; users with a set of regularly updated binary packages which are tuned to work well on our operating system. The package manager we use, pkgsrc, does not yet come with native support for e.g. SMF, and so we provide a limited set of packages, ensuring that those we do we provide include such features.&lt;/p&gt;

&lt;p&gt;However, often users will want packages which are not yet included in our build set, and so to assist those users we have performed a full bulk build of the unmodified pkgsrc-2012Q2 release, which resulted in well over 9,000 binary packages to choose from.&lt;/p&gt;

&lt;p&gt;In addition, thanks to binary compatibility, these packages can also be used on your illumos distribution of choice (please let me know if this is not the case!) if your native package manager does not provide the software you want.&lt;/p&gt;

&lt;p&gt;Note that these packages do not come with SMF support, and may be different from our official packages in terms of build options, etc. Also, to avoid conflict with our official packages, these have been built under a different prefix:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;/opt/pkg	# main prefix&lt;/span&gt;
&lt;span class='go'&gt;/etc/opt/pkg	# configuration files&lt;/span&gt;
&lt;span class='go'&gt;/var/opt/pkg	# transient files&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;compared to our official packages:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='go'&gt;/opt/local	# main prefix&lt;/span&gt;
&lt;span class='go'&gt;/opt/local/etc	# configuration files&lt;/span&gt;
&lt;span class='go'&gt;/var		# transient files&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To use them, run the following:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; For SmartOS use the original build.
&lt;span class='gp'&gt;$&lt;/span&gt; curl http://pkgsrc.smartos.org/packages/SmartOS/2012Q2/bootstrap.tar.gz &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='go'&gt;    | gzip -dc | (cd /; sudo tar -xpf -)&lt;/span&gt;

&lt;span class='gp'&gt;#&lt;/span&gt; For other illumos, use the updated build which should work, but has fewer
&lt;span class='gp'&gt;#&lt;/span&gt; packages, and you will need to ignore warnings about x86_64 !&lt;span class='o'&gt;=&lt;/span&gt; i386.
&lt;span class='gp'&gt;$&lt;/span&gt; curl http://pkgsrc.smartos.org/packages/SmartOS/2012Q2j1/bootstrap.tar.gz &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='go'&gt;    | gzip -dc | (cd /; sudo tar -xpf -)&lt;/span&gt;

&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/opt/pkg/sbin:/opt/pkg/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; sudo pkgin -y update
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin avail | wc -l
&lt;span class='go'&gt;    9401&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin search ...
&lt;span class='gp'&gt;$&lt;/span&gt; sudo pkgin -y install ...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;What&amp;#8217;s included? Here are just a few highlights:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer tools&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PHP: 5.4.4, 5.3.14 + ~100 modules for each&lt;/li&gt;

&lt;li&gt;Perl: 5.14.2 + 1,780 modules&lt;/li&gt;

&lt;li&gt;Python: 3.2.3, 3.1.5, 2.7.3, 2.6.8, 2.5.6 + ~260 modules for 2.x&lt;/li&gt;

&lt;li&gt;Ruby: 1.9.3p194, 1.9.2pl320, 1.8.7.358 + ~450 modules for each&lt;/li&gt;

&lt;li&gt;Editors: (vim 7.2, emacs 23.4 and 24.1, xemacs 21.4)&lt;/li&gt;

&lt;li&gt;Revision control: (git 1.7.10.5, mercurial 2.2.2, bzr 2.5, svn 1.6.17)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Web stack&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apache: 2.4.2, 2.2.22, 2.0.64, 1.3.42 + modules&lt;/li&gt;

&lt;li&gt;MySQL: 5.5.25, 5.1.63, 5.0.96&lt;/li&gt;

&lt;li&gt;PostgreSQL: 9.1.3, 9.0.7, 8.3.18&lt;/li&gt;

&lt;li&gt;Wordpress 3.4.1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Desktop&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GNOME 2.32.1 (not complete)&lt;/li&gt;

&lt;li&gt;KDE 4.8.4 (not complete)&lt;/li&gt;

&lt;li&gt;XFCE 4.6.1&lt;/li&gt;

&lt;li&gt;evilwm 1.1.0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;plus thousands of miscellaneous utilities.&lt;/p&gt;

&lt;p&gt;The long-term goal of course is to integrate all of our changes back into the upstream pkgsrc repository and eventually provide a single package repository, and we will continue to work on that endeavour.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Goodbye Oracle, Hello Joyent!</title>
      <link>http://www.perkin.org.uk/posts/goodbye-oracle-hello-joyent.html</link>
      <pubDate>Mon, 07 May 2012 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/goodbye-oracle-hello-joyent.html</guid>
      <description>&lt;p&gt;Back in 2001 when I started working for the BBC I was given a Sun Ultra 10 workstation running Solaris 8 and &lt;a href='https://en.wikipedia.org/wiki/Common_Desktop_Environment'&gt;CDE&lt;/a&gt; to do my job. As a Linux/FreeBSD user at the time, and someone accustomed to things such as a working vi implementation, recursive grep and Window Maker, this came as something of a culture shock, and it wasn&amp;#8217;t long before I was compiling my own software in a rapid attempt to build and configure a more usable desktop environment - or at least one I was more comfortable in.&lt;/p&gt;

&lt;p&gt;Building all that software by hand quickly became tedious, and so I was delighted to find that &lt;a href='http://blog.netbsd.org/tnf/entry/interview_with_christos_zoulas'&gt;Christos Zoulas&lt;/a&gt; had written a bunch of portability glue, known as Zoularis, which allowed pkgsrc (similar to the FreeBSD ports system I was used to) to be used on Solaris.&lt;/p&gt;

&lt;p&gt;It was still early days, however, and so over the next few years I and others helped to improve Solaris support in pkgsrc. By 2004 we had over &lt;a href='http://mail-index.netbsd.org/pkgsrc-bulk/2004/05/10/0001.html'&gt;1500&lt;/a&gt; packages building on Solaris 9/SPARC using the Sun Studio compiler, and in 2010 there were &lt;a href='http://www.perkin.org.uk/posts/apt-get-and-5000-packages-for-solaris10x86.html'&gt;5000&lt;/a&gt; packages for Solaris 10/x86, along with a native SFW package including pkgin (an &amp;#8220;apt-get&amp;#8221; clone), making it easy to get up and running.&lt;/p&gt;

&lt;p&gt;It was always something of a disappointment to me though that pkgsrc on Solaris wasn&amp;#8217;t more widely deployed as I felt it provided major benefits over Blastwave or IPS. So it was great to see &lt;a href='http://twitter.com/mamash'&gt;Filip Hajný&lt;/a&gt; of &lt;a href='http://www.joyent.com/'&gt;Joyent&lt;/a&gt; join the pkgsrc developers in 2009 for his work on Solaris with Joyent using pkgsrc internally.&lt;/p&gt;

&lt;p&gt;Since then they have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;hired a &lt;a href='http://dtrace.org/blogs/bmc/2010/07/30/hello-joyent/'&gt;number&lt;/a&gt; &lt;a href='http://dtrace.org/blogs/jerry/2010/09/23/joyent-wow/'&gt;of&lt;/a&gt; &lt;a href='http://dtrace.org/blogs/dap/2010/11/17/joining-joyent/'&gt;fantastic&lt;/a&gt; &lt;a href='http://dtrace.org/blogs/rm/2010/12/29/started-at-joyent/'&gt;engineers&lt;/a&gt; from the ashes of Sun Microsystems, who have&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;ported &lt;a href='http://www.linux-kvm.org/page/Main_Page'&gt;KVM&lt;/a&gt; to their &lt;a href='http://smartos.org/'&gt;SmartOS&lt;/a&gt; descendant of Solaris, making it a clear differentiator in the cloud computing arena (DTrace+ZFS+Zones+KVM is the perfect combination for multi-tenancy environments), as well as&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;taken stewardship of &lt;a href='http://nodejs.org/'&gt;node.js&lt;/a&gt; and again hired the &lt;a href='http://tinyclouds.org/'&gt;most&lt;/a&gt; &lt;a href='http://izs.me/'&gt;prominent&lt;/a&gt; engineers involved in that project&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and thus over that time my desire to work there has only increased.&lt;/p&gt;

&lt;p&gt;So, I am obviously delighted to say that today is my first day working for Joyent, focusing on making pkgsrc work even better on SmartOS.&lt;/p&gt;

&lt;p&gt;It isn&amp;#8217;t just the people and the technology which attracted me, though. A recent Twitter post by ex-Sun CEO and co-founder &lt;a href='https://en.wikipedia.org/wiki/Scott_McNealy'&gt;Scott McNealy&lt;/a&gt; says it well:&lt;/p&gt;
&lt;div class='postimg'&gt;
  &lt;img alt='Joyent continue Sun spirit' src='http://www.perkin.org.uk/files/images/scottm-tweet.png' /&gt;
&lt;/div&gt;
&lt;p&gt;As a long time fan of Sun (I got over the initial shock of Solaris) who was fortunate enough to work there, and as someone who experienced the fantastic company culture of MySQL AB, it is this chance to again join an engineering-driven company that &amp;#8220;kicks butt, has fun, doesn&amp;#8217;t cheat, loves its customers, changes computing forever&amp;#8221; which excites me the most.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s just hope Joyent don&amp;#8217;t turn out &lt;em&gt;exactly&lt;/em&gt; the same as Sun Microsystems ;)&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>SmartOS global zone tweaks</title>
      <link>http://www.perkin.org.uk/posts/smartos-global-zone-tweaks.html</link>
      <pubDate>Fri, 13 Apr 2012 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/smartos-global-zone-tweaks.html</guid>
      <description>&lt;p&gt;The basic premise behind &lt;a href='http://smartos.org/'&gt;SmartOS&lt;/a&gt; is to provide a netbooted global zone, and then do actual work inside KVM or zone-based virtual machines. This has a number of advantages, not least that it&amp;#8217;s trivial to upgrade to a newer release - you simply boot a newer image.&lt;/p&gt;

&lt;p&gt;However, the read-only nature of the global zone means that if you want to make changes to the global zone, then they need to be read from permanent storage, rather than making changes as you would normally.&lt;/p&gt;

&lt;p&gt;SmartOS creates a &lt;code&gt;/usbkey&lt;/code&gt; file system on stable storage which holds configuration for the global zone, and an init script &lt;code&gt;/lib/svc/method/smartdc-config&lt;/code&gt; which sources the file &lt;code&gt;/usbkey/config&lt;/code&gt; for configuration details. By default this will mostly include details you provided at install time, however there are additional values you can set to customise the global zone further.&lt;/p&gt;

&lt;p&gt;Here are a couple that I have found, and need for my personal use.&lt;/p&gt;

&lt;h2 id='upload_a_root_authorized_keys_file'&gt;Upload a root authorized_keys file&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;root&lt;/code&gt; user&amp;#8217;s home directory is provided from the ramdisk, so any changes you make will be wiped out on the next boot. This is presumably so that newer images can make changes to the shell rc files, for example to update &lt;code&gt;$PATH&lt;/code&gt; without worrying about all users having to merge these changes.&lt;/p&gt;

&lt;p&gt;However, I&amp;#8217;m not one for typing in passwords all day, so in order to store a &lt;code&gt;/root/.ssh/authorized_keys&lt;/code&gt; file you can do this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;mkdir -p /usbkey/config.inc
&lt;span class='c'&gt;# paste your key into this file&lt;/span&gt;
vi /usbkey/config.inc/authorized_keys
&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;root_authorized_keys_file=authorized_keys&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt;/usbkey/config
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;root_authorized_keys_file&lt;/code&gt; variable points to a file in &lt;code&gt;/usbkey/config.inc&lt;/code&gt;, you can of course change the name if you wish.&lt;/p&gt;

&lt;h2 id='set_a_keyboard_map'&gt;Set a keyboard map&lt;/h2&gt;

&lt;p&gt;By default a US keymap will be loaded for the console, if you want to use a different one then find a suitable layout in &lt;code&gt;/usr/share/lib/keytables/type_6&lt;/code&gt; (in my case &lt;code&gt;uk&lt;/code&gt;) and then:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;default_keymap=uk&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt;/usbkey/config
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='look_for_more_tweaks'&gt;Look for more tweaks&lt;/h2&gt;

&lt;p&gt;As of time of writing (&lt;code&gt;joyent_20120405T204624Z&lt;/code&gt;), these two appear to be the only tweaks available which aren&amp;#8217;t already used by default, however this may change in the future. To see if there are any newer ones available, you can:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;grep CONFIG_ /lib/svc/method/smartdc-config
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and then have a deeper look into the script to see how they are used ;-)&lt;/p&gt;

&lt;h2 id='run_adhoc_scripts'&gt;Run ad-hoc scripts&lt;/h2&gt;

&lt;p&gt;Note that while you may be tempted to think &amp;#8220;aha, it&amp;#8217;s just a shell script, I can use it like &lt;code&gt;rc.local&lt;/code&gt;&amp;#8221;, you can&amp;#8217;t - it&amp;#8217;s explicitly parsed into variables, and trying to put commands in will just break the init script.&lt;/p&gt;

&lt;p&gt;However, the &lt;code&gt;/lib/svc/method/manifest-import&lt;/code&gt; script does import any SMF manifests it finds in &lt;code&gt;/opt/custom/smf&lt;/code&gt;, so if you want to run arbitrary scripts, then have a look at &lt;a href='https://twitter.com/#!/ryancnelson'&gt;@ryancnelson&lt;/a&gt;&amp;#8217;s &lt;a href='http://www.psychicfriends.net/blog/archives/2012/03/21/smartosorg_run_things_at_boot.html'&gt;example&lt;/a&gt; and modify to suit your tastes.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Automated VirtualBox SmartOS installs</title>
      <link>http://www.perkin.org.uk/posts/automated-virtualbox-smartos-installs.html</link>
      <pubDate>Thu, 12 Apr 2012 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/automated-virtualbox-smartos-installs.html</guid>
      <description>&lt;p&gt;This is a quick script I wrote to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download the latest live ISO image of &lt;a href='http://smartos.org/'&gt;SmartOS&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;Create a VirtualBox VM, or update an existing VM with the latest ISO&lt;/li&gt;

&lt;li&gt;Configure the VM with a zones disk, and boot it!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the first install you&amp;#8217;ll need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure the network (likely just &amp;#8220;dhcp&amp;#8221;)&lt;/li&gt;

&lt;li&gt;Add &lt;code&gt;c0d0&lt;/code&gt; as the zones disk&lt;/li&gt;

&lt;li&gt;Set a root password&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After that it will just update the live ISO and use existing settings. By default it will create a port forward so that you can &lt;code&gt;ssh -p 8322
root@localhost&lt;/code&gt; into the VM.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s the script in full (or you can download it &lt;a href='http://www.perkin.org.uk/files/mksmartvm'&gt;here&lt;/a&gt;):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Configurables:&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;#  - Disk size is in GB&lt;/span&gt;
&lt;span class='c'&gt;#  - Memory size is in MB&lt;/span&gt;
&lt;span class='c'&gt;#  - SSH port is the local forwarded port to the VM:22&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='nv'&gt;disksize&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;32&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;memsize&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;1024&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;sshport&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;8322&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;vmname&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;SmartOS&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;dlsite&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;https://download.joyent.com/pub/iso&amp;quot;&lt;/span&gt;

&lt;span class='nv'&gt;vboxdir&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;VBoxManage list systemproperties &lt;span class='se'&gt;\&lt;/span&gt;
            | awk &lt;span class='s1'&gt;&amp;#39;/^Default.machine.folder/ { print $4 }&amp;#39;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Find a suitable md5sum program.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='k'&gt;if &lt;/span&gt;&lt;span class='nb'&gt;type &lt;/span&gt;md5 &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;md5sum&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;md5&amp;#39;&lt;/span&gt;
    &lt;span class='nv'&gt;column&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;NF&amp;#39;&lt;/span&gt;
&lt;span class='k'&gt;elif &lt;/span&gt;&lt;span class='nb'&gt;type &lt;/span&gt;digest &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt;
     digest md5 /dev/null &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;md5sum&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;digest md5&amp;#39;&lt;/span&gt;
    &lt;span class='nv'&gt;column&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;NF&amp;#39;&lt;/span&gt;
&lt;span class='k'&gt;elif &lt;/span&gt;&lt;span class='nb'&gt;type &lt;/span&gt;digest &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt;
     digest -a md5 /dev/null &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;md5sum&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;digest -a md5&amp;#39;&lt;/span&gt;
    &lt;span class='nv'&gt;column&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;1&amp;#39;&lt;/span&gt;
&lt;span class='k'&gt;elif &lt;/span&gt;&lt;span class='nb'&gt;type &lt;/span&gt;md5sum &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;md5sum&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;md5sum&amp;#39;&lt;/span&gt;
    &lt;span class='nv'&gt;column&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;1&amp;#39;&lt;/span&gt;
&lt;span class='k'&gt;elif &lt;/span&gt;&lt;span class='nb'&gt;type &lt;/span&gt;openssl &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt;
     openssl md5 -hex /dev/null &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;md5sum&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;openssl md5 -hex&amp;#39;&lt;/span&gt;
    &lt;span class='nv'&gt;column&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;NF&amp;#39;&lt;/span&gt;
&lt;span class='k'&gt;else&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;ERROR: Sorry, could not find an md5 program&amp;quot;&lt;/span&gt; 1&amp;gt;&amp;amp;2
    &lt;span class='nb'&gt;exit &lt;/span&gt;1
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Download MD5 file and parse it for the latest ISO image and checksum&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
curl -o smartos-sums.txt &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;dlsite&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/md5sums.txt 2&amp;gt;/dev/null
&lt;span class='nv'&gt;latest_md5&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;awk &lt;span class='s1'&gt;&amp;#39;/latest.iso/ { print $1 }&amp;#39;&lt;/span&gt; smartos-sums.txt&lt;span class='k'&gt;)&lt;/span&gt;
&lt;span class='nv'&gt;smartos_version&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;sed -ne &lt;span class='s2'&gt;&amp;quot;/^${latest_md5}/s/.*-\(.*\).iso/\1/p&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
                    smartos-sums.txt&lt;span class='k'&gt;)&lt;/span&gt;
&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; -z &lt;span class='s2'&gt;&amp;quot;${smartos_version}&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;  &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;ERROR: Couldn&amp;#39;t determine latest version&amp;quot;&lt;/span&gt;
  &lt;span class='nb'&gt;exit &lt;/span&gt;1
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Download the latest ISO image and verify&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
mkdir -p &lt;span class='s2'&gt;&amp;quot;${vboxdir}/${vmname}&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; ! -f &lt;span class='s2'&gt;&amp;quot;${vboxdir}/${vmname}/smartos-${smartos_version}.iso&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;  &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Downloading ${dlsite}/smartos-${smartos_version}.iso&amp;quot;&lt;/span&gt;
  curl -o &lt;span class='s2'&gt;&amp;quot;${vboxdir}/${vmname}/smartos-${smartos_version}.iso&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
          &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;dlsite&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/smartos-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;smartos_version&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.iso
  &lt;span class='nv'&gt;dl_md5&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(${&lt;/span&gt;&lt;span class='nv'&gt;md5sum&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;${vboxdir}/${vmname}/smartos-${smartos_version}.iso&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
             | awk &lt;span class='s1'&gt;&amp;#39;{ print $&amp;#39;&lt;/span&gt;&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;column&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39; }&amp;#39;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; -z &lt;span class='s2'&gt;&amp;quot;${dl_md5}&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;ERROR: Couldn&amp;#39;t fetch ISO image&amp;quot;&lt;/span&gt;
    &lt;span class='nb'&gt;exit &lt;/span&gt;1
  &lt;span class='k'&gt;fi&lt;/span&gt;
&lt;span class='k'&gt;  if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;${latest_md5}&amp;quot;&lt;/span&gt; !&lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;${dl_md5}&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;ERROR: md5 checksums do not match&amp;quot;&lt;/span&gt;
    &lt;span class='nb'&gt;exit &lt;/span&gt;1
  &lt;span class='k'&gt;fi&lt;/span&gt;
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Create VirtualBox VM&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Creating/Updating Virtual Machine&amp;quot;&lt;/span&gt;
VBoxManage showvminfo &lt;span class='s2'&gt;&amp;quot;${vmname}&amp;quot;&lt;/span&gt; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='nv'&gt;$?&lt;/span&gt; -eq 0 &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
    &lt;span class='c'&gt;# VM already exists, just update the ISO image&lt;/span&gt;
    VBoxManage storageattach &lt;span class='s2'&gt;&amp;quot;${vmname}&amp;quot;&lt;/span&gt; --storagectl &lt;span class='s2'&gt;&amp;quot;IDE Controller&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
      --port 1 --device 0 --type dvddrive &lt;span class='se'&gt;\&lt;/span&gt;
      --medium &lt;span class='s2'&gt;&amp;quot;${vboxdir}/${vmname}/smartos-${smartos_version}.iso&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;else&lt;/span&gt;
    &lt;span class='c'&gt;# Create the VM&lt;/span&gt;
    VBoxManage createvm --name &lt;span class='s2'&gt;&amp;quot;${vmname}&amp;quot;&lt;/span&gt; --ostype OpenSolaris_64 --register
    VBoxManage storagectl &lt;span class='s2'&gt;&amp;quot;${vmname}&amp;quot;&lt;/span&gt; --name &lt;span class='s2'&gt;&amp;quot;IDE Controller&amp;quot;&lt;/span&gt; --add ide

    &lt;span class='c'&gt;# Attach the ISO image&lt;/span&gt;
    VBoxManage storageattach &lt;span class='s2'&gt;&amp;quot;${vmname}&amp;quot;&lt;/span&gt; --storagectl &lt;span class='s2'&gt;&amp;quot;IDE Controller&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
      --port 1 --device 0 --type dvddrive &lt;span class='se'&gt;\&lt;/span&gt;
      --medium &lt;span class='s2'&gt;&amp;quot;${vboxdir}/${vmname}/smartos-${smartos_version}.iso&amp;quot;&lt;/span&gt;

    &lt;span class='c'&gt;# Create and attach the zone disk&lt;/span&gt;
    VBoxManage createhd --filename &lt;span class='s2'&gt;&amp;quot;${vboxdir}/${vmname}/smartos-zones.vdi&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
      --size &lt;span class='k'&gt;$(&lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;${disksize}*1024&amp;quot;&lt;/span&gt; | bc&lt;span class='k'&gt;)&lt;/span&gt;
    VBoxManage storageattach &lt;span class='s2'&gt;&amp;quot;${vmname}&amp;quot;&lt;/span&gt; --storagectl &lt;span class='s2'&gt;&amp;quot;IDE Controller&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
      --port 0 --device 0 --type hdd &lt;span class='se'&gt;\&lt;/span&gt;
      --medium &lt;span class='s2'&gt;&amp;quot;${vboxdir}/${vmname}/smartos-zones.vdi&amp;quot;&lt;/span&gt;

    &lt;span class='c'&gt;# Set misc settings&lt;/span&gt;
    VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${vmname}&amp;quot;&lt;/span&gt; --boot1 dvd --boot2 disk --boot3 none
    VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${vmname}&amp;quot;&lt;/span&gt; --memory &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;memsize&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
    VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${vmname}&amp;quot;&lt;/span&gt; --natpf1 &lt;span class='s2'&gt;&amp;quot;SSH,tcp,,${sshport},,22&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Start it up&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Starting Virtual Machine&amp;quot;&lt;/span&gt;
VirtualBox --startvm &lt;span class='s2'&gt;&amp;quot;${vmname}&amp;quot;&lt;/span&gt; &amp;amp;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Hopefully there will be a follow-up post which updates my &lt;a href='http://www.perkin.org.uk/posts/pkgsrc-on-solaris.html'&gt;pkgsrc on Solaris&lt;/a&gt; for SmartOS, including zone setup etc.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>iptables script for Debian / Ubuntu</title>
      <link>http://www.perkin.org.uk/posts/iptables-script-for-debian-ubuntu.html</link>
      <pubDate>Fri, 30 Mar 2012 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/iptables-script-for-debian-ubuntu.html</guid>
      <description>&lt;p&gt;Most Linux distributions seem to have their own way of handling iptables. Red Hat based distributions come with an init script &lt;code&gt;/etc/init.d/iptables&lt;/code&gt; which saves/restores configuration and allows you to check the status.&lt;/p&gt;

&lt;p&gt;Debian / Ubuntu come with .. nothing.&lt;/p&gt;

&lt;p&gt;So, there is a plethora of advice and ways of setting iptables up them, and this is mine.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s a simple shell script which is installed to &lt;code&gt;/etc/network/if-pre-up.d/iptables&lt;/code&gt;, meaning it is executed prior to an interface being brought up - better to do it then than afterwards :)&lt;/p&gt;

&lt;p&gt;I provide a couple of shell functions to make it easy write rules which are to be applied to both IPv4 and IPv6.&lt;/p&gt;

&lt;p&gt;Here it is in its entirety, feel free to use/copy/whatever, it&amp;#8217;s public domain.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# IPTables firewall script.  There are many.  This is mine.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;


&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Ensure sane path&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/sbin:/usr/sbin:/bin:/usr/bin

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# When running from the command line, provide a -v option to print the&lt;/span&gt;
&lt;span class='c'&gt;# installed rules at the end.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='nv'&gt;verbose&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;
&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;$1&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;-v&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;shift&lt;/span&gt;
&lt;span class='nb'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;verbose&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;on
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Rather than duplicate entries for iptables and ip6tables, have some small&lt;/span&gt;
&lt;span class='c'&gt;# wrapper functions do it for us.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# ip4tbl - apply ruleset for just iptables&lt;/span&gt;
&lt;span class='c'&gt;# ip6tbl - apply ruleset for just ip6tables&lt;/span&gt;
&lt;span class='c'&gt;# iptbl  - apply ruleset for both iptables and ip6tables&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
ip4tbl&lt;span class='o'&gt;()&lt;/span&gt;
&lt;span class='o'&gt;{&lt;/span&gt;
    iptables &lt;span class='s2'&gt;&amp;quot;$@&amp;quot;&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
ip6tbl&lt;span class='o'&gt;()&lt;/span&gt;
&lt;span class='o'&gt;{&lt;/span&gt;
    ip6tables &lt;span class='s2'&gt;&amp;quot;$@&amp;quot;&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
iptbl&lt;span class='o'&gt;()&lt;/span&gt;
&lt;span class='o'&gt;{&lt;/span&gt;
    ip4tbl &lt;span class='s2'&gt;&amp;quot;$@&amp;quot;&lt;/span&gt;
    ip6tbl &lt;span class='s2'&gt;&amp;quot;$@&amp;quot;&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Flush all rulesets&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
iptbl -F
iptbl -X

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Block by default except outgoing traffic&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
iptbl -P INPUT DROP
iptbl -P FORWARD DROP
iptbl -P OUTPUT ACCEPT

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Allow everything on loopback&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
iptbl -A INPUT -i lo -j ACCEPT

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Permit established connections&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
iptbl -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Permit allowed services on all interfaces.  DNS is restricted to my public&lt;/span&gt;
&lt;span class='c'&gt;# DNS servers, this just runs a hidden master.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
iptbl  -A INPUT -p tcp -m tcp --dport 22   -j ACCEPT
iptbl  -A INPUT -p tcp -m tcp --dport 25   -j ACCEPT
ip4tbl -A INPUT -p tcp -m tcp --dport 53   -s 85.158.46.77    -j ACCEPT
ip4tbl -A INPUT -p udp -m udp --dport 53   -s 85.158.46.77    -j ACCEPT
ip4tbl -A INPUT -p tcp -m tcp --dport 53   -s 193.108.199.128 -j ACCEPT
ip4tbl -A INPUT -p udp -m udp --dport 53   -s 193.108.199.128 -j ACCEPT
ip4tbl -A INPUT -p tcp -m tcp --dport 53   -s 193.108.199.130 -j ACCEPT
ip4tbl -A INPUT -p udp -m udp --dport 53   -s 193.108.199.130 -j ACCEPT
ip4tbl -A INPUT -p tcp -m tcp --dport 53   -s 213.5.89.46     -j ACCEPT
ip4tbl -A INPUT -p udp -m udp --dport 53   -s 213.5.89.46     -j ACCEPT
iptbl  -A INPUT -p tcp -m tcp --dport 80   -j ACCEPT
iptbl  -A INPUT -p tcp -m tcp --dport 113  -j ACCEPT
iptbl  -A INPUT -p tcp -m tcp --dport 443  -j ACCEPT
iptbl  -A INPUT -p tcp -m tcp --dport 465  -j ACCEPT
iptbl  -A INPUT -p tcp -m tcp --dport 993  -j ACCEPT

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Permit ICMP and traceroute&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
ip4tbl -A INPUT -p icmp -j ACCEPT
ip6tbl -A INPUT -p ipv6-icmp -j ACCEPT
iptbl  -A INPUT -p udp -m udp --dport 33434:33523 -j ACCEPT

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Log denied connections&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='nv'&gt;LOGCOMMON&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-m limit --limit 5/min -j LOG --log-prefix &amp;#39;iptables: &amp;#39; --log-level 7&amp;quot;&lt;/span&gt;
iptbl  -A INPUT -p tcp       &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;LOGCOMMON&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
iptbl  -A INPUT -p udp       &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;LOGCOMMON&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
ip4tbl -A INPUT -p icmp      &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;LOGCOMMON&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
ip6tbl -A INPUT -p ipv6-icmp &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;LOGCOMMON&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Finally, reject to keep open connections down&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
iptbl -A INPUT -j REJECT

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Display INPUT chain if verbose&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; -n &lt;span class='s2'&gt;&amp;quot;${verbose}&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;iptables  -L INPUT -vn --line-numbers
    ip6tables -L INPUT -vn --line-numbers
&lt;span class='k'&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Just remember to make it executable ;-)&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>New site design</title>
      <link>http://www.perkin.org.uk/posts/new-site-design.html</link>
      <pubDate>Mon, 20 Feb 2012 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/new-site-design.html</guid>
      <description>&lt;p&gt;I am a minimalist at heart, and I love command line interfaces and text files.&lt;/p&gt;

&lt;p&gt;However, I&amp;#8217;m also pragmatic, and so for a long time my blog has been powered by Wordpress, which made it relatively easy to manage content and design. I just didn&amp;#8217;t want the hassle of maintaining something myself.&lt;/p&gt;

&lt;p&gt;Somewhere along the way recently I stumbled across &lt;a href='https://github.com/mojombo/jekyll'&gt;Jekyll&lt;/a&gt;, and the idea of generating a static site from templates.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;d seen a few sites I liked the look of, and I loved the idea of simplifying my site (and editing posts in vim!), and so the end result is the site you see now.&lt;/p&gt;

&lt;p&gt;I pondered implementing something like &lt;a href='http://disqus.com/'&gt;disqus&lt;/a&gt; for comments, but honestly I get so few proper responses, compared to the hundreds and hundreds of spam attempts, that it&amp;#8217;s not worth it - if you want to comment on a post, just use twitter (I&amp;#8217;ll probably implement a little button to do that at some point).&lt;/p&gt;

&lt;p&gt;Also, I got rid of categories, simpler to just have tags.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s likely I&amp;#8217;ve messed up conversion of my old blog posts, as I did them all manually. If you spot anything obviously broken, please let me know. One of the great things of the Jekyll approach is that you can simply manage your site via github, and so if you prefer you can comment on breakages &lt;a href='https://github.com/jperkin/www.perkin.org.uk'&gt;here&lt;/a&gt;!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Set up anonymous FTP upload on Oracle Linux</title>
      <link>http://www.perkin.org.uk/posts/set-up-anonymous-ftp-upload-on-oracle-linux.html</link>
      <pubDate>Wed, 11 Jan 2012 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/set-up-anonymous-ftp-upload-on-oracle-linux.html</guid>
      <description>&lt;p&gt;Just because this took a little longer than I expected, here&amp;#8217;s a quick howto for setting up an anonymous FTP drop-off on Oracle Linux, which I use as a simple way to transfer files out of my Virtual Machines.&lt;/p&gt;

&lt;h2 id='install_vsftpd'&gt;Install vsftpd&lt;/h2&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo yum -y install vsftpd
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_iptables'&gt;Configure iptables&lt;/h2&gt;

&lt;p&gt;As FTP is a more complicated protocol than most, there is a special netfilter module required in order to correctly keep track of connections.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; You will perhaps want to change the insert number here.
&lt;span class='gp'&gt;$&lt;/span&gt; sudo iptables -I INPUT 4 -m state --state NEW -p tcp --dport 21 -j ACCEPT
&lt;span class='gp'&gt;$&lt;/span&gt; sudo /etc/init.d/iptables save
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Add &lt;code&gt;nf_conntrack_ftp&lt;/code&gt; to &lt;code&gt;IPTABLES_MODULES&lt;/code&gt;&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /etc/sysconfig/iptables-config
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then load the module rather than reboot&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo modprobe nf_conntrack_ftp
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='create_incoming'&gt;Create /incoming&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;/incoming&lt;/code&gt; area and ensure it has the correct file permissions and SELinux context. This is the bit which had me stumped for a little while, as I didn&amp;#8217;t know about &lt;code&gt;allow_ftpd_anon_write&lt;/code&gt;, and while I normally just disable SELinux, I do also like to know how things should work (and be able to write about them!):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo mkdir /var/ftp/incoming
&lt;span class='gp'&gt;$&lt;/span&gt; sudo chown ftp:ftp /var/ftp/incoming

&lt;span class='gp'&gt;#&lt;/span&gt; This allows anonymous users to upload, but not see what is in the directory
&lt;span class='gp'&gt;$&lt;/span&gt; sudo chmod 750 /var/ftp/incoming

&lt;span class='gp'&gt;$&lt;/span&gt; sudo chcon -u system_u -t public_content_rw_t /var/ftp/incoming
&lt;span class='gp'&gt;$&lt;/span&gt; sudo setsebool &lt;span class='nv'&gt;allow_ftpd_anon_write&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_vsftpd'&gt;Configure vsftpd&lt;/h2&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /etc/vsftpd/vsftpd.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;anon_upload_enable=YES
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='startup'&gt;Startup&lt;/h2&gt;

&lt;p&gt;Finally, enable and start vsftpd:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo chkconfig vsftpd on
&lt;span class='gp'&gt;$&lt;/span&gt; sudo /etc/init.d/vsftpd start
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And that&amp;#8217;s it, you should now be able to FTP as anonymous and upload files into &lt;code&gt;/incoming&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Kickstart Oracle Linux in VirtualBox</title>
      <link>http://www.perkin.org.uk/posts/kickstart-oracle-linux-in-virtualbox.html</link>
      <pubDate>Mon, 09 Jan 2012 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/kickstart-oracle-linux-in-virtualbox.html</guid>
      <description>&lt;p&gt;In my &lt;a href='http://www.perkin.org.uk/posts/kickstart-oracle-linux-from-ubuntu.html'&gt;previous post&lt;/a&gt; I configured an Ubuntu laptop as a Kickstart install server for a physical machine I wanted to build.&lt;/p&gt;

&lt;p&gt;Now that everything is configured for automated installs, it makes sense to use the same infrastructure to install virtual machines too. Everything can be done from the command line, and new virtual machines can be provisioned very quickly.&lt;/p&gt;

&lt;p&gt;Again, I will use Oracle Linux 6.2 as an example.&lt;/p&gt;

&lt;h2 id='create_virtual_machine'&gt;Create Virtual Machine&lt;/h2&gt;

&lt;p&gt;These commands create a new virtual machine, including disk, and configures it for network booting. If you don&amp;#8217;t already have VirtualBox installed:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo apt-get install virtualbox
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Set the name of the virtual machine as it appears in VirtualBox, this variable is then used throughout:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;VM&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Oracle Linux 6.2&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Create the VM:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage createvm --name &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --ostype &lt;span class='s2'&gt;&amp;quot;Oracle_64&amp;quot;&lt;/span&gt; --register
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Create the hard disk (32GB expanding) and attach it via SATA. Note that I store my VMs in &lt;code&gt;${HOME}/VirtualBox&lt;/code&gt; rather than the default &lt;code&gt;${HOME}/VirtualBox VMs&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage createhd --filename &lt;span class='s2'&gt;&amp;quot;VirtualBox/${VM}/${VM}.vdi&amp;quot;&lt;/span&gt; --size 32768

&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storagectl &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --name &lt;span class='s2'&gt;&amp;quot;SATA Controller&amp;quot;&lt;/span&gt; --add sata &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='gp'&gt;&amp;gt;&lt;/span&gt;   --controller IntelAHCI

&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storageattach &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --storagectl &lt;span class='s2'&gt;&amp;quot;SATA Controller&amp;quot;&lt;/span&gt; --port 0 &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='gp'&gt;&amp;gt;&lt;/span&gt;   --device 0 --type hdd --medium &lt;span class='s2'&gt;&amp;quot;VirtualBox/${VM}/${VM}.vdi&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Default RAM is 128MB, Oracle Linux installer requires at least 512MB however. Once installed we can drop back down to 256MB or so:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --memory 512
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Configure boot order. Put disk first, as on the first boot there is nothing on it so it falls through to PXE for install, then after the install the disk is bootable.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --boot1 disk --boot2 net --boot3 none --boot4 none
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Change NIC type from the default e1000, as a vanilla VirtualBox install does not include the firmware necessary to network boot from that device – it is available in the &amp;#8220;VirtualBox Extension Pack&amp;#8221; add-on. Switch to a plain PCNet Fast III which does include PXE firmware.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --nictype1 Am79C973
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;VirtualBox does have the ability to serve TFTP directly from the file system by placing files inside &lt;code&gt;${HOME}/.VirtualBox/TFTP/&lt;/code&gt; but I prefer to just use the network as it&amp;#8217;s already configured.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --nattftpserver1 10.0.2.2
&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt; --nattftpfile1 pxelinux.0
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_pxelinuxkickstart'&gt;Configure pxelinux/kickstart&lt;/h2&gt;

&lt;p&gt;We just need a couple of tweaks to the configs from the last blog entry, as the network addresses are different inside VirtualBox, and we also may want a different kickstart configuration.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /var/lib/tftpboot/pxelinux.cfg/default
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I just amended the existing entry to point to 10.0.2.2 which is the address of the machine running VirtualBox, and a different ks-vm.cfg kickstart configuration file, but you could also create a new label if you wanted to regularly switch between different configurations:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;LABEL ol6.2
    KERNEL /ol6.2/vmlinuz
    APPEND initrd=/ol6.2/initrd.img ks=http://10.0.2.2/ks-vm.cfg
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;For virtual machines I use a slightly different configuration compared to previously. I&amp;#8217;ve only shown the changes below, not the full file:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo cp /usr/share/nginx/www/ks.cfg /usr/share/nginx/www/ks-vm.cfg
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;# Update network configuration for DHCP instead of static
network --bootproto=dhcp
url --url=http://10.0.2.2/ol6.2

# Don&amp;#39;t specify disks, just use default layout
bootloader --location=mbr --driveorder=sda
clearpart --all --initlabel

# Just add &amp;#39;screen&amp;#39; to the default set of @base and @core packages.
%packages
screen
%end
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='start_virtual_machine'&gt;Start Virtual Machine&lt;/h2&gt;

&lt;p&gt;All that&amp;#8217;s left to do is to boot up the VM, and everything else should run automatically.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VirtualBox --startvm &lt;span class='s2'&gt;&amp;quot;${VM}&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;All done!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Kickstart Oracle Linux from Ubuntu</title>
      <link>http://www.perkin.org.uk/posts/kickstart-oracle-linux-from-ubuntu.html</link>
      <pubDate>Mon, 09 Jan 2012 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/kickstart-oracle-linux-from-ubuntu.html</guid>
      <description>&lt;p&gt;As my new job involves working on Oracle Linux, I figured I should migrate my home server to it, which would also mean I could move it to a proper RAID10 configuration rather than relying on multiple RAID1s.&lt;/p&gt;

&lt;p&gt;My laptop runs Ubuntu, and I wanted to install the server from it using PXE and Kickstart, so here&amp;#8217;s how I did it.&lt;/p&gt;

&lt;h2 id='configure_dhcpd'&gt;Configure dhcpd&lt;/h2&gt;

&lt;p&gt;DHCP is required for two things, to give the server its network configuration, and to point it at the PXE boot loader we want to use.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo apt-get install isc-dhcp-server
&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /etc/dhcp/dhcpd.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here&amp;#8217;s the configuration I used, which says to configure 192.168.2.0/24 with a dynamic DHCP range between 192.168.2.100 – 192.168.2.200, and to boot machines using pxelinux.0 which is relative to the TFTP root directory (configured in the next section):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;subnet 192.168.2.0 netmask 255.255.255.0 {
    range 192.168.2.100 192.168.2.200;
    filename &amp;quot;pxelinux.0&amp;quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The isc-dhcp-server install automatically tries to start the server, but will fail as it isn&amp;#8217;t configured, so we restart it now that there is a working configuration installed&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo /etc/init.d/isc-dhcp-server restart
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_tftpd'&gt;Configure tftpd&lt;/h2&gt;

&lt;p&gt;TFTP is a simple protocol used to transfer files over the network, and due to its simplicity it is the primary way to network boot, as it can be easily embedded into firmware.&lt;/p&gt;

&lt;p&gt;All we need to do is install the TFTP daemon and syslinux which includes the PXE boot loader, then put the pxelinux file into the tftproot area:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo apt-get install syslinux tftpd-hpa
&lt;span class='gp'&gt;$&lt;/span&gt; sudo cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_oracle_linux_dvd'&gt;Configure Oracle Linux DVD&lt;/h2&gt;

&lt;p&gt;To save space on the laptop we can just mount the DVD read-only and install from that:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo mkdir /media/ol6.2
&lt;span class='gp'&gt;$&lt;/span&gt; sudo mount -o loop,ro /path/to/OracleLinux-R6-U2-Server-x86_64-dvd.iso /media/ol6.2
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;However, we do need to copy the kernel and initrd image from the DVD into the tftproot as they are required for booting:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo mkdir /var/lib/tftpboot/ol6.2 /var/lib/tftpboot/pxelinux.cfg
&lt;span class='gp'&gt;$&lt;/span&gt; sudo cp -a /mnt/images/pxeboot/&lt;span class='o'&gt;{&lt;/span&gt;initrd.img,vmlinuz&lt;span class='o'&gt;}&lt;/span&gt; /var/lib/tftpboot/ol6.2/
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_pxelinux'&gt;Configure pxelinux&lt;/h2&gt;

&lt;p&gt;All that&amp;#8217;s left for the PXE stage is to configure the boot loader, and tell it what kernel and initrd we want to use:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /var/lib/tftpboot/pxelinux.cfg/default
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This configuration has just one entry which is booted after a short wait, but pxelinux has many more options, including the ability to boot from local disk.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;DEFAULT	ol6.2
PROMPT 1
TIMEOUT 5

LABEL ol6.2
    KERNEL /ol6.2/vmlinuz
    APPEND initrd=/ol6.2/initrd.img ks=http://192.168.2.1/ks.cfg
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Note the ks argument which specifies the kickstart file we will use, that and the web server required to serve it will be set up next.&lt;/p&gt;

&lt;h2 id='configure_nginx'&gt;Configure nginx&lt;/h2&gt;

&lt;p&gt;I chose nginx as it is small and simple to configure, but any web server will do.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo apt-get install nginx
&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /etc/nginx/sites-available/default
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The install will be performed over HTTP, so we need to make the DVD we mounted earlier available. This entry in the &lt;code&gt;server { }&lt;/code&gt; section makes the DVD available via http://192.168.2.1/ol6.2/:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;server {
[...]
    location /ol6.2 {
        root /media;
        autoindex on;
        allow all;
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then start nginx (unlike isc-dhcp-server this isn&amp;#8217;t done automatically):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;$ sudo /etc/init.d/nginx start
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='configure_kickstart'&gt;Configure kickstart&lt;/h2&gt;

&lt;p&gt;Finally, we create a kickstart configuration which specifies exactly how our target machine is to be installed, and this allows a completely unattended installation.&lt;/p&gt;

&lt;p&gt;Ideally I should create a specific area for holding files like this, but as a quick hack I simply put it into the default nginx web root (and thus available as http://192.168.2.1/ks.cfg as configured earlier in the pxelinux.cfg/default file:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;sudo vi /usr/share/nginx/www/ks.cfg
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here is my ks.cfg file in full. The only thing missing is a rootpw line to automatically set a root password, however for maximum security I am happy to forego a completely unattended installation and instead have the installer prompt me to type it in during the install.&lt;/p&gt;

&lt;p&gt;Some notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UK keyboard language and timezone selected.&lt;/li&gt;

&lt;li&gt;Automatically reboot when the installer is finished.&lt;/li&gt;

&lt;li&gt;Point to the Oracle Linux DVD using the url directive.&lt;/li&gt;

&lt;li&gt;I have 4 disks configured with RAID1 for /boot, and RAID10 for swap and /.&lt;/li&gt;

&lt;li&gt;Disks are referred to by path, to ensure correct ordering.&lt;/li&gt;

&lt;li&gt;A small set of packages are installed, containing just the functionality I require.&lt;/li&gt;

&lt;li&gt;A small %post section is used to perform any fixes I want for the first boot.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;#
# Miscellaneous options.
#
install
keyboard uk
lang en_GB.UTF-8
reboot
selinux --enforcing
timezone Europe/London

#
# User setup.  I&amp;#39;d create my local user here and configure sudoers, but
# kickstart doesn&amp;#39;t yet support creating a user with uid/gid of 1000 (the
# gid is always 500, even if you add the named group first).
#
authconfig --enableshadow --passalgo=sha512

#
# Networking.  The &amp;#39;network&amp;#39; line needs to be on a single line
# for kickstart to work - it is only split here for the blog.
#
firewall --service=ssh
network --bootproto=static \
        --hostname=gromit.adsl.perkin.org.uk \
        --ip=192.168.2.10 \
        --netmask=255.255.255.0 \
        --gateway=192.168.2.1 \
        --nameserver=193.178.223.141,208.72.84.24 \
        --ipv6=auto
url --url=http://192.168.2.1/ol6.2

#
# Disk configuration.
#
bootloader --location=mbr --driveorder=sda,sdb,sdc,sdd
clearpart --all --initlabel
#
# /boot (RAID1 necessary as booting from RAID10 isn&amp;#39;t supported)
#
part raid.00 --asprimary --size=1024 --ondisk=/dev/disk/by-path/pci-*-0*0
part raid.01 --asprimary --size=1024 --ondisk=/dev/disk/by-path/pci-*-1*0
part raid.02 --asprimary --size=1024 --ondisk=/dev/disk/by-path/pci-*-2*0
part raid.03 --asprimary --size=1024 --ondisk=/dev/disk/by-path/pci-*-3*0
raid /boot --level=1 --device=md0 --fstype=ext4 raid.00 raid.01 raid.02 raid.03
#
# swap, RAID10 of size RAM+2GB, give or take..
#
part raid.10 --asprimary --size=6144 --ondisk=/dev/disk/by-path/pci-*-0*0
part raid.11 --asprimary --size=6144 --ondisk=/dev/disk/by-path/pci-*-1*0
part raid.12 --asprimary --size=6144 --ondisk=/dev/disk/by-path/pci-*-2*0
part raid.13 --asprimary --size=6144 --ondisk=/dev/disk/by-path/pci-*-3*0
raid swap --level=10 --device=md1 --fstype=swap raid.10 raid.11 raid.12 raid.13
#
# /, RAID10 of remainder (have to specify an arbitrary --size even with --grow)
#
part raid.20 --asprimary --size=1024 --grow --ondisk=/dev/disk/by-path/pci-*-0*0
part raid.21 --asprimary --size=1024 --grow --ondisk=/dev/disk/by-path/pci-*-1*0
part raid.22 --asprimary --size=1024 --grow --ondisk=/dev/disk/by-path/pci-*-2*0
part raid.23 --asprimary --size=1024 --grow --ondisk=/dev/disk/by-path/pci-*-3*0
raid / --level=10 --device=md2 --fstype=ext4 raid.20 raid.21 raid.22 raid.23

#
# Packages.  @base and @core are pre-selected.
#
%packages
@cifs-file-server
@console-internet --optional
@development
@legacy-unix --optional
@mail-server
@network-server --optional
@network-tools
@nfs-file-server
@web-server
screen
%end

#
# Post-install fix-ups.
#
%post
#
# The &amp;#39;network&amp;#39; directive doesn&amp;#39;t support DNS search paths, so set those
# manually, and disable Network Manager.
#
printf &amp;quot;/^NM_CONTROLLED/s/yes/no/\nw\nq\n&amp;quot; \
  | ed /etc/sysconfig/network-scripts/ifcfg-eth0
printf &amp;quot;/^#/s/.*/search adsl.perkin.org.uk perkin.org.uk/\nw\nq\n&amp;quot; \
  | ed /etc/resolv.conf
#
# Disable unwanted services
#
chkconfig --del cups
%end
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;All done.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Last day at MySQL</title>
      <link>http://www.perkin.org.uk/posts/last-day-at-mysql.html</link>
      <pubDate>Thu, 22 Dec 2011 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/last-day-at-mysql.html</guid>
      <description>&lt;p&gt;Today is my final day working on MySQL. It has been an amazing 4.5 years, and I&amp;#8217;ve loved working on the technical challenges involved in producing a piece of software which runs on so many different platforms, as well as working with so many talented individuals. I have learned a lot, which is just how I like it.&lt;/p&gt;

&lt;p&gt;Times have changed since I first joined MySQL AB, of course. But despite going through two acquisitions, the day to day work hasn&amp;#8217;t changed much at all. I still get to work from home, which is something I am passionate about and feel many companies are missing out on massively by still being stuck in an outdated 20th century mindset. Oracle have continued to invest in MySQL, providing additional headcount and extra hardware. And the vast majority of people I started working with back in 2007 are still with the company (don&amp;#8217;t believe the FUD, folks) and working harder than ever.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m most proud of the work we have done internally to ensure our MySQL releases are in excellent shape. When I first joined, our internal &amp;#8220;PushBuild&amp;#8221; system was very limited, only able to handle a small number of pushes with reduced testing across a few platforms, and the builds produced were completely different to those that were released.&lt;/p&gt;

&lt;p&gt;Nowadays, thanks to the investment made by Sun and Oracle, we have a large server farm producing thousands of builds and hundreds of gigabytes of data every day across all our supported platforms. Those which are based on MySQL 5.5 or newer have additional package verification tests, using chroots and virtual machines, to ensure that the RPM/MSI/etc packages can be installed, run, and uninstalled, all automatically and on every push by developers. We run additional nightly and weekly tests which extend the default set of test suites. Our 5.5+ releases are produced directly in PushBuild. And we are looking to extend this to all MySQL products, not just the Server.&lt;/p&gt;

&lt;p&gt;If the above sounds fun, keep an eye out for job posts, as the Release Engineering team is looking to expand, and they are an amazing group of people to work with.&lt;/p&gt;

&lt;p&gt;I certainly found it fun, which is why I&amp;#8217;m going to continue in that line of work, and stay within Oracle, but move to the Linux group. To be honest, databases have never been a passion of mine, however I am rather fond of Operating Systems, and so I am really looking forward to continuing to work on continuous integration and testing, but with Oracle Linux and Oracle VM instead of MySQL. Plus, it will be nice to go back to a purely technical role – I have learned over the last year or so that management isn&amp;#8217;t really my thing :)&lt;/p&gt;

&lt;p&gt;To all my colleagues, past and present, thank you for the wonderful ride. I have many, many good memories, and hopefully we will keep in touch.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Installing OpenBSD with softraid</title>
      <link>http://www.perkin.org.uk/posts/installing-openbsd-with-softraid.html</link>
      <pubDate>Thu, 15 Dec 2011 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/installing-openbsd-with-softraid.html</guid>
      <description>&lt;p&gt;This is more of a log for me than anything else, but perhaps someone will find this useful.&lt;/p&gt;

&lt;p&gt;OpenBSD includes a software RAID implementation which supports booting in newer snapshots, and I was itching to install the latest version and use it as my file server, which has 4 750GB disks. There is a small bit of preparation work to do prior to installing, which is the bulk of this entry, most of which is based on &lt;a href='http://www.undeadly.org/cgi?action=article&amp;amp;sid=20111002154251'&gt;this undeadly.org article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Grab latest amd64 &lt;a href='http://mirror.bytemark.co.uk/OpenBSD/snapshots/amd64/install50.iso'&gt;snapshot&lt;/a&gt;, boot it, drop into (S)hell mode and set up the disks:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='nb'&gt;cd&lt;/span&gt; /dev
sh MAKEDEV sd1 sd2 sd3 sd4 sd5
&lt;span class='k'&gt;for &lt;/span&gt;disk in 0 1 2 3
&lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='c'&gt;# Clear beginning of disks..&lt;/span&gt;
  dd &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/dev/zero &lt;span class='nv'&gt;of&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/dev/rsd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;c &lt;span class='nv'&gt;bs&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1m &lt;span class='nv'&gt;count&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;10

  &lt;span class='c'&gt;# ..and initialise new partition table&lt;/span&gt;
  fdisk -iy sd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;

  &lt;span class='c'&gt;#&lt;/span&gt;
  &lt;span class='c'&gt;# Create BSD disklabel:&lt;/span&gt;
  &lt;span class='c'&gt;#&lt;/span&gt;
  &lt;span class='c'&gt;# - 128m partitions at start to hold kernels for booting&lt;/span&gt;
  &lt;span class='c'&gt;# - 4g spare raid on each disk for testing&lt;/span&gt;
  &lt;span class='c'&gt;# - rest raid for main OS and data&lt;/span&gt;
  &lt;span class='c'&gt;#   - OS and /home on first two mirrored disks&lt;/span&gt;
  &lt;span class='c'&gt;#   - /store on second two mirrored disks&lt;/span&gt;
  &lt;span class='c'&gt;#&lt;/span&gt;
  print &lt;span class='s2'&gt;&amp;quot;a a\n\n128m\n\na d\n\n4g\nraid\na e\n\n\nraid\nw\nq\n&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
    | disklabel -E sd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;

  &lt;span class='c'&gt;# Clear beginning of raid partitions&lt;/span&gt;
  dd &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/dev/zero &lt;span class='nv'&gt;of&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/dev/rsd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;d &lt;span class='nv'&gt;bs&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1m &lt;span class='nv'&gt;count&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;10
  dd &lt;span class='k'&gt;if&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/dev/zero &lt;span class='nv'&gt;of&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/dev/rsd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;e &lt;span class='nv'&gt;bs&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1m &lt;span class='nv'&gt;count&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;10
&lt;span class='k'&gt;done&lt;/span&gt;

&lt;span class='c'&gt;# Create RAID1 mirrors&lt;/span&gt;
bioctl -c 1 -l sd0e,sd1e softraid0
bioctl -c 1 -l sd2e,sd3e softraid0

&lt;span class='c'&gt;# Exit shell and start the (I)nstall&lt;/span&gt;
&lt;span class='nb'&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As for the install, go with the sensible defaults, other than:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;change keyboard layout to &amp;#8220;uk&amp;#8221;&lt;/li&gt;

&lt;li&gt;manually configure network, enable rtsol&lt;/li&gt;

&lt;li&gt;start ntpd&lt;/li&gt;

&lt;li&gt;do not expect to run X&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When it comes to disk selection, choose sd4 as the root disk, and use the following layout:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;# partition  size  mount
  sd4a       1G    /
  sd4b       8G    swap
  sd4d       1G    /tmp
  sd4e       8G    /var
  sd4f       16G   /usr
  sd4h       rest  /home
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;then initialise sd5 with:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;# partition  size  mount
  sd5a       2G    /altroot
  sd5d       8G    /scratch
  sd5e       rest  /store
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Install the full OS, set the correct timezone, then before rebooting initialize the boot partitions and copy the kernels to them. Doing this on all of them means we can boot from any disk.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='k'&gt;for &lt;/span&gt;disk in 0 1 2 3
&lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;  &lt;/span&gt;newfs sd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;a
  mount /dev/sd&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;disk&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;a /mnt2
  cp /mnt/bsd* /mnt2
  umount /mnt2
&lt;span class='k'&gt;done&lt;/span&gt;
eject cd0a
reboot
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Job done.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Create VirtualBox VM from the command line</title>
      <link>http://www.perkin.org.uk/posts/create-virtualbox-vm-from-the-command-line.html</link>
      <pubDate>Wed, 21 Sep 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/create-virtualbox-vm-from-the-command-line.html</guid>
      <description>&lt;p&gt;As something of a follow-up post to the previous entry, here&amp;#8217;s a quick recipe for creating a Virtual Machine using the VirtualBox command line tools:&lt;/p&gt;

&lt;p&gt;We&amp;#8217;re using Windows Server 2008 64bit as an example, modify to taste.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;VM&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;Windows-2008-64bit&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Create a 32GB &amp;#8220;dynamic&amp;#8221; disk.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage createhd --filename &lt;span class='nv'&gt;$VM&lt;/span&gt;.vdi --size 32768
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can get a list of the OS types VirtualBox recognises using:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage list ostypes
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then copy the most appropriate one into here.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage createvm --name &lt;span class='nv'&gt;$VM&lt;/span&gt; --ostype &lt;span class='s2'&gt;&amp;quot;Windows2008_64&amp;quot;&lt;/span&gt; --register
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Add a SATA controller with the dynamic disk attached.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storagectl &lt;span class='nv'&gt;$VM&lt;/span&gt; --name &lt;span class='s2'&gt;&amp;quot;SATA Controller&amp;quot;&lt;/span&gt; --add sata &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='gp'&gt;&amp;gt;&lt;/span&gt;  --controller IntelAHCI
&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storageattach &lt;span class='nv'&gt;$VM&lt;/span&gt; --storagectl &lt;span class='s2'&gt;&amp;quot;SATA Controller&amp;quot;&lt;/span&gt; --port 0 &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='gp'&gt;&amp;gt;&lt;/span&gt;  --device 0 --type hdd --medium &lt;span class='nv'&gt;$VM&lt;/span&gt;.vdi
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Add an IDE controller with a DVD drive attached, and the install ISO inserted into the drive:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storagectl &lt;span class='nv'&gt;$VM&lt;/span&gt; --name &lt;span class='s2'&gt;&amp;quot;IDE Controller&amp;quot;&lt;/span&gt; --add ide
&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storageattach &lt;span class='nv'&gt;$VM&lt;/span&gt; --storagectl &lt;span class='s2'&gt;&amp;quot;IDE Controller&amp;quot;&lt;/span&gt; --port 0 &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='gp'&gt;&amp;gt;&lt;/span&gt;  --device 0 --type dvddrive --medium /path/to/windows_server_2008.iso
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Misc system settings.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='nv'&gt;$VM&lt;/span&gt; --ioapic on
&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='nv'&gt;$VM&lt;/span&gt; --boot1 dvd --boot2 disk --boot3 none --boot4 none
&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='nv'&gt;$VM&lt;/span&gt; --memory 1024 --vram 128
&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage modifyvm &lt;span class='nv'&gt;$VM&lt;/span&gt; --nic1 bridged --bridgeadapter1 e1000g0
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Configuration is all done, boot it up! If you&amp;#8217;ve done this one a remote machine, you can RDP to the console via &lt;code&gt;vboxhost:3389&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxHeadless -s &lt;span class='nv'&gt;$VM&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Once you have configured the operating system, you can shutdown and eject the DVD.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage storageattach &lt;span class='nv'&gt;$VM&lt;/span&gt; --storagectl &lt;span class='s2'&gt;&amp;quot;IDE Controller&amp;quot;&lt;/span&gt; --port 0 &lt;span class='se'&gt;\&lt;/span&gt;
&lt;span class='gp'&gt;&amp;gt;&lt;/span&gt;  --device 0 --type dvddrive --medium none
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, it&amp;#8217;s a good idea to take regular snapshots so that you can always revert back to a known-good state rather than having to completely re-install.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage snapshot &lt;span class='nv'&gt;$VM&lt;/span&gt; take &amp;lt;name of snapshot&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And, if you need to revert back to a particular snapshot:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; VBoxManage snapshot &lt;span class='nv'&gt;$VM&lt;/span&gt; restore &amp;lt;name of snapshot&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Creating chroots for fun and MySQL testing</title>
      <link>http://www.perkin.org.uk/posts/creating-chroots-for-fun-and-mysql-testing.html</link>
      <pubDate>Wed, 14 Sep 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/creating-chroots-for-fun-and-mysql-testing.html</guid>
      <description>&lt;p&gt;Virtualisation is all the rage today, however there are still a few cases where good old-fashioned Unix chroot is still applicable, and testing MySQL across multiple platforms and architectures is one of those cases.&lt;/p&gt;

&lt;p&gt;At Oracle we do full automated package verification testing of our MySQL server binaries prior to release, which attempts to install the package, start the server, run some functionality testing, then uninstall. It is of course highly desirable that the testing environment this is performed in is as close to a clean install of the target operating system as possible, to avoid problems such as our packages depending upon some local changes or packages we may have installed which won&amp;#8217;t be available on a customer system.&lt;/p&gt;

&lt;p&gt;Given the large number of platforms and architectures that MySQL supports, going the virtualisation route would mean having to use many different products: VirtualBox for x86, zones for SPARC, qemu for ia64/PA-RISC/others (if it even supports them), and this gets complicated quickly and is not very maintainable. Thus I chose to use chroot as much as possible. In addition, it&amp;#8217;s much faster and less intensive on resources to use a chroot than boot up an entire OS image each time.&lt;/p&gt;

&lt;p&gt;I built all images directly from the original installation images (DVD, ISO, RPM, etc), to ensure that there was no contamination from our build environment or local install scripts in the image – they should be as close to what a normal user or customer will be running in their setup. From the install image, the packages are installed to a temporary directory, some final modifications are made, then the directory is tarred up ready to be extracted by the test framework and used.&lt;/p&gt;

&lt;p&gt;Here are some operating system specific examples, which set up an extracted chroot image into &lt;code&gt;${CHROOTDIR}&lt;/code&gt;. There may be additional steps required to get a fully functioning chroot, such as copying device files (&lt;code&gt;/dev/zero&lt;/code&gt; and &lt;code&gt;/dev/null&lt;/code&gt; are usually the minimum requirements) and adding users.&lt;/p&gt;

&lt;h2 id='freebsd'&gt;FreeBSD&lt;/h2&gt;

&lt;p&gt;FreeBSD 7 and 8 come as a number of sets in tar format, and for our purposes we only need to extract the base set. You may wish to add more sets if you want to use your chroot for building packages:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;
&lt;span class='nv'&gt;mdunit&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;mdconfig -a -t vnode -o &lt;span class='nb'&gt;readonly&lt;/span&gt; -f /path/to/dvd1/of/freebsd.iso&lt;span class='k'&gt;)&lt;/span&gt;
mount_cd9660 /dev/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;mdunit&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; /mnt
cat /mnt/*/base/base.?? | tar -xpzf - -C &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
umount /mnt
mdconfig -d -u &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;mdunit&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='hpux'&gt;HP-UX&lt;/h2&gt;

&lt;p&gt;HP-UX has since been EOL&amp;#8217;d for MySQL, however this information might still prove useful. The HP-UX installation media contains per-directory packages, with the contents representing how they are laid out on the destination file system with each file gzip compressed.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;
&lt;span class='nb'&gt;cd&lt;/span&gt; /path/to/extracted/hpux-dvd1
&lt;span class='k'&gt;for &lt;/span&gt;pkg in &lt;span class='nv'&gt;$LIST_OF_PKGS&lt;/span&gt;
&lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;  for &lt;/span&gt;subpkg in &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;pkg&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/*
  &lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;    if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; ! -d &lt;span class='s2'&gt;&amp;quot;${subpkg}&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;      continue&lt;/span&gt;
&lt;span class='k'&gt;    fi&lt;/span&gt;
&lt;span class='k'&gt;    for &lt;/span&gt;d in &lt;span class='k'&gt;$(&lt;/span&gt;find &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;subpkg&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -type d&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;      &lt;/span&gt;mkdir -p &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/&lt;span class='k'&gt;$(&lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;d&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
        | sed -e &lt;span class='s2'&gt;&amp;quot;s#${subpkg}/##g&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
              -e &lt;span class='s2'&gt;&amp;quot;s#usr/newconfig/##g&amp;quot;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;done&lt;/span&gt;
&lt;span class='k'&gt;    for &lt;/span&gt;f in &lt;span class='k'&gt;$(&lt;/span&gt;find &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;subpkg&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -type f&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;      &lt;/span&gt;gzip -dc &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;f&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; &amp;gt;&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/&lt;span class='k'&gt;$(&lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;f&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
        | sed -e &lt;span class='s2'&gt;&amp;quot;s#${subpkg}/##g&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
              -e &lt;span class='s2'&gt;&amp;quot;s#usr/newconfig/##g&amp;quot;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;done&lt;/span&gt;
&lt;span class='k'&gt;  done&lt;/span&gt;
&lt;span class='k'&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Once this is done you&amp;#8217;ll need to fix up permissions in bin and lib directories (make files executable), as well as create a bunch of symlinks for e.g. &lt;code&gt;/bin&lt;/code&gt; and &lt;code&gt;/lib&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='osx'&gt;OSX&lt;/h2&gt;

&lt;p&gt;For OSX we don&amp;#8217;t actually use a chroot tarball but instead create a sparse disk image. Currently the size of the &amp;#8220;chroot&amp;#8221; is very large as there&amp;#8217;s no easy way to strip down an OSX install, so mounting a disk image is faster than unpacking a chroot, plus it preserves various HFS-specific attributes.&lt;/p&gt;

&lt;p&gt;You will likely need at least the BSD, BaseSystem, and Essentials packages.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Create a sparse image to hold the chroot (which isn&amp;#39;t really a directory)&lt;/span&gt;
hdiutil create -fs HFS+ -size 8g -type SPARSE -volname osx-chroot &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
hdiutil attach -mountpoint &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.sparseimage
&lt;span class='c'&gt;# Either attach a DVD image or the real thing&lt;/span&gt;
hdiutil attach -mountpoint /Volumes/osx-install /path/to/dvd
&lt;span class='c'&gt;# Install packages&lt;/span&gt;
&lt;span class='k'&gt;for &lt;/span&gt;pkg in BSD BaseSystem Essentials
&lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;  &lt;/span&gt;installer -verbose &lt;span class='se'&gt;\&lt;/span&gt;
   -pkg /Volumes/osx-install/System/Installation/Packages/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;pkg&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.pkg &lt;span class='se'&gt;\&lt;/span&gt;
   -target &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
&lt;span class='k'&gt;done&lt;/span&gt;
&lt;span class='c'&gt;# Unmount&lt;/span&gt;
hdiutil detach &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
hdiutil detach /Volumes/osx-install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='red_hat__oracle_linux__suse'&gt;Red Hat / Oracle Linux / SuSE&lt;/h2&gt;

&lt;p&gt;For RPM-based distributions we use rpm to directly install packages into the chroot. The list of RPMs we install varies quite a lot from release to release, usually by having to increase the number:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RH3: 81&lt;/li&gt;

&lt;li&gt;RH4: 85&lt;/li&gt;

&lt;li&gt;RH5: 114&lt;/li&gt;

&lt;li&gt;RH6: 203&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;for the same functionality.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Kludge for &amp;#39;setup&amp;#39; RPM to install&lt;/span&gt;
mkdir -p &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/var/lock/rpm
&lt;span class='c'&gt;# If installing from an ISO:&lt;/span&gt;
mount -o loop /path/to/iso /mnt
&lt;span class='c'&gt;# Path varies from release to release&lt;/span&gt;
&lt;span class='nb'&gt;cd&lt;/span&gt; /mnt/path/to/RPMs
rpm --root&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -Uvh &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;LIST_OF_RPMS&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='solaris'&gt;Solaris&lt;/h2&gt;

&lt;p&gt;Similar to RPM, we use the native package manager to install packages directly into the chroot directory:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;# Avoid prompts&lt;/span&gt;
sed -e &lt;span class='s2'&gt;&amp;quot;s/ask$/nocheck/&amp;quot;&lt;/span&gt; /var/sadm/install/admin/default &amp;gt; /tmp/admin-&lt;span class='nv'&gt;$$&lt;/span&gt;
pkgadd -a /tmp/admin-&lt;span class='nv'&gt;$$&lt;/span&gt; -R &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;CHROOTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -d . &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;LIST_OF_PKGS&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
rm /tmp/admin-&lt;span class='nv'&gt;$$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='windows'&gt;Windows&lt;/h2&gt;

&lt;p&gt;Ok, so of course we can&amp;#8217;t use chroot images for Windows, as it doesn&amp;#8217;t have &lt;code&gt;chroot(2)&lt;/code&gt;. So here we use VirtualBox and its snapshot ability to load a clean snapshot of a basic Windows install, do the tests, then shut down the virtual machine, restore the snapshot, and boot up again.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Graphing memory usage during an MTR run</title>
      <link>http://www.perkin.org.uk/posts/graphing-memory-usage-during-an-mtr-run.html</link>
      <pubDate>Thu, 30 Jun 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/graphing-memory-usage-during-an-mtr-run.html</guid>
      <description>&lt;p&gt;In order to optimally size the amount of RAM to allocate to a set of new machines for running MTR, I ran a few tests to check the memory usage of an MTR run for mysql-trunk and cluster-7.1. As using a RAM disk considerably speeds things up, I set the vardir to be on &lt;code&gt;/ramdisk&lt;/code&gt; and logged the usage of that too.&lt;/p&gt;

&lt;p&gt;The tests were performed on an 8-core E5450 @ 3.00GHz with 24GB RAM, with 8GB allocated to &lt;code&gt;/ramdisk&lt;/code&gt;. Each branch ran the &lt;code&gt;default.daily&lt;/code&gt; collection, which generally contains the most testing we do per-run. Between each run I rebooted the machine to clear the buffer cache and &lt;code&gt;/ramdisk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I used something like the script below, which saved the per-second usage of &lt;code&gt;/ramdisk&lt;/code&gt;, the total RAM used, and the RAM used minus buffers.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/bash&lt;/span&gt;

&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;mysql-trunk&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;BUILDDIR&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;mysql-5.6.3-m5-linux2.6-x86_64&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;${HOME}/mtr-test/${BRANCH}&amp;quot;&lt;/span&gt;

stats&lt;span class='o'&gt;()&lt;/span&gt;
&lt;span class='o'&gt;{&lt;/span&gt;
  &lt;span class='nv'&gt;i&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1
  rm -f &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/stats-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
  &lt;span class='k'&gt;while&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; -f &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/running &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;do&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;rd&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;df -k /ramdisk | awk &lt;span class='s1'&gt;&amp;#39;/^\// {print $3}&amp;#39;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='nv'&gt;mem&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;free | awk &lt;span class='s1'&gt;&amp;#39;/^Mem/ {print $3}&amp;#39;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='nv'&gt;mem1&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$(&lt;/span&gt;free | awk &lt;span class='s1'&gt;&amp;#39;/cache:/ {print $3}&amp;#39;&lt;/span&gt;&lt;span class='k'&gt;)&lt;/span&gt;
    &lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;${i} ${rd} ${mem} ${mem1}&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt;&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/stats-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
    &lt;span class='nv'&gt;i&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;$((&lt;/span&gt;i+1&lt;span class='k'&gt;))&lt;/span&gt;
    sleep 1
  &lt;span class='k'&gt;done&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='nb'&gt;export &lt;/span&gt;&lt;span class='nv'&gt;TMPDIR&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;${TESTDIR}/tmp&amp;quot;&lt;/span&gt;
rm -rf &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TMPDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
mkdir -p &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TMPDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;

&amp;gt;&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/running
stats &amp;amp;

&lt;span class='o'&gt;(&lt;/span&gt;
  &lt;span class='nb'&gt;cd&lt;/span&gt; &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BUILDDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/mysql-test

  perl mysql-test-run.pl ... --parallel&lt;span class='o'&gt;=&lt;/span&gt;8 --vardir&lt;span class='o'&gt;=&lt;/span&gt;/ramdisk/mtr-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/...
  mv /ramdisk/mtr-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/* &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TMPDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/
  ...
&lt;span class='o'&gt;)&lt;/span&gt;

sync
rm -f &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;TESTDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/running
&lt;span class='nb'&gt;wait&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;First I graphed a straight run of the two branches, using the following gnuplot script:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='gnuplot'&gt;&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;terminal&lt;/span&gt; &lt;span class='n'&gt;png&lt;/span&gt; &lt;span class='n'&gt;enhanced&lt;/span&gt; &lt;span class='n'&gt;font&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Times,11&amp;quot;&lt;/span&gt; &lt;span class='n'&gt;size&lt;/span&gt; &lt;span class='mi'&gt;640&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='mi'&gt;768&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;output&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;mtr-ram.png&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;MTR memory usage (8-core Xeon, 24GB, 8GB RAM disk)&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;xlabel&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Time (minutes)&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;ylabel&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Memory usage (GB)&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;yrange&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;16&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;xtics&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;key&lt;/span&gt; &lt;span class='n'&gt;top&lt;/span&gt; &lt;span class='n'&gt;box&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;grid&lt;/span&gt;
&lt;span class='k'&gt;plot&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;stats-mysql-trunk&amp;quot;&lt;/span&gt; &lt;span class='nb'&gt;every&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
        &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;mysql-trunk /ramdisk usage&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; \
     &lt;span class='s'&gt;&amp;quot;stats-mysql-trunk&amp;quot;&lt;/span&gt; &lt;span class='nb'&gt;every&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
        &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;mysql-trunk RAM (inc buf)&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; \
     &lt;span class='s'&gt;&amp;quot;stats-mysql-trunk&amp;quot;&lt;/span&gt; &lt;span class='nb'&gt;every&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
        &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;mysql-trunk RAM (exc buf)&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; \
     &lt;span class='s'&gt;&amp;quot;stats-mysql-cluster-7.1&amp;quot;&lt;/span&gt; &lt;span class='nb'&gt;every&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
        &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;cluster-7.1 /ramdisk usage&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; \
     &lt;span class='s'&gt;&amp;quot;stats-mysql-cluster-7.1&amp;quot;&lt;/span&gt; &lt;span class='nb'&gt;every&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
        &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;cluster-7.1 RAM (inc buf)&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; \
     &lt;span class='s'&gt;&amp;quot;stats-mysql-cluster-7.1&amp;quot;&lt;/span&gt; &lt;span class='nb'&gt;every&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='err'&gt;$&lt;/span&gt;&lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='o'&gt;/&lt;/span&gt;&lt;span class='mi'&gt;1024&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
        &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;cluster-7.1 RAM (exc buf)&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='postimg'&gt;
  &lt;img alt='MTR memory usage' src='http://www.perkin.org.uk/files/images/mtr-ram.png' /&gt;
&lt;/div&gt;
&lt;p&gt;I then performed a valgrind run on mysql-trunk using similar scripts. As valgrind takes considerably longer (and uses more RAM) I kept it separate as the combined graph isn&amp;#8217;t very clear:&lt;/p&gt;
&lt;div class='postimg'&gt;
  &lt;img alt='MTR+valgrind memory usage' src='http://www.perkin.org.uk/files/images/mtr-ram-valgrind.png' /&gt;
&lt;/div&gt;
&lt;p&gt;So, based on these results, the host machine (16GB RAM + 8GB RAM disk) is probably a sensible guide for now, and allows for some future growth.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Fix input box keybindings in Firefox</title>
      <link>http://www.perkin.org.uk/posts/fix-input-box-keybindings-in-firefox.html</link>
      <pubDate>Wed, 29 Jun 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/fix-input-box-keybindings-in-firefox.html</guid>
      <description>&lt;p&gt;Those of us used to command line editing will no doubt have been frustrated many times in Firefox when editing text in an input box and subconciously hitting &lt;code&gt;ctrl-w&lt;/code&gt; to &lt;code&gt;delete-word&lt;/code&gt;, only to have the tab close and your work deleted.&lt;/p&gt;

&lt;p&gt;Thankfully there is a workaround to this. It used to be a case of adding the following to &lt;code&gt;.gtkrc&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;gtk-key-theme-name = &amp;quot;Emacs&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;However these days it&amp;#8217;s a gconf setting:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;$ gconftool-2 --set /desktop/gnome/interface/gtk_key_theme Emacs --type string
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This will bind &lt;code&gt;ctrl-w&lt;/code&gt; to &lt;code&gt;delete-word&lt;/code&gt; when in an input box, but retain the close tab binding elsewhere, a nice implementation of &lt;a href='http://en.wikipedia.org/wiki/DWIM'&gt;DWIM&lt;/a&gt;. See &lt;a href='http://kb.mozillazine.org/Emacs_Keybindings_%28Firefox%29'&gt;this page&lt;/a&gt; for more information.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>How to lose weight</title>
      <link>http://www.perkin.org.uk/posts/how-to-lose-weight.html</link>
      <pubDate>Fri, 24 Jun 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/how-to-lose-weight.html</guid>
      <description>&lt;p&gt;This year I set myself a target to get back to my pre-marital weight. Back in 2001 I was 90kg, but over the past decade I&amp;#8217;d steadily gone up and for quite a few years had hovered around 100kg.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m a bit of a perfectionist, and like shiny graphs, so from Jan 1st this year I weighed myself every day on the Wii Fit, and kept a record of my progress. This morning I was finally under 90kg. Here&amp;#8217;s how things have gone thus far:&lt;/p&gt;
&lt;div class='postimg'&gt;
  &lt;img alt='My weight loss between 1st January 2011 and 24th June 2011' src='http://www.perkin.org.uk/files/images/weight-jun11.png' /&gt;
&lt;/div&gt;
&lt;p&gt;And for the geeks, my gnuplot script, assuming an input file named &lt;code&gt;weight.txt&lt;/code&gt; containing lines of the format &lt;code&gt;&amp;quot;%Y-%m-%d &amp;lt;weight&amp;gt;&amp;quot;&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='gnuplot'&gt;&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;terminal&lt;/span&gt; &lt;span class='n'&gt;png&lt;/span&gt; &lt;span class='n'&gt;size&lt;/span&gt; &lt;span class='mi'&gt;640&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;400&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;output&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;weight-jun11.png&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;xdata&lt;/span&gt; &lt;span class='n'&gt;time&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;timefmt&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;%Y-%m-%d&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;format&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;%b&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;xlabel&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;Date&amp;#39;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;ytics&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;ylabel&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;Weight (kg)&amp;#39;&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nb'&gt;multiplot&lt;/span&gt;
&lt;span class='k'&gt;plot&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;weight.txt&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;using&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='nb'&gt;title&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;Weight&amp;#39;&lt;/span&gt; &lt;span class='nb'&gt;with&lt;/span&gt; &lt;span class='n'&gt;lines&lt;/span&gt; &lt;span class='n'&gt;linecolor&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='my_three_step_plan_for_losing_weight'&gt;My three step plan for losing weight&lt;/h2&gt;

&lt;p&gt;The interwebs are awash with a million different ways to lose weight, and there are thousands of companies who will gladly accept large chunks of your cash in order to provide you with their expert opinion on how to do it. This is my three-step plan, and you can have it for free:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Eat less.&lt;/li&gt;

&lt;li&gt;Eat less!&lt;/li&gt;

&lt;li&gt;Profit!!!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Really, that&amp;#8217;s it. It&amp;#8217;s not rocket science, after all. If you eat less stuff (especially saturated fat and sugar), there is less excess for your body to store as fat, and thus over time you weigh less as your body starts to use up the excess you have stored.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s some things I did to achieve this.&lt;/p&gt;

&lt;h3 id='eat_less'&gt;Eat less&lt;/h3&gt;

&lt;p&gt;The basic aim. For me this was mainly about reducing my portion size.&lt;/p&gt;

&lt;p&gt;Previously, I&amp;#8217;d eat a massive bowl of cereal in the morning. which I thought was a good thing as everyone always says to ensure you have a good breakfast. However I was eating more than my body needed and as a consequence it was likely storing up the excess.&lt;/p&gt;

&lt;p&gt;Also at meal times I&amp;#8217;d usually serve myself a full plate, and always feel that I needed to finish it. I liked feeling full. However, again, this likely just meant I was eating more than I needed, and I found that just by serving less food I was still satisfying my hunger but with less excess.&lt;/p&gt;

&lt;p&gt;After a relatively short period of time I found that by avoiding these large meals, I needed less to feel full – as if my stomach had shrunk and gotten used to the reduced size. This was a great positive feedback loop, as it massively helped avoid the temptation to snack between meals.&lt;/p&gt;

&lt;h3 id='cut_down_on_sugarfat'&gt;Cut down on sugar/fat&lt;/h3&gt;

&lt;p&gt;I realise this can be hard for some people, I found it relatively easy but as you can see on the graph above there are some upward trends, which were mainly when I went to visit my parents, who have a cupboard full of chocolates, crisps, cakes, sweets, etc, and I find it really hard not to have at least one or two fake Lidl snickers bars per day!&lt;/p&gt;

&lt;p&gt;However, also note that after an upward trend, I lost the weight again pretty quickly, so don&amp;#8217;t worry too much about a few days of eating junk, I actually noticed how bad I felt afterwards after getting used to a reduced sugar/fat intake, and that provided good incentive to cut down again.&lt;/p&gt;

&lt;p&gt;Some practical things I did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Stopped putting sugar in tea/coffee. I&amp;#8217;ve since regressed, but it was helpful to do this for a while, and definitely helped wean my body off desiring sugar.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Avoided snacking on crisps, chocolate, biscuits, etc. When you work from home this can be difficult, but I found it helped to ensure they weren&amp;#8217;t in the house to begin with, and that we were stocked up on bananas, apples, and other less sugary/fatty snacks.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Used a fine cheese grater when making sandwiches, beans on toast, etc. Previously I&amp;#8217;d put a good few slabs of cheese in, when I didn&amp;#8217;t really need that quantity. The fine grater ensured I still got the taste, but with less quantity.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Bought reduced fat mayonnaise, margarine, etc. These actually taste pretty good these days, and in a sandwich with lots of fresh cucumber, tomato, salad etc you don&amp;#8217;t notice the difference&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these things helped to lose weight and, in a similar manner to the &amp;#8216;eating less&amp;#8217; part, trained my body to not require them as much as it used to – and actually, to noticeably feel worse if ever I regressed, which made getting back on track very easy.&lt;/p&gt;

&lt;h3 id='weigh_myself_daily'&gt;Weigh myself daily&lt;/h3&gt;

&lt;p&gt;It seems this is generally not recommended, and advice is that you should weigh yourself weekly (at the same time each week). Logically this doesn&amp;#8217;t make sense to me, as a geek it&amp;#8217;s obvious that the more data points you have, the better. Your body weight can fluctuate quite a lot from day to day especially with regards to how much liquid you have drunk, and if you are only weighing yourself once per week you could get caught out by a daily spike.&lt;/p&gt;

&lt;p&gt;Aside from the geek factor of a better graph resolution, I also prefer daily weighing as it provides me, as a perfectionist, with incentives both ways. If I weigh less compared to the previous day, I feel good that I am achieving my aim, and am encouraged to continue. If I weigh more, it&amp;#8217;s a warning that I may have eaten too much, and I am then motivated to be more careful that day.&lt;/p&gt;

&lt;p&gt;Weighing daily also helps to just keep your mind reminded of the task, plus if you&amp;#8217;re on the Wii Fit already you might be tempted to do some exercise :)&lt;/p&gt;

&lt;h2 id='next_steps'&gt;Next steps&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;m not content to stay here, the next plan is to get closer to my ideal BMI weight which is around 80kg. This is likely to be much harder, as there is less excess fat for me to get rid of now. However, one thing I haven&amp;#8217;t done so far is increase the amount of exercise I do, and there is definitely room for improvement there!&lt;/p&gt;

&lt;p&gt;Hopefully I can provide another update later this year and perhaps be around 85kg.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>How to fix stdio buffering</title>
      <link>http://www.perkin.org.uk/posts/how-to-fix-stdio-buffering.html</link>
      <pubDate>Thu, 23 Jun 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/how-to-fix-stdio-buffering.html</guid>
      <description>&lt;p&gt;It&amp;#8217;s a common problem. You write some shell command like:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | egrep -v &lt;span class='s1'&gt;&amp;#39;some|stuff&amp;#39;&lt;/span&gt; | sed | awk
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and wonder why nothing is printed, even though you know some text has matched. The problem is that stdio is being buffered, and there&amp;#8217;s a very good write-up of the problem &lt;a href='http://www.pixelbeat.org/programming/stdio_buffering/'&gt;here&lt;/a&gt; so I won&amp;#8217;t repeat the technical background.&lt;/p&gt;

&lt;p&gt;What I will provide though is how to fix it for common cases.&lt;/p&gt;

&lt;h2 id='stdbuf'&gt;stdbuf&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;stdbuf&lt;/code&gt; is part of GNU coreutils, and is essentially an &lt;code&gt;LD_PRELOAD&lt;/code&gt; hack which calls &lt;code&gt;setvbuf()&lt;/code&gt; for an application. Thus it is a generic solution to the problem and can be used to fix most applications. Usage looks like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | stdbuf -o0 app ...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;which will disable output buffering for app, assuming it does not do something itself to reverse the &lt;code&gt;setvbuf()&lt;/code&gt; call. An example of a misbehaving application is &lt;code&gt;mawk&lt;/code&gt;, below.&lt;/p&gt;

&lt;h2 id='awk'&gt;awk&lt;/h2&gt;

&lt;p&gt;GNU &lt;code&gt;awk&lt;/code&gt; needs no modifications, that is it does not buffer when there is no controlling tty.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mawk&lt;/code&gt; however (the default &lt;code&gt;awk&lt;/code&gt; in Debian/Ubuntu and possibly others) buffers output, and also does not seem to work with &lt;code&gt;stdbuf&lt;/code&gt;. It does however provide a &lt;code&gt;-Winteractive&lt;/code&gt; option which will turn off buffering.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | gawk
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | mawk -Winteractive
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='sed'&gt;sed&lt;/h2&gt;

&lt;p&gt;GNU &lt;code&gt;sed&lt;/code&gt; provides the &lt;code&gt;-u&lt;/code&gt; option which calls &lt;code&gt;fflush()&lt;/code&gt;, thereby providing unbuffered output. You can also use &lt;code&gt;stdbuf&lt;/code&gt; as above.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | sed -u
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | stdbuf -o0 sed
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='grep'&gt;grep&lt;/h2&gt;

&lt;p&gt;Similar to &lt;code&gt;sed&lt;/code&gt;, GNU &lt;code&gt;grep&lt;/code&gt; provides a specific option, &lt;code&gt;--line-buffered&lt;/code&gt;, to disable buffering, or again you can use &lt;code&gt;stdbuf&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | grep --line-buffered
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; tail -f /var/log/foo | stdbuf -o0 grep
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Serving multiple DNS search domains in IOS DHCP</title>
      <link>http://www.perkin.org.uk/posts/serving-multiple-dns-search-domains-in-ios-dhcp.html</link>
      <pubDate>Mon, 13 Jun 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/serving-multiple-dns-search-domains-in-ios-dhcp.html</guid>
      <description>&lt;p&gt;I have a Cisco router at home which I also use as a DHCP server, and it works pretty well. Today I wanted to fix a long-standing issue on my network, in that I want multiple DNS search domains.&lt;/p&gt;

&lt;p&gt;First off, the domain-name DHCP option doesn&amp;#8217;t support multiple entries so we can&amp;#8217;t use that. So, off to try raw DHCP option codes. You can find the list of options &lt;a href='http://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xml'&gt;here&lt;/a&gt;, thus 119 is the one I want.&lt;/p&gt;

&lt;p&gt;Trying a simple:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;ip dhcp pool host.net.example.com
   option 119 ascii net.example.com,example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;didn&amp;#8217;t work at all. A quick prod of lazyweb (in this case Simon on IRC) suggested using hex input instead. In order to do that we need to convert the ASCII string into Cisco&amp;#8217;s hex sequence, which is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Split domain name by dot&lt;/li&gt;

&lt;li&gt;Prepend each string by its length (in hex)&lt;/li&gt;

&lt;li&gt;NUL terminate each domain&lt;/li&gt;

&lt;li&gt;Dot-seperate the final string in 16bit chunks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To do this I wrote a quick Python script:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='python'&gt;&lt;span class='c'&gt;#!/usr/bin/python&lt;/span&gt;

&lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;sys&lt;/span&gt;

&lt;span class='n'&gt;hexlist&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[]&lt;/span&gt;
&lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;domain&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='n'&gt;sys&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;argv&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;:]:&lt;/span&gt;
    &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;part&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='n'&gt;domain&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
        &lt;span class='n'&gt;hexlist&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;%02x&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;%&lt;/span&gt; &lt;span class='nb'&gt;len&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;part&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
        &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='n'&gt;part&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
            &lt;span class='n'&gt;hexlist&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;encode&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;hex&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
    &lt;span class='n'&gt;hexlist&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;00&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;print&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;join&lt;/span&gt;&lt;span class='p'&gt;([(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;.&lt;/span&gt;&lt;span class='si'&gt;%s&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;%&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='ow'&gt;and&lt;/span&gt; &lt;span class='ow'&gt;not&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;%&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; \
               &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='nb'&gt;enumerate&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;hexlist&lt;/span&gt;&lt;span class='p'&gt;)])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;which can be used like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; ./cisco.py net.example.com example.com
&lt;span class='go'&gt;036e.6574.0765.7861.6d70.6c65.0363.6f6d.0007.6578.616d.706c.6503.636f.6d00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then back to IOS and paste it in:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;ip dhcp pool host.net.example.com
   option 119 hex 036e.6574.0765.7861.6d70.6c65.0363.6f6d.0007.6578.616d.706c.6503.636f.6d00
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This seems to do what we want, though IOS appears to append a dot to each domain when serving via DHCP.&lt;/p&gt;

&lt;p&gt;One last note, if you use this in addition to domain-name then the option 119 list will be appended to the domain-name name in the search list, so you&amp;#8217;d actually want something like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;ip dhcp pool host.net.example.com
   domain-name net.example.com
   option 119 hex 0765.7861.6d70.6c65.0363.6f6d.00
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;to generate a resolv.conf containing:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;domain net.example.com
search net.example.com example.com.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Fix Firefox URL double click behaviour</title>
      <link>http://www.perkin.org.uk/posts/fix-firefox-url-double-click-behaviour.html</link>
      <pubDate>Mon, 13 Jun 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/fix-firefox-url-double-click-behaviour.html</guid>
      <description>&lt;p&gt;One of the best things I find with OS X is the consistent and sane handling of keyboard and mouse bindings. Since having to move back to Linux for work I am constantly frustrated that different applications all have their own idea of what shortcuts to use.&lt;/p&gt;

&lt;p&gt;One of the biggest annoyances was the mouse click behaviour in the browser URL bar. OS X behaviour is one click to position cursor, two clicks to select a word, three clicks to select all. I rely on this behaviour a lot as I frequently copy/paste parts of URLs.&lt;/p&gt;

&lt;p&gt;Thankfully that&amp;#8217;s one that can be fixed easily. Simply navigate to &lt;a href='about:config'&gt;about:config&lt;/a&gt; and double click on the &lt;code&gt;browser.urlbar.doubleClickSelectsAll&lt;/code&gt; key to set it to false.&lt;/p&gt;

&lt;p&gt;One annoyance down, lots more to go..&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>SSH via HTTP proxy in OSX</title>
      <link>http://www.perkin.org.uk/posts/ssh-via-http-proxy-in-osx.html</link>
      <pubDate>Wed, 20 Apr 2011 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/ssh-via-http-proxy-in-osx.html</guid>
      <description>&lt;p&gt;If you happen to be stuck behind a corporate firewall with only HTTP proxies for external access, you might still be able to SSH out through them using the built-in &lt;code&gt;nc&lt;/code&gt; on OSX.&lt;/p&gt;

&lt;p&gt;First, hope that the proxies haven&amp;#8217;t disabled the &lt;code&gt;CONNECT&lt;/code&gt; method, then simply add a section to your &lt;code&gt;.ssh/config&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;Host foobar.example.com
    ProxyCommand          nc -X connect -x proxyhost:proxyport %h %p
    ServerAliveInterval   10
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This will tunnel the connection through the HTTP proxy to the remote server. The &lt;code&gt;ServerAliveInterval&lt;/code&gt; setting is required as most proxies will drop the connection after a period of inactivity.&lt;/p&gt;

&lt;p&gt;To avoid issues with trying to connect to the host when not behind the corporate firewall, replace the above with a fake entry for the proxy method like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;Host foobar-proxy.example.com
    HostName              foobar.example.com
    ProxyCommand          nc -X connect -x proxyhost:proxyport %h %p
    ServerAliveInterval   10
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then use&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; ssh foobar-proxy.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;when inside the firewall, and&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; ssh foobar.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;when outside.&lt;/p&gt;

&lt;p&gt;Simples, no external software required.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>How to build MySQL releases</title>
      <link>http://www.perkin.org.uk/posts/how-to-build-mysql-releases.html</link>
      <pubDate>Tue, 09 Nov 2010 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/how-to-build-mysql-releases.html</guid>
      <description>&lt;p&gt;One of the major benefits from the &lt;a href='http://forge.mysql.com/wiki/CMake'&gt;CMake work&lt;/a&gt; available in MySQL 5.5 is that in the MySQL Release Engineering team we have been able to make it easy for users and developers to build MySQL exactly as we do for the official releases. For too long there has been a disconnect between the binaries produced as part of a regular &amp;#8220;&lt;code&gt;./configure; make&lt;/code&gt;&amp;#8221; build and what we ship to users and customers.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;re still not exactly where we want to be, there are still some parts which need to be integrated into the server tree, but for now it&amp;#8217;s relatively straightforward to build exactly as we do.&lt;/p&gt;

&lt;p&gt;Here are the instructions, using the &lt;code&gt;mysql-5.5.6-rc.tar.gz&lt;/code&gt; source tarball as an example.&lt;/p&gt;

&lt;h2 id='targz'&gt;tar.gz&lt;/h2&gt;

&lt;p&gt;These are the generic instructions to build a tarball release. Note that we make use of CMake&amp;#8217;s out-of-srcdir support to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ensure the source directory is kept pristine&lt;/li&gt;

&lt;li&gt;allow us to easily build both debug and release binaries, and package them together&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

tar -zxf mysql-5.5.6-rc.tar.gz

&lt;span class='c'&gt;# Build debug binaries first, they are picked up in the final &amp;#39;make package&amp;#39;&lt;/span&gt;
mkdir debug
&lt;span class='o'&gt;(&lt;/span&gt;
  &lt;span class='nb'&gt;cd &lt;/span&gt;debug
  cmake ../mysql-5.5.6-rc -DBUILD_CONFIG&lt;span class='o'&gt;=&lt;/span&gt;mysql_release -DCMAKE_BUILD_TYPE&lt;span class='o'&gt;=&lt;/span&gt;Debug
  make &lt;span class='nv'&gt;VERBOSE&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1
&lt;span class='o'&gt;)&lt;/span&gt;

&lt;span class='c'&gt;# Build release binaries and create final package&lt;/span&gt;
mkdir release
&lt;span class='o'&gt;(&lt;/span&gt;
  &lt;span class='nb'&gt;cd &lt;/span&gt;release
  cmake ../mysql-5.5.6-rc -DBUILD_CONFIG&lt;span class='o'&gt;=&lt;/span&gt;mysql_release
  make &lt;span class='nv'&gt;VERBOSE&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;1 package
&lt;span class='o'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Assuming everything goes ok, you should end up with a tarball in the &lt;code&gt;release/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Some platforms require extra flags to be specified on the CMake command line to ensure the correct compiler etc is used. Here are some that we use.&lt;/p&gt;

&lt;h3 id='avoid_libstdc_dependancy'&gt;Avoid libstdc++ dependancy&lt;/h3&gt;

&lt;p&gt;In order to create &amp;#8220;generic&amp;#8221; binaries, on GCC platforms we compile using &lt;code&gt;CXX=gcc&lt;/code&gt;. This avoids &lt;code&gt;libstdc++&lt;/code&gt; being pulled in, and means that the server will run across a larger range of releases as you do not rely on having the exact version of &lt;code&gt;libstdc++&lt;/code&gt; installed by your system package manager.&lt;/p&gt;

&lt;p&gt;Paste this before running cmake.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; CXXFLAGS is required to trick CMake into believing it is a C++ compiler
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;CXX&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;gcc; &lt;span class='nv'&gt;CXXFLAGS&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-fno-exceptions&amp;quot;&lt;/span&gt;; &lt;span class='nb'&gt;export &lt;/span&gt;CXX CXXFLAGS
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='specify_target_architecture'&gt;Specify target architecture&lt;/h3&gt;

&lt;p&gt;On systems which support multiple targets, you can specify exactly which one you want, rather than relying on the OS default. These strings are meant to be added to the cmake command lines above.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OSX&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; -DCMAKE_OSX_ARCHITECTURES&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;i386&amp;quot;&lt;/span&gt;    &lt;span class='c'&gt;# 32bit&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; -DCMAKE_OSX_ARCHITECTURES&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;x86_64&amp;quot;&lt;/span&gt;  &lt;span class='c'&gt;# 64bit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;GCC/Sun Studio&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; -DCMAKE_C_FLAGS&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-m32&amp;quot;&lt;/span&gt; -DCMAKE_CXX_FLAGS&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-m32&amp;quot;&lt;/span&gt;  &lt;span class='c'&gt;# 32bit&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; -DCMAKE_C_FLAGS&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-m64&amp;quot;&lt;/span&gt; -DCMAKE_CXX_FLAGS&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;-m64&amp;quot;&lt;/span&gt;  &lt;span class='c'&gt;# 64bit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;HP/UX&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; -DCMAKE_C_FLAGS&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;+DD64&amp;quot;&lt;/span&gt; -DCMAKE_CXX_FLAGS&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;+DD64&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='rpm'&gt;RPM&lt;/h2&gt;

&lt;p&gt;We&amp;#8217;ve spent a lot of time improving the RPM builds too. Previously some of the configuration was only available in the commercial RPM builds, but now we have merged them into the community version.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

mkdir -p rpm/&lt;span class='o'&gt;{&lt;/span&gt;BUILD,RPMS,SOURCES,SPECS,SRPMS&lt;span class='o'&gt;}&lt;/span&gt; tmp

&lt;span class='c'&gt;# Create spec file.&lt;/span&gt;
&lt;span class='c'&gt;# XXX: We should probably just include this in the source tarball.&lt;/span&gt;
tar -zxf mysql-5.5.6-rc.tar.gz
&lt;span class='o'&gt;(&lt;/span&gt;
  mkdir bld; &lt;span class='nb'&gt;cd &lt;/span&gt;bld
  cmake ../mysql-5.5.6-rc
&lt;span class='o'&gt;)&lt;/span&gt;

cp bld/support-files/*.spec rpm/SPECS
cp mysql-5.5.6-rc.tar.gz rpm/SOURCES

rpmbuild -v --define&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;_topdir $PWD/rpm&amp;quot;&lt;/span&gt; --define&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;_tmppath $PWD/tmp&amp;quot;&lt;/span&gt; &lt;span class='se'&gt;\&lt;/span&gt;
 -ba rpm/SPECS/mysql.5.5.6-rc.spec
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You should end up with nice shiny RPMs in &lt;code&gt;rpm/RPMS&lt;/code&gt;. One thing to note is that the RPM spec no longer runs the test suite as part of the build, so you will need to run that separately. On the plus side, you get your RPMs much quicker.&lt;/p&gt;

&lt;p&gt;Another nice thing about the improved RPM spec is that you can now build targetted distribution RPMs, as we do. These have extra dependancy information in them tailored to the target distribution. Currently the spec file supports the distributions we build on, but we will accept patches for others.&lt;/p&gt;

&lt;p&gt;To enable this, use:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; rpmbuild -v --define&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;distro_specific 1&amp;quot;&lt;/span&gt; ...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='windows'&gt;Windows&lt;/h2&gt;

&lt;p&gt;Our Windows builds have relied on CMake since MySQL 5.0, but the procedure has still changed to ensure that you can build as we do. These instructions use &lt;code&gt;cmd.exe&lt;/code&gt; but you can use the Visual Studio front end if you prefer.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bat'&gt;unzip mysql&lt;span class='m'&gt;-5&lt;/span&gt;.&lt;span class='m'&gt;5&lt;/span&gt;.&lt;span class='m'&gt;6&lt;/span&gt;-rc.zip

&lt;span class='c'&gt;rem There is no separate &amp;#39;debug&amp;#39; directory on Windows, as the CMake&lt;/span&gt;
&lt;span class='c'&gt;rem infrastructure doesn&amp;#39;t yet know to pull files in from there on Windows.&lt;/span&gt;
&lt;span class='k'&gt;md&lt;/span&gt; release
&lt;span class='k'&gt;cd&lt;/span&gt; release

&lt;span class='c'&gt;rem Choose your target architecture, 32bit&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nv'&gt;VSTARGET&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;Visual Studio &lt;span class='m'&gt;9&lt;/span&gt; &lt;span class='m'&gt;2008&lt;/span&gt;
&lt;span class='c'&gt;rem or 64bit&lt;/span&gt;
&lt;span class='k'&gt;set&lt;/span&gt; &lt;span class='nv'&gt;VSTARGET&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;Visual Studio &lt;span class='m'&gt;9&lt;/span&gt; &lt;span class='m'&gt;2008&lt;/span&gt; Win&lt;span class='m'&gt;64&lt;/span&gt;

cmake ..\mysql&lt;span class='m'&gt;-5&lt;/span&gt;.&lt;span class='m'&gt;5&lt;/span&gt;.&lt;span class='m'&gt;6&lt;/span&gt;-rc -DBUILD_CONFIG&lt;span class='o'&gt;=&lt;/span&gt;mysql_release \
 -DCMAKE_BUILD_TYPE&lt;span class='o'&gt;=&lt;/span&gt;Debug -G &lt;span class='s2'&gt;&amp;quot;%VSTARGET%&amp;quot;&lt;/span&gt;

devenv MySql.sln &lt;span class='n'&gt;/build&lt;/span&gt; Debug

cmake ..\mysql&lt;span class='m'&gt;-5&lt;/span&gt;.&lt;span class='m'&gt;5&lt;/span&gt;.&lt;span class='m'&gt;6&lt;/span&gt;-rc -DBUILD_CONFIG&lt;span class='o'&gt;=&lt;/span&gt;mysql_release \
 -DCMAKE_BUILD_TYPE&lt;span class='o'&gt;=&lt;/span&gt;RelWithDebInfo -G &lt;span class='s2'&gt;&amp;quot;%VSTARGET%&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can now choose which type of package to create. 5.5 includes new code to create minimal MSI packages, these should work ok, and only differ from the official MySQL MSI packages in that they do not include the instance config wizard.&lt;/p&gt;

&lt;p&gt;To create the MSI packages you will need to install &lt;a href='http://wix.codeplex.com/'&gt;WiX&lt;/a&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bat'&gt;&lt;span class='c'&gt;rem Standard zip package&lt;/span&gt;
devenv MySql.sln &lt;span class='n'&gt;/build&lt;/span&gt; RelWithDebInfo &lt;span class='n'&gt;/project&lt;/span&gt; package

&lt;span class='c'&gt;rem Full MSI package&lt;/span&gt;
devenv MySql.sln &lt;span class='n'&gt;/build&lt;/span&gt; RelWithDebInfo &lt;span class='n'&gt;/project&lt;/span&gt; msi

&lt;span class='c'&gt;rem &amp;#39;Essentials&amp;#39; MSI package&lt;/span&gt;
devenv MySql.sln &lt;span class='n'&gt;/build&lt;/span&gt; RelWithDebInfo &lt;span class='n'&gt;/project&lt;/span&gt; msi_essentials
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Assuming everything goes ok, you should have some packages in the &lt;code&gt;release\&lt;/code&gt; directory.&lt;/p&gt;

&lt;h2 id='work_still_to_be_done'&gt;Work still to be done&lt;/h2&gt;

&lt;p&gt;We still have a number of scripts only available internally, for example those we use to create SVR4, DMG and DEPOT packages. However, we are looking to integrate these into the MySQL Server source tree so that all users can benefit from them.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>'apt-get' and 5,000 packages for Solaris10/x86</title>
      <link>http://www.perkin.org.uk/posts/apt-get-and-5000-packages-for-solaris10x86.html</link>
      <pubDate>Thu, 29 Apr 2010 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/apt-get-and-5000-packages-for-solaris10x86.html</guid>
      <description>&lt;p&gt;Here&amp;#8217;s how:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;#&lt;/span&gt; Install pkg_* tools and the &lt;span class='s1'&gt;&amp;#39;pkgin&amp;#39;&lt;/span&gt; package manager
&lt;span class='gp'&gt;$&lt;/span&gt; pkgadd -d http://www.netbsd.org/~jperkin/TNFpkgsrc-x86.pkg all

&lt;span class='gp'&gt;#&lt;/span&gt; Add tools to PATH
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/opt/pkg/sbin:/opt/pkg/bin:&lt;span class='nv'&gt;$PATH&lt;/span&gt;

&lt;span class='gp'&gt;#&lt;/span&gt; Update package repository &lt;span class='o'&gt;(&lt;/span&gt;akin to &lt;span class='s1'&gt;&amp;#39;apt-get update&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin up

&lt;span class='gp'&gt;#&lt;/span&gt; Search &lt;span class='k'&gt;for &lt;/span&gt;a particular package &lt;span class='o'&gt;(&lt;/span&gt;you can use regexp&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin search ^ap.*python 

&lt;span class='gp'&gt;#&lt;/span&gt; Install it
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin install ap22-py25-python

&lt;span class='gp'&gt;#&lt;/span&gt; Update all packages &lt;span class='o'&gt;(&lt;/span&gt;akin to &lt;span class='s1'&gt;&amp;#39;apt-get dist-upgrade&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin full-upgrade

&lt;span class='gp'&gt;#&lt;/span&gt; How many packages are available?
&lt;span class='gp'&gt;$&lt;/span&gt; pkgin avail | wc -l
&lt;span class='go'&gt;   4970&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ok, so the headline might be slightly mis-leading, this isn&amp;#8217;t really apt-get but a tool which is very similar. This is work which builds upon my &lt;a href='http://www.perkin.org.uk/posts/pkgsrc-on-solaris.html'&gt;previous post&lt;/a&gt; using pkgsrc to build binary packages on Solaris.&lt;/p&gt;

&lt;p&gt;See &lt;a href='http://imil.net/pkgin/'&gt;http://imil.net/pkgin/&lt;/a&gt; for more information on pkgin.&lt;/p&gt;

&lt;p&gt;Hopefully this will prove really useful to people still using Solaris 10 and unable to use the new pkg(5) stuff in OpenSolaris.&lt;/p&gt;

&lt;p&gt;Please try it out and provide any feedback to &lt;a href='mailto:pkgsrc-users@netbsd.org'&gt;pkgsrc-users@netbsd.org&lt;/a&gt;. I&amp;#8217;m hoping to keep the packages updated for the 2009Q3 branch.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>ZFS and NFS vs OSX</title>
      <link>http://www.perkin.org.uk/posts/zfs-and-nfs-vs-osx.html</link>
      <pubDate>Wed, 16 Sep 2009 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/zfs-and-nfs-vs-osx.html</guid>
      <description>&lt;p&gt;gromit is my Solaris 10 server, chorlton is my OSX desktop. Explain this:&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;root@gromit#&lt;/span&gt; zfs &lt;span class='nb'&gt;set &lt;/span&gt;&lt;span class='nv'&gt;sharenfs&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;anon=shared,sec=none&amp;#39;&lt;/span&gt; gromit/store
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;root@gromit#&lt;/span&gt; zfs get sharenfs gromit/store
&lt;span class='go'&gt;NAME          PROPERTY  VALUE                 SOURCE&lt;/span&gt;
&lt;span class='go'&gt;gromit/store  sharenfs  anon=shared,sec=none  local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;user@chorlton$&lt;/span&gt; ls /net/gromit/store
&lt;span class='go'&gt;ls: cannot open directory /net/gromit/store/: Operation not permitted&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;root@gromit#&lt;/span&gt; zfs &lt;span class='nb'&gt;set &lt;/span&gt;&lt;span class='nv'&gt;sharenfs&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;anon=shared&amp;#39;&lt;/span&gt; gromit/store
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;user@chorlton$&lt;/span&gt; ls /net/gromit/store
&lt;span class='go'&gt;file1  file2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;user@chorlton$&lt;/span&gt; touch /net/gromit/store/file3
&lt;span class='go'&gt;touch: /net/gromit/store/file3: Permission denied&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;root@gromit#&lt;/span&gt; zfs &lt;span class='nb'&gt;set &lt;/span&gt;&lt;span class='nv'&gt;sharenfs&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;anon=shared,sec=none&amp;#39;&lt;/span&gt; gromit/store
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;user@chorlton$&lt;/span&gt; touch /net/gromit/store/file3
&lt;span class='gp'&gt;user@chorlton$&lt;/span&gt; &lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='nv'&gt;$?&lt;/span&gt;
&lt;span class='go'&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>pkgsrc on Solaris</title>
      <link>http://www.perkin.org.uk/posts/pkgsrc-on-solaris.html</link>
      <pubDate>Sat, 12 Sep 2009 00:00:00 +0100</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/pkgsrc-on-solaris.html</guid>
      <description>&lt;p&gt;For many years, building and installing third-party software on Solaris has been a huge pain. For people who do not use &lt;a href='http://www.pkgsrc.org/'&gt;pkgsrc&lt;/a&gt;, that is.&lt;/p&gt;

&lt;p&gt;Originating from the &lt;a href='http://www.netbsd.org/'&gt;NetBSD&lt;/a&gt; project, pkgsrc is a source-based cross-platform package manager. If you&amp;#8217;ve used FreeBSD ports, then it is very similar as it derives from the same codebase, so the basic premise is that you:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /usr/pkgsrc/www/apache22
&lt;span class='gp'&gt;$&lt;/span&gt; make package
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and pkgsrc will download the source for Apache 2.2, compile it and all dependancies, install it on the local system and create a package which can be installed on other similar systems.&lt;/p&gt;

&lt;p&gt;However, we&amp;#8217;ve taken ports further and applied the NetBSD philosophy of portability, meaning that it not only works on NetBSD, but across all *BSD as well as Linux, OSX, HP/UX, AIX, IRIX, QNX, Windows (via Interix), and of course Solaris.&lt;/p&gt;

&lt;p&gt;So while apt-get might be awesome, it only really works on Linux. FreeBSD might have way more ports than us, but only runs on FreeBSD and OSX. pkgsrc provides a consistent interface across all the platforms listed above, and in some cases provides a superior package manager than the system provides.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s how I use pkgsrc on Solaris, in this specific case Solaris 10/x86. Paths are specific to my setup, you can of course change them.&lt;/p&gt;

&lt;h2 id='create_a_chrootzone_environment'&gt;Create a chroot/zone environment&lt;/h2&gt;

&lt;p&gt;I use the zones feature of Solaris 10 to ensure that all packages are built in a sandbox. This has a number of benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The running system is unaffected by the builds, in that they are not writing to the same file system. This is good when you have misbehaving packages.&lt;/li&gt;

&lt;li&gt;You can separate the build and install phases, so that you can verify all the packages have been built and are correct before starting any install/upgrade procedure&lt;/li&gt;

&lt;li&gt;It&amp;#8217;s easier to catch package mistakes, e.g. unpackaged files.&lt;/li&gt;

&lt;li&gt;It avoids pollution from the host environment which may produce bad packages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For creating a zone, I wrote the following &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/create-zone'&gt;&lt;code&gt;create-zone&lt;/code&gt;&lt;/a&gt; script:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='nv'&gt;DOMAIN&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;adsl.perkin.org.uk&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;MASQDOMAIN&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;perkin.org.uk&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;PHYSIF&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;e1000g0&amp;quot;&lt;/span&gt;
&lt;span class='nv'&gt;RPOOL&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;gromit&amp;quot;&lt;/span&gt;

&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='nv'&gt;$# &lt;/span&gt;-eq 1 &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='nv'&gt;$1&lt;/span&gt;; &lt;span class='nb'&gt;shift&lt;/span&gt;
&lt;span class='nb'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;ipaddr&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='sb'&gt;`&lt;/span&gt;getent hosts &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; | awk &lt;span class='s1'&gt;&amp;#39;{print $1}&amp;#39;&lt;/span&gt;&lt;span class='sb'&gt;`&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; -z &lt;span class='s2'&gt;&amp;quot;${ipaddr}&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;        &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;ERROR: Could not determine IP address of $name&amp;quot;&lt;/span&gt;
        &lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Either add to hosts database or provide on command line&amp;quot;&lt;/span&gt;
        &lt;span class='nb'&gt;echo&lt;/span&gt;
&lt;span class='nb'&gt;        echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;usage: $0 &amp;lt;name&amp;gt; [ &amp;lt;ipaddr&amp;gt; ]&amp;quot;&lt;/span&gt;
        &lt;span class='nb'&gt;exit &lt;/span&gt;2
    &lt;span class='k'&gt;fi&lt;/span&gt;
&lt;span class='k'&gt;elif&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='nv'&gt;$# &lt;/span&gt;-eq 2 &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='nv'&gt;$1&lt;/span&gt;; &lt;span class='nb'&gt;shift&lt;/span&gt;
&lt;span class='nb'&gt;    &lt;/span&gt;&lt;span class='nv'&gt;ipaddr&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='nv'&gt;$1&lt;/span&gt;; &lt;span class='nb'&gt;shift&lt;/span&gt;
&lt;span class='k'&gt;else&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;usage: $0 &amp;lt;name&amp;gt; [ &amp;lt;ipaddr&amp;gt; ]&amp;quot;&lt;/span&gt;
    &lt;span class='nb'&gt;exit &lt;/span&gt;2
&lt;span class='k'&gt;fi&lt;/span&gt;

zfs list &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;RPOOL&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/zones/&lt;span class='nv'&gt;$name&lt;/span&gt; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='nv'&gt;$?&lt;/span&gt; -eq 0 &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;${RPOOL}/zones/$name already exists, not continuing&amp;quot;&lt;/span&gt;
    &lt;span class='nb'&gt;exit &lt;/span&gt;1
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='c'&gt;# Inherited directories are read-only&lt;/span&gt;
cat &amp;gt;/tmp/zonecfg.&lt;span class='nv'&gt;$$&lt;/span&gt; &lt;span class='s'&gt;&amp;lt;&amp;lt; EOF&lt;/span&gt;
&lt;span class='s'&gt;    create&lt;/span&gt;
&lt;span class='s'&gt;    set zonepath=/zones/$name&lt;/span&gt;
&lt;span class='s'&gt;    set autoboot=true&lt;/span&gt;
&lt;span class='s'&gt;    add net&lt;/span&gt;
&lt;span class='s'&gt;        set address=$ipaddr/24&lt;/span&gt;
&lt;span class='s'&gt;        set physical=${PHYSIF}&lt;/span&gt;
&lt;span class='s'&gt;    end&lt;/span&gt;
&lt;span class='s'&gt;    verify&lt;/span&gt;
&lt;span class='s'&gt;    commit&lt;/span&gt;
&lt;span class='s'&gt;    exit&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;

zonecfg -z &lt;span class='nv'&gt;$name&lt;/span&gt; -f /tmp/zonecfg.&lt;span class='nv'&gt;$$&lt;/span&gt;
rm /tmp/zonecfg.&lt;span class='nv'&gt;$$&lt;/span&gt;

zoneadm -z &lt;span class='nv'&gt;$name&lt;/span&gt; install

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Automatically configure new zone with most of the settings from the current&lt;/span&gt;
&lt;span class='c'&gt;# global, grabbing the encrypted root password directly.  Note that the&lt;/span&gt;
&lt;span class='c'&gt;# service_profile keyword doesn&amp;#39;t seem to be used here, so we configure the&lt;/span&gt;
&lt;span class='c'&gt;# limited_net profile manually and optionally install a custom site.xml which&lt;/span&gt;
&lt;span class='c'&gt;# is parsed and activated during first boot.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
cat &lt;span class='s'&gt;&amp;lt;&amp;lt; EOF &amp;gt;/zones/$name/root/etc/sysidcfg&lt;/span&gt;
&lt;span class='s'&gt;network_interface=PRIMARY&lt;/span&gt;
&lt;span class='s'&gt;{&lt;/span&gt;
&lt;span class='s'&gt;    hostname=$name.${DOMAIN}&lt;/span&gt;
&lt;span class='s'&gt;}&lt;/span&gt;
&lt;span class='s'&gt;name_service=DNS&lt;/span&gt;
&lt;span class='s'&gt;{&lt;/span&gt;
&lt;span class='s'&gt;    domain_name=${DOMAIN}&lt;/span&gt;
&lt;span class='s'&gt;    name_server=`awk &amp;#39;/^nameserver/ { print $NF; exit }&amp;#39; /etc/resolv.conf`&lt;/span&gt;
&lt;span class='s'&gt;}&lt;/span&gt;
&lt;span class='s'&gt;nfs4_domain=dynamic&lt;/span&gt;
&lt;span class='s'&gt;root_password=`awk -F: &amp;#39;/^root/ {print $2}&amp;#39; /etc/shadow`&lt;/span&gt;
&lt;span class='s'&gt;security_policy=NONE&lt;/span&gt;
&lt;span class='s'&gt;service_profile=limited_net&lt;/span&gt;
&lt;span class='s'&gt;system_locale=C&lt;/span&gt;
&lt;span class='s'&gt;terminal=xterm&lt;/span&gt;
&lt;span class='s'&gt;timezone=Europe/London&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Use the limited_net profile and install custom site.xml if provided.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
rm /zones/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/root/var/svc/profile/generic.xml
ln -s generic_limited_net.xml /zones/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/root/var/svc/profile/generic.xml
&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; -f /install/zones/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.xml &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;cp /install/zones/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.xml /zones/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;name&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/root/var/svc/profile/site.xml
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Disable nscd host cache&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/nscd.conf &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;/enable-cache/s/^#//&lt;/span&gt;
&lt;span class='s'&gt;wq&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Configure sendmail to masquerade and route via smarthost.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/mail/cf/cf/submit.mc &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;/^dnl/&lt;/span&gt;
&lt;span class='s'&gt;a&lt;/span&gt;
&lt;span class='s'&gt;FEATURE(\`masquerade_envelope&amp;#39;)dnl&lt;/span&gt;
&lt;span class='s'&gt;MASQUERADE_AS(\`${MASQDOMAIN}&amp;#39;)dnl&lt;/span&gt;
&lt;span class='s'&gt;dnl&lt;/span&gt;
&lt;span class='s'&gt;.&lt;/span&gt;
&lt;span class='s'&gt;/^FEATURE.*msp/s/.127.0.0.1./mail.perkin.org.uk/&lt;/span&gt;
&lt;span class='s'&gt;wq!&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;
&lt;span class='o'&gt;(&lt;/span&gt;
  &lt;span class='nb'&gt;cd&lt;/span&gt; /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/mail/cf/cf
  /usr/ccs/bin/make submit.cf &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;span class='o'&gt;)&lt;/span&gt;
cp /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/mail/cf/cf/submit.cf &lt;span class='se'&gt;\&lt;/span&gt;
   /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/mail/submit.cf

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Use SHA512 crypted passwords, and change root&amp;#39;s home directory.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/security/policy.conf &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;/^CRYPT_DEFAULT/s/__unix__/6/&lt;/span&gt;
&lt;span class='s'&gt;wq&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;
mkdir -m 0700 /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/root
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/passwd &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;/^root/s,:/:,:/root:,&lt;/span&gt;
&lt;span class='s'&gt;/^root/s,:/sbin/sh,:/bin/bash,&lt;/span&gt;
&lt;span class='s'&gt;wq&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;

cp /root/.bash_profile /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/root/.bash_profile

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Allow root login over SSH (rest of network takes care of external access&lt;/span&gt;
&lt;span class='c'&gt;# so this isn&amp;#39;t a problem) and enforce SSH key authentication.&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/ssh/sshd_config &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;/^PermitRootLogin/s/no$/yes/&lt;/span&gt;
&lt;span class='s'&gt;/^PasswordAuthentication/s/yes$/no/&lt;/span&gt;
&lt;span class='s'&gt;wq&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;
mkdir -m 0700 /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/root/.ssh
cp /home/jperkin/.ssh/id_rsa.pub /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/root/.ssh/authorized_keys

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# Automount shared directories from global zone using direct mounts&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/auto_master &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;a&lt;/span&gt;
&lt;span class='s'&gt;/-        auto_direct&lt;/span&gt;
&lt;span class='s'&gt;.&lt;/span&gt;
&lt;span class='s'&gt;wq&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;
ex /zones/&lt;span class='nv'&gt;$name&lt;/span&gt;/root/etc/auto_direct &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class='s'&gt;&amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class='s'&gt;a&lt;/span&gt;
&lt;span class='s'&gt;/content    gromit-lan:/content&lt;/span&gt;
&lt;span class='s'&gt;/install    gromit-lan:/install&lt;/span&gt;
&lt;span class='s'&gt;.&lt;/span&gt;
&lt;span class='s'&gt;wq&lt;/span&gt;
&lt;span class='s'&gt;EOF&lt;/span&gt;

&lt;span class='c'&gt;#&lt;/span&gt;
&lt;span class='c'&gt;# All done!  Fire it up...&lt;/span&gt;
&lt;span class='c'&gt;#&lt;/span&gt;
zoneadm -z &lt;span class='nv'&gt;$name&lt;/span&gt; boot
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And the corresponding &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/delete-zone'&gt;&lt;code&gt;delete-zone&lt;/code&gt;&lt;/a&gt; script is:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='nv'&gt;RPOOL&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;gromit&amp;quot;&lt;/span&gt;

&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='nv'&gt;$# &lt;/span&gt;-ne 1 &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;usage: $0 &amp;lt;zone&amp;gt;&amp;quot;&lt;/span&gt;
    &lt;span class='nb'&gt;exit &lt;/span&gt;2
&lt;span class='k'&gt;fi&lt;/span&gt;

zoneadm -z &lt;span class='nv'&gt;$1&lt;/span&gt; halt
zonecfg -z &lt;span class='nv'&gt;$1&lt;/span&gt; delete -F
zfs destroy &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;RPOOL&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/zones/&lt;span class='nv'&gt;$1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you want to use them then there are some variables to set at the top, and you may want to scan through them for additional bits to change, for example &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/create-zone'&gt;&lt;code&gt;create-zone&lt;/code&gt;&lt;/a&gt; copies my ssh public key which will most likely be wrong for your setup :-)&lt;/p&gt;

&lt;p&gt;One additional piece of configuration for &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/create-zone'&gt;&lt;code&gt;create-zone&lt;/code&gt;&lt;/a&gt; is an optional SMF xml file. I use this file to disable inetd inside the zone for additional security, like so:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='xml'&gt;&lt;span class='cp'&gt;&amp;lt;?xml version=&amp;#39;1.0&amp;#39;?&amp;gt;&lt;/span&gt;
&lt;span class='cp'&gt;&amp;lt;!DOCTYPE service_bundle SYSTEM &amp;#39;/usr/share/lib/xml/dtd/service_bundle.dtd.1&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class='nt'&gt;&amp;lt;service_bundle&lt;/span&gt; &lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;profile&amp;#39;&lt;/span&gt; &lt;span class='na'&gt;name=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;extract&amp;#39;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;lt;service&lt;/span&gt; &lt;span class='na'&gt;name=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;network/inetd&amp;#39;&lt;/span&gt; &lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;service&amp;#39;&lt;/span&gt; &lt;span class='na'&gt;version=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;instance&lt;/span&gt; &lt;span class='na'&gt;name=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;default&amp;#39;&lt;/span&gt; &lt;span class='na'&gt;enabled=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;false&amp;#39;&lt;/span&gt;&lt;span class='nt'&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;lt;/service&amp;gt;&lt;/span&gt;
&lt;span class='nt'&gt;&amp;lt;/service_bundle&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The file should be named &amp;#60;yourzonename&amp;#62;.xml. Mine is named &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/vm-generic.xml'&gt;&lt;code&gt;vm-generic.xml&lt;/code&gt;&lt;/a&gt; and I then create symlinks to it for each VM I want with that default configuration.&lt;/p&gt;

&lt;h2 id='fetch_pkgsrc'&gt;Fetch pkgsrc&lt;/h2&gt;

&lt;p&gt;pkgsrc is developed very rapidly. Tracking nearly 9,000 pieces of third-party software means there are always many updates. Thankfully, we provide quarterly branches for people who want more stability, and I recommend using the latest quarterly release. At time of writing, this is known as &lt;code&gt;pkgsrc-2009Q2&lt;/code&gt;. Within the next month or so we will release &lt;code&gt;pkgsrc-2009Q3&lt;/code&gt;, and you can figure out the names of future releases yourself.&lt;/p&gt;

&lt;p&gt;The easiest way to get pkgsrc is using cvs. I keep stuff like this under &lt;code&gt;/content&lt;/code&gt; as opposed to the default of &lt;code&gt;/usr&lt;/code&gt;, you can use whatever you wish but will need to change all my example scripts to match where you put it.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /content
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;pkgsrc-2009Q2&amp;quot;&lt;/span&gt;
&lt;span class='gp'&gt;$&lt;/span&gt; cvs -d anoncvs@anoncvs.netbsd.org:/cvsroot co -r&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -d&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt; -P pkgsrc
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Alternatively, you can fetch either bzip2 or gzip archives of the current branch. I recommend the cvs method as, with the branch being updated for security fixes and other important changes, you can easily track it using&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /content/pkgsrc-2009Q2
&lt;span class='gp'&gt;$&lt;/span&gt; cvs update
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='pkgsrc_configuration'&gt;pkgsrc configuration&lt;/h2&gt;

&lt;p&gt;pkgsrc is configured using a &lt;code&gt;mk.conf&lt;/code&gt; file, &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/mk.conf'&gt;this&lt;/a&gt; is mine:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;#
# Local settings
#
OS_HOST!= uname -n

#
# Per-host settings
#
#    vm0 builds local packages
#
.if !empty(OS_HOST:Mvm0.*) || !empty(OS_HOST:Mgromit.*)
PKGDIRSUFFIX=
PKG_DEFAULT_OPTIONS=    inet6 perl sasl ssl ncursesw
PKG_OPTIONS.mutt+=      mutt-hcache mutt-smtp
PKG_UID.cyrus=          2000
#PKG_GID.cyrus=         mail
PKG_SHELL.cyrus=        /usr/bin/false
PKG_UID.www=            2001
PKG_GID.www=            2001
PYTHON_VERSION_DEFAULT= 24
X11_TYPE=               modular
#
#    vm1 modular X11 bulk builds
#
.elif !empty(OS_HOST:Mvm1.*)
X11_TYPE=       modular
PKGDIRSUFFIX=   -${X11_TYPE}
#
#    vm2 native X11 bulk builds
#
.elif !empty(OS_HOST:Mvm2.*)
X11_TYPE=       native
PKGDIRSUFFIX=   -${X11_TYPE}
#
#    vm3 pkgsrc dev builds
#
.elif !empty(OS_HOST:Mvm3.*)
X11_TYPE=       modular
PKGDIRSUFFIX=   -${X11_TYPE}
.endif

.if exists(../../CVS/Tag)
PKG_BRANCH!=    ${TOOLS_PLATFORM.awk} -F- &amp;#39;{print $$2}&amp;#39; &amp;lt; ../../CVS/Tag
.else
PKG_BRANCH=     HEAD
.endif

ALLOW_VULNERABLE_PACKAGES=  YES

BULKFILESDIR=           ${WRKOBJDIR}
DISTDIR=                /install/pkgsrc/distfiles/
FAILOVER_FETCH=         YES
INSTALL_UNSTRIPPED=     YES
LINTPKGSRC_DB=          ${_PKGSRCDIR}/.lintpkgsrc.db
MASTER_SITE_OVERRIDE=   ftp://ftp.netbsd.org/pub/NetBSD/packages/distfiles/
PACKAGES=               /install/pkgsrc/packages/${PKG_BRANCH}${PKGDIRSUFFIX}
PKGCHK_CONF=            /install/pkgsrc/misc/pkgchk.conf
SKIP_LICENSE_CHECK=     YES
WRKOBJDIR=              /tmp/pkgsrc

#
# Parse pkgchk.conf and supply list of packages for the bulk build framework.
#
.if defined(SPECIFIC_PKGS)
PKGLIST!= ${TOOLS_PLATFORM.awk} &amp;#39;$$1 !~ /^(\#|$$)/ {print $$1}&amp;#39; ${PKGCHK_CONF}
.  for _pkg_ in ${PKGLIST}
HOST_SPECIFIC_PKGS+= ${_pkg_}
.  endfor
.endif
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is the primary configuration file for pkgsrc. Again, you may need to tailor this to your environment, and may find it useful to read the pkgsrc guide to understand what it all means.&lt;/p&gt;

&lt;p&gt;As I do a lot of pkgsrc development I have a number of virtual machines up and running doing various bits and pieces. Obviously I don&amp;#8217;t want to copy that &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/mk.conf'&gt;mk.conf&lt;/a&gt; around, so I also have a small &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/mk-include.conf'&gt;fragment&lt;/a&gt; file which is appended to each virtual machine&amp;#8217;s &lt;code&gt;mk.conf&lt;/code&gt; (using the &lt;code&gt;--mk-fragment&lt;/code&gt; argument to &lt;code&gt;bootstrap&lt;/code&gt;) and includes the global copy:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;.include &amp;quot;/install/pkgsrc/misc/mk.conf&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The bulk build setup in pkgsrc requires its own configuration, and for this you will need to edit a file inside pkgsrc. There is an example file provided, so what I usually do is symlink this to the real copy then I can easily keep it up-to-date via cvs.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /content/pkgsrc-2009Q2/mk/bulk
&lt;span class='gp'&gt;$&lt;/span&gt; ln -s build.conf-example build.conf
&lt;span class='gp'&gt;$&lt;/span&gt; vi build.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Again, you can find my personal build.conf here.&lt;/p&gt;

&lt;p&gt;Finally, there is a configuration file for &lt;code&gt;pkg_chk&lt;/code&gt; which is a package inside pkgsrc which makes managing upgrades easier (ideally it should be a part of the main pkgsrc tools but that&amp;#8217;s for another day). &lt;code&gt;pkgchk.conf&lt;/code&gt; is a list of package directories, relative to the pkgsrc top level, which are to be built and installed for this setup. If you have a large installation then &lt;code&gt;pkg_chk&lt;/code&gt; has extra features to make it possible to share &lt;code&gt;pkgchk.conf&lt;/code&gt; across a number of machines and configure packages on a per-host, per-OS etc basis.&lt;/p&gt;

&lt;p&gt;Thus, a sample &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/pkgchk.conf'&gt;&lt;code&gt;pkgchk.conf&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;chat/irssi
chat/irssi-icb
converters/xlhtml
databases/lbdb
databases/rrdtool
devel/autoconf
devel/automake
devel/bzr
devel/bzrtools
devel/diffutils
devel/libtool-base
devel/scmcvs
editors/vim
mail/mutt-devel
misc/screen
net/p5-Net-SNMP
net/p5-Net-SNMP-Interfaces
net/rsync
net/samba
net/tnftp
pkgtools/digest
pkgtools/pkg_chk
pkgtools/rc.subr
print/mp
security/cy2-login
security/cy2-plain
security/sudo
sysutils/coreutils
textproc/antiword
textproc/grep
textproc/urlview
www/apache22
www/w3m
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It is highly likely you will want to change the &lt;code&gt;pkgchk.conf&lt;/code&gt; file from what I use :-)&lt;/p&gt;

&lt;h2 id='build_scripts'&gt;Build scripts&lt;/h2&gt;

&lt;p&gt;Once everything is set up, I have two scripts to build then update my packages, intuitively called &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/build-packages'&gt;&lt;code&gt;build-packages&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;/opt/pkg/sbin:/opt/pkg/bin:/sbin:/usr/sbin:/usr/bin:/usr/ccs/bin&amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;export &lt;/span&gt;PATH

&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;2009Q2&amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;export &lt;/span&gt;BRANCH

&lt;span class='nv'&gt;PDIR&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/install/pkgsrc

&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; ! -f &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;PDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/bootstrap-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.tar &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
&lt;span class='k'&gt;    &lt;/span&gt;&lt;span class='nb'&gt;cd&lt;/span&gt; /content/pkgsrc-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/bootstrap
    ./bootstrap --workdir&lt;span class='o'&gt;=&lt;/span&gt;/tmp/pkgsrc --prefix&lt;span class='o'&gt;=&lt;/span&gt;/opt/pkg &lt;span class='se'&gt;\&lt;/span&gt;
                --varbase&lt;span class='o'&gt;=&lt;/span&gt;/var/opt/pkg --sysconfdir&lt;span class='o'&gt;=&lt;/span&gt;/etc/opt/pkg &lt;span class='se'&gt;\&lt;/span&gt;
                --mk-fragment&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;PDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/misc/mk-include.conf &lt;span class='se'&gt;\&lt;/span&gt;
                --binary-kit&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;PDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/bootstrap-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.tar
    rm -rf /tmp/pkgsrc
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; ! -f /opt/pkg/bin/bmake &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cd&lt;/span&gt; /; tar -xf &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;PDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/bootstrap-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.tar&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='nb'&gt;cd&lt;/span&gt; /content/pkgsrc-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;

/bin/ksh mk/bulk/build -s  2&amp;gt;&amp;amp;1 | tee -a &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;PDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/logs/build-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.log
/bin/ksh mk/bulk/upload -n 2&amp;gt;&amp;amp;1 | tee -a &lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;PDIR&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/logs/upload-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.log
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/update-packages'&gt;&lt;code&gt;update-packages&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='c'&gt;#!/bin/sh&lt;/span&gt;

&lt;span class='nv'&gt;PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;/opt/pkg/sbin:/opt/pkg/bin:/sbin:/usr/sbin:/usr/bin:/usr/ccs/bin&amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;export &lt;/span&gt;PATH

&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;2009Q2
&lt;span class='nb'&gt;export &lt;/span&gt;BRANCH

&lt;span class='nv'&gt;PKGSRCDIR&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/content/pkgsrc-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;
&lt;span class='nb'&gt;export &lt;/span&gt;PKGSRCDIR

&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; ! -f /opt/pkg/bin/bmake &lt;span class='o'&gt;]&lt;/span&gt;; &lt;span class='k'&gt;then&lt;/span&gt;
    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cd&lt;/span&gt; /; tar -xf /install/pkgsrc/bootstrap-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.tar&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='k'&gt;fi&lt;/span&gt;

&lt;span class='c'&gt;# Run this anyway in case there are updates to pkg_chk&lt;/span&gt;
env &lt;span class='nv'&gt;PKG_PATH&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;/install/pkgsrc/packages/&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;/All pkg_add -u pkg_chk

&lt;span class='c'&gt;# Dry run first&lt;/span&gt;
pkg_chk -aurbn

&lt;span class='nb'&gt;printf&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Do you wish to install? [y/N]: &amp;quot;&lt;/span&gt;
&lt;span class='nb'&gt;read &lt;/span&gt;ans
&lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;${ans}&amp;quot;&lt;/span&gt; in
&lt;span class='o'&gt;[&lt;/span&gt;Yy&lt;span class='o'&gt;])&lt;/span&gt;
    pkg_chk -aurb 2&amp;gt;&amp;amp;1 | tee -a /install/pkgsrc/logs/pkg_chk-&lt;span class='k'&gt;${&lt;/span&gt;&lt;span class='nv'&gt;BRANCH&lt;/span&gt;&lt;span class='k'&gt;}&lt;/span&gt;.log
    ;;
&lt;span class='k'&gt;esac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;These are pretty simple as all the hard work has all been done. &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/build-packages'&gt;&lt;code&gt;build-packages&lt;/code&gt;&lt;/a&gt; is ran inside the zone, then &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/update-packages'&gt;&lt;code&gt;update-packages&lt;/code&gt;&lt;/a&gt; on the main host. These scripts hardcode the name of the branch currently used, so you will need to update this when moving to newer releases.&lt;/p&gt;

&lt;h2 id='quick_recap'&gt;Quick recap&lt;/h2&gt;

&lt;p&gt;Ok, so here is the stuff I have for my setup and where I keep them:&lt;/p&gt;
&lt;div class='posttable'&gt;
 &lt;table&gt;
  &lt;thead&gt;
   &lt;tr&gt;&lt;th style='width: 40%'&gt;Path&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/content/pkgsrc-2009Q2&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Checked out pkgsrc tree, &quot;2009Q2&quot; branch&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/content/scripts/&lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/create-zone'&gt;create-zone&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Creates Solaris zone&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/content/scripts/&lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/delete-zone'&gt;delete-zone&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Uninstalls and deletes zone&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/content/scripts/&lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/build-packages'&gt;build-packages&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Bulk build packages inside the zone&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/content/scripts/&lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/update-packages'&gt;update-packages&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Updates installed packages&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/install/pkgsrc/misc/&lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/mk.conf'&gt;mk.conf&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Main pkgsrc configuration file&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/install/pkgsrc/misc/&lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/mk-include.conf'&gt;mk-include.conf&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Fragment file included in each zone's &lt;code&gt;mk.conf&lt;/code&gt;, sources the global &lt;code&gt;mk.conf&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/install/pkgsrc/misc/&lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/pkgchk.conf'&gt;pkgchk.conf&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;pkg_chk&lt;/code&gt; configuration file&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/install/zones/&lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/vm-generic.xml'&gt;vm-generic.xml&lt;/a&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Shared SMF configuration file, symlinked to from e.g. &quot;&lt;code&gt;vm0.xml&lt;/code&gt;&quot;&lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;And these are the paths where stuff will be created:&lt;/p&gt;
&lt;div class='posttable'&gt;
 &lt;table&gt;
  &lt;thead&gt;
   &lt;tr&gt;&lt;th&gt;Path&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/install/pkgsrc/distfiles&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Source tarballs of packages&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/install/pkgsrc/packages/2009Q2&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Resulting binary packages&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/tmp/pkgsrc&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Temporary build area for packages&lt;/td&gt;&lt;/tr&gt;
   &lt;tr&gt;&lt;td&gt;&lt;code&gt;/content/vwww/www.adsl.perkin.org.uk/pkgstat&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Bulk build results directory&lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
 &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;It&amp;#8217;s definitely harder than it should be to get this all setup, but the good news is that once it&amp;#8217;s done there&amp;#8217;s very little maintenance.&lt;/p&gt;

&lt;h2 id='kicking_it_all_off'&gt;Kicking it all off&lt;/h2&gt;

&lt;p&gt;Once everything is setup:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; /content/scripts/create-zone vm0
&lt;span class='gp'&gt;$&lt;/span&gt; ssh vm0 /content/scripts/build-packages
&lt;span class='gp'&gt;$&lt;/span&gt; /content/scripts/update-packages
&lt;span class='gp'&gt;$&lt;/span&gt; /content/scripts/delete-zone vm0
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This should do the lot. Once &lt;a href='http://www.perkin.org.uk/files/solaris-pkgsrc/build-packages'&gt;&lt;code&gt;build-packages&lt;/code&gt;&lt;/a&gt; has finished you should, if you configured your email address in build.conf, get an email with the bulk build results which looks similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href='http://mail-index.netbsd.org/pkgsrc-bulk/2009/08/23/msg006883.html'&gt;http://mail-index.netbsd.org/pkgsrc-bulk/2009/08/23/msg006883.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A fuller report is available if you configure a web server to serve the &lt;code&gt;pkgstat&lt;/code&gt; directory created by the bulk build, and this can help debug problems (again see the above URL for an example).&lt;/p&gt;

&lt;p&gt;You will need to add &lt;code&gt;/opt/pkg/sbin:/opt/pkg/bin&lt;/code&gt; to &lt;code&gt;$PATH&lt;/code&gt;. Configuration files are in &lt;code&gt;/etc/opt/pkg&lt;/code&gt;, and log files and metadata are kept in &lt;code&gt;/var/opt/pkg&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id='this_stuff_should_be_obsolete'&gt;This stuff should be obsolete&lt;/h2&gt;

&lt;p&gt;While this all works well for me, it&amp;#8217;s pretty lame for users who just want to install packages and have stuff work. I&amp;#8217;m working on providing regular updates of binary packages, including a SVR4 package of the bootstrap kit, so that in theory all a user needs to do is&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; pkgadd TNFpkgsrc.pkg
&lt;span class='gp'&gt;$&lt;/span&gt; pkg_add apache22
&lt;span class='gp'&gt;#&lt;/span&gt; Upgrade all installed packages to latest releases
&lt;span class='gp'&gt;$&lt;/span&gt; pkg_chk -aurb
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;m almost there, just needs some tidying up and regular builds. Please feel free to help out!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Jumpstart from OSX</title>
      <link>http://www.perkin.org.uk/posts/jumpstart-from-osx.html</link>
      <pubDate>Tue, 09 Dec 2008 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/jumpstart-from-osx.html</guid>
      <description>&lt;p&gt;I recently built a new file server on which I planned to install Solaris 10 10/08. I&amp;#8217;m not a fan of CD/DVD installs, so wanted to jumpstart via PXE, though I only had OSX handy.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s how I installed my new machine (gromit.adsl.perkin.org.uk/192.168.1.10) from my iMac (192.168.1.30) over the local network.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that since writing this piece I&amp;#8217;ve updated to Solaris 10 10/09, and have changed the examples to use that instead.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id='step_1_prepare_file_system'&gt;Step 1, Prepare File System&lt;/h2&gt;

&lt;p&gt;First off, create a dedicated file system which we can export our jumpstart configuration from. You can probably skip this and just use any existing file system but this way everything is self-contained and we avoid NFS exporting more than we need.&lt;/p&gt;

&lt;p&gt;We use HFSX to ensure that the file system is case sensitive, HFS+ can cause problems with &lt;code&gt;pkgadd(1M)&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; hdiutil create -size 1g -type SPARSE -fs HFSX -volname &lt;span class='s2'&gt;&amp;quot;install&amp;quot;&lt;/span&gt; install
&lt;span class='gp'&gt;$&lt;/span&gt; hdiutil attach install.sparseimage -mountpoint /install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Next up, download and mount &lt;code&gt;sol-10-u8-ga-x86-dvd.iso&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; open sol-10-u8-ga-x86-dvd.iso
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='step_2_nfs'&gt;Step 2, NFS&lt;/h2&gt;

&lt;p&gt;Share &lt;code&gt;/install&lt;/code&gt; and the DVD via NFS with the correct options. &lt;code&gt;-alldirs&lt;/code&gt; allows clients to mount from any point within that file system (which jumpstart requires), and &lt;code&gt;-maproot=root&lt;/code&gt; is also required by jumpstart. As this allows root-owned files to be created, make sure you understand the security risks.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /etc/exports
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;/install                  -alldirs -maproot=root
/Volumes/SOL_10_1009_X86  -alldirs -maproot=root
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo nfsd checkexports &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo nfsd &lt;span class='nb'&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='step_3_dhcp'&gt;Step 3, DHCP&lt;/h2&gt;

&lt;p&gt;For DHCP I happen to already use my Cisco router as a DHCP server on the local network, so added the following configuration:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;ip dhcp pool gromit.adsl.perkin.org.uk
   host 192.168.1.10 255.255.255.0
   hardware-address xxxx.xxxx.xxxx
   bootfile /boot/grub/pxegrub
   next-server 192.168.1.30
   client-name gromit
   domain-name adsl.perkin.org.uk
   dns-server xxx.xxx.xxx.xxx
   default-router 192.168.1.1
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;however, given this is a guide for setting everything up under OSX I also tried using ISC DHCP on OSX to prove it can be done that way too.&lt;/p&gt;

&lt;p&gt;I used &lt;a href='http://www.pkgsrc.org/'&gt;pkgsrc&lt;/a&gt; to install it (I&amp;#8217;ll add another blog some time showing how to set up pkgsrc)&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /usr/pkgsrc/net/isc-dhcpd
&lt;span class='gp'&gt;$&lt;/span&gt; sudo bmake package
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And here is my DHCP configuration file in full:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;option domain-name &amp;quot;adsl.perkin.org.uk&amp;quot;;
option domain-name-servers xxx.xxx.xxx.xxx;
ddns-update-style none;
authoritative;
log-facility local7;

subnet 192.168.1.0 netmask 255.255.255.0 {
    option routers 192.168.1.1;
}

group {
    filename &amp;quot;/boot/grub/pxegrub&amp;quot;;
    next-server 192.168.1.30;

    host gromit {
        hardware ethernet xx:xx:xx:xx:xx:xx;
        fixed-address 192.168.1.10;
        option host-name &amp;quot;gromit.adsl.perkin.org.uk&amp;quot;;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, start DHCP with:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo /usr/pkg/sbin/dhcpd
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Most parts of these configurations should be self-explanatory. The &lt;code&gt;/boot/grub/pxegrub&lt;/code&gt; entry is important for our next step, and I&amp;#8217;d recommend using that exact pathname for reasons explained later.&lt;/p&gt;

&lt;h2 id='step_4_tftp'&gt;Step 4, TFTP&lt;/h2&gt;

&lt;p&gt;Now, enable the TFTP server which comes with OSX. I added the &lt;code&gt;-s&lt;/code&gt; option so tftpd would chroot to the tftpboot directory, both for security reasons and also to ensure that paths specified as &lt;code&gt;/path/to/file&lt;/code&gt; would work correctly (relative to &lt;code&gt;/install/tftpboot&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;I also changed the location of the tftpboot directory so that everything was self-contained within the UFS image. In previous attempts I didn&amp;#8217;t do this and ran into problems with GRUB which I think are again caused by case-insensitive file systems.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo vi /System/Library/LaunchDaemons/tftp.plist
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='xml'&gt;[...]
    &lt;span class='nt'&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span class='nt'&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/usr/libexec/tftpd&lt;span class='nt'&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;string&amp;gt;&lt;/span&gt;-i&lt;span class='nt'&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;string&amp;gt;&lt;/span&gt;-s&lt;span class='nt'&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class='nt'&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/install/tftpboot&lt;span class='nt'&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class='nt'&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
[...]
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; mkdir /install/tftpboot
&lt;span class='gp'&gt;$&lt;/span&gt; sudo launchctl load -w /System/Library/LaunchDaemons/tftp.plist
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can then create a test file and check that it&amp;#8217;s working as you expect, using:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;testing&amp;quot;&lt;/span&gt; &amp;gt;/install/tftpboot/testfile
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;printf&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;verbose\ntrace\nget testfile\n&amp;quot;&lt;/span&gt; | tftp localhost
&lt;span class='gp'&gt;$&lt;/span&gt; rm /install/tftpboot/testfile
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='step_5_grub'&gt;Step 5, GRUB&lt;/h2&gt;

&lt;p&gt;Next up, configure PXE booting using GRUB. We need to copy the GRUB images and configuration from the Solaris install DVD then modify it for our environment:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; rsync -av /Volumes/SOL_10_1009_X86/boot/grub /install/tftpboot/boot/
&lt;span class='gp'&gt;$&lt;/span&gt; rsync -av /Volumes/SOL_10_1009_X86/boot/multiboot /install/tftpboot/sol10u8x/
&lt;span class='gp'&gt;$&lt;/span&gt; rsync -av /Volumes/SOL_10_1009_X86/boot/x86.miniroot /install/tftpboot/sol10u8x/
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As we are copying the boot files from the DVD, they come hardcoded with particular pathnames to e.g. the &lt;code&gt;menu.lst&lt;/code&gt; file. While it may be possible to pass extra parameters to pxegrub and load this from a different path, I simply recommend doing as I do and replicating the &lt;code&gt;/boot/grub/&lt;/code&gt; path structure so that everything Just Works.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;menu.lst&lt;/code&gt; file includes kernel arguments and allows you to choose which type of install to perform at startup. My file listed below has 3 choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unattended install using a graphical environment (if available). The &amp;#8220;install&amp;#8221; keyword after the kernel instructs it to perform an unattended install, so long as it can find the necessary settings from sysidcfg etc.&lt;/li&gt;

&lt;li&gt;As above, but force the use of the console and do not start a graphical environment (using the &amp;#8220;nowin&amp;#8221; keyword)&lt;/li&gt;

&lt;li&gt;A manual install, so you need to go through the steps of layout out disks, selecting packages, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; vi /install/tftpboot/boot/grub/menu.lst
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;default=0
timeout=60

title Solaris PXE Unattended Install
    kernel /sol10u8x/multiboot kernel/unix - install -B \
      install_media=192.168.1.30:/Volumes/SOL_10_1009_X86,\
      sysid_config=192.168.1.30:/install/jumpstart,\
      install_config=192.168.1.30:/install/jumpstart
    module /sol10u8x/x86.miniroot

title Solaris PXE Unattended Install (console)
    kernel /sol10u8x/multiboot kernel/unix - install nowin -B \
      install_media=192.168.1.30:/Volumes/SOL_10_1009_X86,\
      sysid_config=192.168.1.30:/install/jumpstart,\
      install_config=192.168.1.30:/install/jumpstart
    module /sol10u8x/x86.miniroot

title Solaris PXE Manual Install
    kernel /sol10u8x/multiboot kernel/unix -B \
      install_media=192.168.1.30:/Volumes/SOL_10_1009_X86
    module /sol10u8x/x86.miniroot
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Anyone used to doing jumpstart but with RARP/bootparams will notice the symmetry between &lt;code&gt;install_config&lt;/code&gt; etc in the GRUB configuration and similar options in &lt;code&gt;/etc/bootparams&lt;/code&gt;. Make sure that the full kernel arguments are all on one line, and that there are no spaces in between the &lt;code&gt;install_media=..,sysid_config=..&lt;/code&gt; options.&lt;/p&gt;

&lt;h2 id='step_6_jumpstart'&gt;Step 6, Jumpstart&lt;/h2&gt;

&lt;p&gt;Finally, set up your Jumpstart configuration. Here&amp;#8217;s what I personally use, you may want something different:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; mkdir /install/jumpstart
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /install/jumpstart
&lt;span class='gp'&gt;$&lt;/span&gt; vi sysidcfg
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;name_service=DNS
{
    domain_name=adsl.perkin.org.uk
    name_server=xxx.xxx.xxx.xxx
}
network_interface=PRIMARY
{
    default_route=192.168.1.1
    netmask=255.255.255.0
    protocol_ipv6=yes
}
nfs4_domain=dynamic
root_password=xxxxxxxx
terminal=xterm
timeserver=localhost
timezone=Europe/London
security_policy=NONE
service_profile=limited_net
system_locale=C
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ordinarily this file is processed using a &lt;code&gt;check&lt;/code&gt; script available in the &lt;code&gt;jumpstart_sample&lt;/code&gt; directory on the Solaris DVD, however this only works from a Solaris host. To create the &lt;code&gt;rules.ok&lt;/code&gt; file, we need to strip out any comments and put entries on one line, then create the checksum (although this isn&amp;#8217;t actually necessary).&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; vi rules &lt;span class='c'&gt;# emacs sucks :)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;hostname gromit.adsl.perkin.org.uk - profile -
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; cp rules rules.ok
&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;echo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;# version=2 checksum=$(cksum -o 2 rules | awk &amp;#39;{print $1}&amp;#39;)&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; rules.ok
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Machine profile. This gives me a full Solaris install (minus OEM stuff) on mirrored ZFS disks with additional dump/swap space (the defaults made dump a bit too small I found).&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; vi profile
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;install_type    initial_install
pool            store auto 4g 4g mirror c1t0d0s0 c1t1d0s0
bootenv         installbe bename sol10u8x
cluster         SUNWCall
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='step_7_make_a_cup_of_tea'&gt;Step 7, Make A Cup Of Tea&lt;/h2&gt;

&lt;p&gt;With everything set up you should be able to enable PXE booting in your BIOS and watch it automatically install. One small minor problem you may have if you don&amp;#8217;t have a BIOS which allows you to hit F12 or similar and choose PXE booting for one boot only is that it will infinitely cycle through installing, rebooting, installing, rebooting.. until you change your boot options.&lt;/p&gt;

&lt;p&gt;If this happens, I recommend making more cups of tea until you happen to return in time to change the BIOS settings. If you aren&amp;#8217;t able to do this for a while, you may need to add the extra steps 8, 9 and 10 titled &amp;#8220;Visit The Bathroom&amp;#8221;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Set up local caching DNS server on OSX 10.4</title>
      <link>http://www.perkin.org.uk/posts/set-up-local-caching-dns-server-on-osx-104.html</link>
      <pubDate>Mon, 31 Dec 2007 00:00:00 +0000</pubDate>
      <author>jonathan@perkin.org.uk (Jonathan Perkin)</author>
      <guid>http://www.perkin.org.uk/posts/set-up-local-caching-dns-server-on-osx-104.html</guid>
      <description>&lt;p&gt;OSX 10.4 ships with ISC &lt;code&gt;named&lt;/code&gt;, but is not configured correctly out of the box. Follow the instructions below to run a local caching name server.&lt;/p&gt;

&lt;p&gt;First, we need to generate an rndc key. The default &lt;code&gt;named.conf&lt;/code&gt; comes configured to use one, but if it does not exist will bail with an error. Simply run &lt;code&gt;rndc-confgen(1)&lt;/code&gt; to create one.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo rndc-confgen -a
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Next, download the latest &lt;code&gt;named.root&lt;/code&gt; file, as the supplied &lt;code&gt;named.ca&lt;/code&gt; is rather outdated (as you can see from the diff output).&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; &lt;span class='nb'&gt;cd&lt;/span&gt; /var/named
&lt;span class='gp'&gt;$&lt;/span&gt; sudo curl -O ftp://ftp.internic.net/domain/named.root
&lt;span class='gp'&gt;$&lt;/span&gt; diff -u named.ca named.root
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now edit &lt;code&gt;/etc/named.conf&lt;/code&gt;, we need to make three changes. Firstly, the rndc port is wrong in the default configuration, so make it:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;        inet 127.0.0.1 port 953 allow {any;}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Next, add a &lt;code&gt;listen-on&lt;/code&gt; directive in the options section to instruct named to only listen on certain interfaces, ensuring that we keep as secure as possible. I have added the internal 192.168/16 LAN to my configuration so that Parallels VMs and other machines can use the server, but if you do not need this then just keep the localhost entry:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;        directory &amp;quot;/var/named&amp;quot;;
        listen-on {
                127.0.0.1;
                192.168/16;
        };
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, change the root DNS server file from &lt;code&gt;named.ca&lt;/code&gt; to &lt;code&gt;named.root&lt;/code&gt; as downloaded above. You could simply overwrite the &lt;code&gt;named.ca&lt;/code&gt; file instead with &lt;code&gt;named.root&lt;/code&gt;, however I like to keep defaults around as much as possible - you never know if an update will blat your changes or not:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='text'&gt;zone &amp;quot;.&amp;quot; IN {
        type hint;
        file &amp;quot;named.root&amp;quot;;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;All done. All that&amp;#8217;s left to do is (re)start the service:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; sudo service org.isc.named stop
&lt;span class='gp'&gt;$&lt;/span&gt; sudo service org.isc.named start
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;then run a quick test to ensure it is working correctly:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='console'&gt;&lt;span class='gp'&gt;$&lt;/span&gt; dig www.perkin.org.uk @localhost
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you get a reply, configure your DNS server to be 127.0.0.1 and you&amp;#8217;re all set.&lt;/p&gt;</description>
    </item>
    

  </channel>
</rss>
