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

<channel>
	<title>Forward Lateral &#187; Technology</title>
	<atom:link href="http://forwardlateral.com/blog/category/technology/feed/" rel="self" type="application/rss+xml" />
	<link>http://forwardlateral.com/blog</link>
	<description>A nice place to hear myself talk</description>
	<lastBuildDate>Wed, 06 Apr 2011 00:38:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Metazip 0.8 released</title>
		<link>http://forwardlateral.com/blog/2009/09/09/metazip-0-8-released/</link>
		<comments>http://forwardlateral.com/blog/2009/09/09/metazip-0-8-released/#comments</comments>
		<pubDate>Thu, 10 Sep 2009 05:08:36 +0000</pubDate>
		<dc:creator>Michael Birk</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://forwardlateral.com/blog/?p=386</guid>
		<description><![CDATA[Metazip is an Apache 2.x module that allows you to serve dynamically-constructed, uncompressed zip files. Thus, your users can choose to download individual files or entire collections, but you don't have to reserve disk space for both.]]></description>
			<content:encoded><![CDATA[<h1>Metazip</h1>
<ul>
<li>Copyright 2009 <a href="http://forwardlateral.com/">Michael Birk</a></li>
<li>Web: <a href="http://forwardlateral.com/metazip">http://forwardlateral.com/metazip</a></li>
<li>Project: <a href="http://github.com/mbirk/metazip">http://github.com/mbirk/metazip</a></li>
<li>Email: <a href="mailto:mbirk@forwardlateral.com">mbirk@forwardlateral.com</a></li>
</ul>
<p>Metazip is an Apache 2.x module that allows you to serve dynamically-constructed, uncompressed zip files.  Thus, your users can choose to download individual files or entire collections, but you don&#8217;t have to reserve disk space for both.</p>
<p>For example, let&#8217;s say we have a directory with some .mp3 files. This directory also has a .zip file containing the very same .mp3 files. Note that it must be an <em>uncompressed</em> .zip file, so that it contains exact copies of the .mp3 files:</p>
<div><img class="alignnone" title="Directory with uncompressed .zip file and .mp3 files." src="http://forwardlateral.com/metazip/without_metazip.png" alt="" width="530" height="224" /></div>
<p>Now, by running the Metazip command-line tool, we can &#8220;compress&#8221; this .zip file by removing the duplicate copies of the .mp3 files. The resulting .zip.mz file has all of the original .zip file&#8217;s metadata (e.g. the header at the beginning of every .zip file), but the .mp3 data has been replaced with a simple filename:</p>
<div><img class="alignnone" title="Directory with .zip.mz file and .mp3 files.  (Not to scale.)" src="http://forwardlateral.com/metazip/with_metazip.png" alt="" width="506" height="223" /></div>
<p>We can reconstruct the original .zip file by combining the .zip.mz file with the .mp3 files. The mod_metazip Apache module does exactly that, and it does this without adding any significant load on the server! Internally, Apache uses a data structure called a &#8220;<a href="http://apr.apache.org/docs/apr-util/0.9/group__APR__Util__Bucket__Brigades.html">bucket brigade</a>,&#8221; which allows it to efficiently combine different pieces of data into a single logical stream.<br />
Features:</p>
<ul>
<li>Extremely efficient, by hooking into Apache&#8217;s filter system.</li>
<li>Works equally well for .zip, .tar, and .rar archive files.</li>
<li>Supports resumption of aborted downloads.</li>
<li>Lightweight, self-contained C implementation.</li>
<li>Free, open source license (Apache).</li>
</ul>
<p>Restrictions:</p>
<ul>
<li>Works for uncompressed archives only.</li>
<li>Requires command line utility to construct .zip.mz file.</li>
<li>Currently only supported on Linux with GNU bash, gcc, and make.</li>
</ul>
<h2>Building and Installing Metazip</h2>
<p>Building metazip should be as simple as typing &#8220;make all&#8221;.  This checks prerequisites, compiles all source files, links the executables, and builds  the mod_metazip.so shared library.</p>
<p>Optionally, you can test Metazip prior to installing it.  Just run &#8220;make test&#8221;.  This invokes Apache in debug mode, and you can point your browser to http://localhost:8000/ to test metazip interactively.</p>
<p>If all goes well, you can install Metazip using &#8220;make install&#8221;.  However, this may require root access, depending on where Apache is installed.  Type &#8220;make -n install&#8221; to see what commands are run during installation.</p>
<h2>Apache Configuration</h2>
<p>Metazip is easy to configure.  Just add a few lines to your httpd.conf:</p>
<pre># Load the metazip module.
LoadModule metazip_module modules/mod_metazip.so

# Associate .mz files with Metazip.
AddType application/x-metazip .mz

# Enable the filter for Metazip files.
FilterDeclare METAZIP
FilterProvider METAZIP METAZIP resp=Content-Type application/x-metazip
FilterChain METAZIP

# Set the "X-Metazip: enabled" header.
RequestHeader append X-Metazip enabled

# Set the relative directory for .mz files.
&lt;Directory /path/to&gt;
MetazipDirectory /path/to/dir
&lt;/Directory&gt;</pre>
<p>Note: When a user requests a .mz file, Metazip sets the Content-Disposition  header with the archive filename (without the .mz extension).  Therefore,  your users will always be prompted with the &#8220;correct&#8221; filename.</p>
<p>Optionally, you can use mod_rewrite to &#8220;hide&#8221; the .mz extension. If a user requests a non-existent archive (say, example.zip), then mod_rewrite can replace this with a request for the corresponding .mz file (example.zip.mz). This allows you to integrate Metazip without having to change existing links to archives.</p>
<p>To use mod_rewrite with metazip, just add the following to the .htaccess  file in your document root (or within a &lt;Directory&gt; section in httpd.conf):</p>
<pre># If the requested archive doesn't exist,
# try the corresponding .mz file.
&lt;IfModule mod_rewrite.c&gt;
RewriteEngine On
RewriteCond %{REQUEST_FILENAME}    !-f
RewriteCond %{REQUEST_FILENAME}.mz  -f
RewriteRule \.zip|\.tar|\.rar$ %{REQUEST_URI}.mz
&lt;/IfModule&gt;</pre>
<p>Note: You may need to dynamically load mod_rewrite, using the LoadModule directive in httpd.conf:</p>
<pre>LoadModule rewrite_module modules/mod_rewrite.so</pre>
<h2>Requirements</h2>
<p>Metazip depends on several GNU extensions, so GNU bash, gcc, and make are  required.  Of course, it is an Apache 2.x module, so the Apache development  environment is required.  On Red Hat systems, the required package is  &#8220;httpd-devel&#8221;.  On Debian systems, it is &#8220;apache2-dev&#8221;.<!-- PHP 5.x --></p>
]]></content:encoded>
			<wfw:commentRss>http://forwardlateral.com/blog/2009/09/09/metazip-0-8-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>metazip 0.1 Released</title>
		<link>http://forwardlateral.com/blog/2007/01/02/metazip-01-released/</link>
		<comments>http://forwardlateral.com/blog/2007/01/02/metazip-01-released/#comments</comments>
		<pubDate>Tue, 02 Jan 2007 08:16:15 +0000</pubDate>
		<dc:creator>Michael Birk</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[C]]></category>

		<guid isPermaLink="false">http://forwardlateral.com/blog/2007/01/02/metazip-01-released/</guid>
		<description><![CDATA[So I finally got around to releasing a project I&#8217;ve had sitting around for more than a year. It&#8217;s metazip (or mod_metazip): metazip is an Apache 2.0 module that allows you to serve dynamically-constructed, uncompressed zip files. Thus, your users can choose to download individual files or entire collections, but you don&#8217;t have to reserve [...]]]></description>
			<content:encoded><![CDATA[<p>So I finally got around to releasing a project I&#8217;ve had sitting around for more than a year.  It&#8217;s <a href="http://metazip.sourceforge.net/">metazip</a> (or mod_metazip):</p>
<blockquote><p>metazip is an Apache 2.0 module that allows you to serve dynamically-constructed, uncompressed zip files. Thus, your users can choose to download individual files or entire collections, but you don&#8217;t have to reserve disk space for both.
</p></blockquote>
<p>I originally wrote metazip to solve a problem at <a href="http://www.archive.org/">Archive.org</a>.  They have <a href="http://www.archive.org/details/audio">an amazing collection of freely-downloadable music</a>, most of it being complete live shows of <a href="http://www.archive.org/browse.php?collection=etree&#038;field=%2Fmetadata%2Fcreator">bands that allow free distribution</a>.  It&#8217;s really the logical, modern extension of the good ol&#8217; days of Grateful Dead tape-trading.  And, indeed, Archive.org has thousands of Dead shows free for the listening.  Check it out!</p>
<p>Anyway, Archive.org allows you to download an entire show as a single .zip file.  You can also select individual tracks.  They employ a Perl script that dynamically creates these zip files on the fly.  This seems logical, since otherwise they would consume double the disk space (and their archive is immense)!</p>
<p>Unfortunately, the script has a rather fatal flaw: it doesn&#8217;t support resumption of downloads, <a href="http://www.google.com/search?q=resumption+OR+resume+site%3Awww.archive.org%2Fiathreads">a topic of much consternation in their forums</a>.  (Also see <a href="http://www.archive.org/iathreads/post-view.php?id=30217">my post on the subject</a>, which includes a quirky workaround I concocted.)  This can be mighty frustrating if your Internet connection craps out 95% of the way through a 1GB download!  Most browsers and other HTTP clients support resumption, which would allow you to download that last 5% without starting over.</p>
<p>For more information about metazip, how it works, and how to set it up, see the <a href="http://metazip.sourceforge.net/">metazip web site</a>.  It&#8217;s an open-source project, so feel free to contribute to its development at <a href="https://sourceforge.net/projects/metazip/">the SourceForge project page</a>.<br />
<!-- PHP 5.x --></p>
<p><a class="a2a_button_digg" href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2007%2F01%2F02%2Fmetazip-01-released%2F&amp;linkname=metazip%200.1%20Released" title="Digg" rel="nofollow" target="_blank"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a><a class="a2a_button_facebook" href="http://www.addtoany.com/add_to/facebook?linkurl=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2007%2F01%2F02%2Fmetazip-01-released%2F&amp;linkname=metazip%200.1%20Released" title="Facebook" rel="nofollow" target="_blank"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/icons/facebook.png" width="16" height="16" alt="Facebook"/></a><a class="a2a_button_stumbleupon" href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2007%2F01%2F02%2Fmetazip-01-released%2F&amp;linkname=metazip%200.1%20Released" title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a><a class="a2a_button_twitter" href="http://www.addtoany.com/add_to/twitter?linkurl=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2007%2F01%2F02%2Fmetazip-01-released%2F&amp;linkname=metazip%200.1%20Released" title="Twitter" rel="nofollow" target="_blank"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/icons/twitter.png" width="16" height="16" alt="Twitter"/></a><a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2007%2F01%2F02%2Fmetazip-01-released%2F&amp;linkname=metazip%200.1%20Released" title="Reddit" rel="nofollow" target="_blank"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a><a class="a2a_button_yahoo_buzz" href="http://www.addtoany.com/add_to/yahoo_buzz?linkurl=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2007%2F01%2F02%2Fmetazip-01-released%2F&amp;linkname=metazip%200.1%20Released" title="Yahoo Buzz" rel="nofollow" target="_blank"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/icons/buzz.png" width="16" height="16" alt="Yahoo Buzz"/></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2007%2F01%2F02%2Fmetazip-01-released%2F&amp;title=metazip%200.1%20Released" id="wpa2a_2"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/share_save_256_24.png" width="256" height="24" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://forwardlateral.com/blog/2007/01/02/metazip-01-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Don&#8217;t go there: Keeping the Unix &#8216;find&#8217; command out of your CVS and Subversion directories.</title>
		<link>http://forwardlateral.com/blog/2006/02/27/dont-go-there/</link>
		<comments>http://forwardlateral.com/blog/2006/02/27/dont-go-there/#comments</comments>
		<pubDate>Tue, 28 Feb 2006 06:42:36 +0000</pubDate>
		<dc:creator>Michael Birk</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[bash]]></category>

		<guid isPermaLink="false">http://forwardlateral.com/blog/2006/02/27/dont-go-there/</guid>
		<description><![CDATA[You&#8217;ve avoided learning the ins-and-outs of the Unix find command because it doesn&#8217;t play nice within your Subversion and CVS working directories? Well then, I&#8217;ve got just the solution! Don&#8217;t want to read my ridiculous blathering? No problem! Just download the free, open source code that &#8220;fixes&#8221; find. This article assumes that you have a [...]]]></description>
			<content:encoded><![CDATA[<p>You&#8217;ve avoided learning the ins-and-outs of the Unix <em>find</em> command because it doesn&#8217;t play nice within your Subversion and CVS working directories? Well then, I&#8217;ve got just the solution!</p>
<blockquote><p>Don&#8217;t want to read my ridiculous blathering? No problem! Just <a title="dont-go-there.sh: Keeping the Unix 'find' command out of your CVS and Subversion directories." href="http://forwardlateral.com/dont-go-there.sh">download the free, open source code that &#8220;fixes&#8221; <em>find</em></a>.</p></blockquote>
<p><span id="more-11"></span></p>
<p>This article assumes that you have a basic understanding of Unix and the command-line shell. The software only works with <a href="http://www.gnu.org/software/bash/bash.html">GNU bash</a>.</p>
<p>The Unix <em>find</em> and <em>xargs</em> commands are quite useful for quickly processing files in an entire directory tree. One of the most common idioms is to combine them with <em>grep</em> in order to do a &#8220;recursive grep&#8221; that searches through all of the files in a directory. For example:</p>
<pre lang="bash"><strong>find /path/to/haystack/ -type f | xargs grep needle</strong></pre>
<p>However, this will fail if any of the path names have spaces or other special characters. To fix that problem, use null separators:</p>
<pre lang="bash"><strong>find /path/to/haystack/ -type f -print0 | xargs -0 grep needle</strong></pre>
<p>Usually, the &#8220;haystack&#8221; is simply the current directory. And often, we want to search files with a particular extension, such as <em>.sh</em> files. For example:</p>
<pre lang="bash"><strong>find . -name \*.sh -print0 | xargs -0 grep needle</strong></pre>
<p>Unfortunately, if you run these commands within a <em>working directory</em> &#8212; that is, a directory tree that is managed by a source control system such as CVS or Subversion &#8212; you may get more than you bargained for. That&#8217;s because these systems create special, &#8220;hidden&#8221; directories that you aren&#8217;t supposed to mess with. With Subversion, it is the &#8216;.svn&#8217; directory:</p>
<pre lang="bash"><strong>ls .svn/</strong>
README.txt empty-file format props tmp
dir-props entries prop-base text-base wcprops</pre>
<p>CVS uses a similar directory named, well, CVS.</p>
<p>When you consider that every subdirectory in your working directory tree has its own &#8216;.svn&#8217; (or CVS) directory, it&#8217;s easy to see how this can interfere with your recursive greps and whatnot. What to do?</p>
<p>One idea is to use the power of <em>find</em> to skip over those special directories. Unfortunately, <em>find</em> can be tricky to get right. It turns out that the proper syntax is:</p>
<pre lang="bash"><strong>find . ! ( -name .svn -prune )</strong></pre>
<p>That&#8217;s not too pretty, especially when you consider that ! and ( are special characters in both <em>bash</em> and <em>find</em>. So you&#8217;d better type:</p>
<pre lang="bash"><strong>find . \! \( -name .svn -prune \)</strong></pre>
<p>Clearly that&#8217;s an error-prone burden, particularly once you connect the dots:</p>
<pre lang="bash"><strong>find . \! \( -name .svn -prune \) -name \*.sh -print0 | xargs grep -0 needle</strong></pre>
<p>I&#8217;ve packaged this into a transparent wrapper that tweaks the command line before <em>find</em> sees it, inserting a filter like the one above. And although <em>find</em> has a non-standard syntax that, among other things, places constraints on the ordering of the options, the resulting logic is non-trivial but manageable.</p>
<p>To use this solution, <a title="dont-go-there.sh: Keeping the Unix 'find' command out of your CVS and Subversion directories." href="http://forwardlateral.com/dont-go-there.sh">download the script</a> and place it in your home directory (or anywhere else). Then modify your .bashrc or .bash_profile script to include it:</p>
<pre lang="bash"><strong>source ~/dont-go-there.sh</strong></pre>
<p>The next time you login, the find wrapper function will be in place. To test it, try the new <em>-debug</em> option:</p>
<pre lang="bash"><strong>find -debug . -type f
</strong>find . ! ( ( -name .svn -o -name CVS ) -prune ) -type f</pre>
<p>Note that, if need be, you can bypass the wrapper using the <em>command</em> builtin. In that case, <em>find</em> is invoked directly and the .svn and CVS directories are not treated specially:</p>
<pre lang="bash"><strong>command find . -name .svn</strong></pre>
<p><!-- PHP 5.x --></p>
<p><a class="a2a_button_digg" href="http://www.addtoany.com/add_to/digg?linkurl=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2006%2F02%2F27%2Fdont-go-there%2F&amp;linkname=Don%26%238217%3Bt%20go%20there%3A%20Keeping%20the%20Unix%20%26%238216%3Bfind%26%238217%3B%20command%20out%20of%20your%20CVS%20and%20Subversion%20directories." title="Digg" rel="nofollow" target="_blank"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/icons/digg.png" width="16" height="16" alt="Digg"/></a><a class="a2a_button_facebook" href="http://www.addtoany.com/add_to/facebook?linkurl=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2006%2F02%2F27%2Fdont-go-there%2F&amp;linkname=Don%26%238217%3Bt%20go%20there%3A%20Keeping%20the%20Unix%20%26%238216%3Bfind%26%238217%3B%20command%20out%20of%20your%20CVS%20and%20Subversion%20directories." title="Facebook" rel="nofollow" target="_blank"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/icons/facebook.png" width="16" height="16" alt="Facebook"/></a><a class="a2a_button_stumbleupon" href="http://www.addtoany.com/add_to/stumbleupon?linkurl=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2006%2F02%2F27%2Fdont-go-there%2F&amp;linkname=Don%26%238217%3Bt%20go%20there%3A%20Keeping%20the%20Unix%20%26%238216%3Bfind%26%238217%3B%20command%20out%20of%20your%20CVS%20and%20Subversion%20directories." title="StumbleUpon" rel="nofollow" target="_blank"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/icons/stumbleupon.png" width="16" height="16" alt="StumbleUpon"/></a><a class="a2a_button_twitter" href="http://www.addtoany.com/add_to/twitter?linkurl=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2006%2F02%2F27%2Fdont-go-there%2F&amp;linkname=Don%26%238217%3Bt%20go%20there%3A%20Keeping%20the%20Unix%20%26%238216%3Bfind%26%238217%3B%20command%20out%20of%20your%20CVS%20and%20Subversion%20directories." title="Twitter" rel="nofollow" target="_blank"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/icons/twitter.png" width="16" height="16" alt="Twitter"/></a><a class="a2a_button_reddit" href="http://www.addtoany.com/add_to/reddit?linkurl=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2006%2F02%2F27%2Fdont-go-there%2F&amp;linkname=Don%26%238217%3Bt%20go%20there%3A%20Keeping%20the%20Unix%20%26%238216%3Bfind%26%238217%3B%20command%20out%20of%20your%20CVS%20and%20Subversion%20directories." title="Reddit" rel="nofollow" target="_blank"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/icons/reddit.png" width="16" height="16" alt="Reddit"/></a><a class="a2a_button_yahoo_buzz" href="http://www.addtoany.com/add_to/yahoo_buzz?linkurl=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2006%2F02%2F27%2Fdont-go-there%2F&amp;linkname=Don%26%238217%3Bt%20go%20there%3A%20Keeping%20the%20Unix%20%26%238216%3Bfind%26%238217%3B%20command%20out%20of%20your%20CVS%20and%20Subversion%20directories." title="Yahoo Buzz" rel="nofollow" target="_blank"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/icons/buzz.png" width="16" height="16" alt="Yahoo Buzz"/></a><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fforwardlateral.com%2Fblog%2F2006%2F02%2F27%2Fdont-go-there%2F&amp;title=Don%26%238217%3Bt%20go%20there%3A%20Keeping%20the%20Unix%20%26%238216%3Bfind%26%238217%3B%20command%20out%20of%20your%20CVS%20and%20Subversion%20directories." id="wpa2a_4"><img src="http://forwardlateral.com/blog/wp-content/plugins/add-to-any/share_save_256_24.png" width="256" height="24" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://forwardlateral.com/blog/2006/02/27/dont-go-there/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

