<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule">
  <channel>
    <title>Posts on Blog of Julian Andres Klode</title>
    <link>https://blog.jak-linux.org/post/</link>
    <description>Recent content in Posts on Blog of Julian Andres Klode</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>Copyright © 2018-2020 Julian Andres Klode, articles licensed under &lt;a rel=&#34;license&#34; href=&#34;http://creativecommons.org/licenses/by-sa/4.0/&#34;&gt;CC BY-SA 4.0&lt;/a&gt;.&lt;br/&gt;
Comments are provided by &lt;a href=&#34;https://joinmastodon.org&#34;&gt;Mastodon&lt;/a&gt; and copyright of their authors.&lt;br/&gt;&lt;br/&gt;

This website does not store any personally identifiable information. As part of standard web server
access_log logging, it stores requests and the user agents and shortened IP addresses used to make
them. It does, however, load some avatars from mastodon.&lt;br/&gt;&lt;br/&gt;

Powered by &lt;a href=&#34;https://gohugo.io/tools/&#34;&gt;Hugo&lt;/a&gt;, and the &lt;a href=&#34;https://github.com/julian-klode/ernest/&#34;&gt;Ernest&lt;/a&gt; theme.
</copyright>
    <creativeCommons:license>http://www.creativecommons.org/licenses/by-sa/4.0/</creativeCommons:license>
    <lastBuildDate>Sat, 18 Oct 2025 21:37:17 +0200</lastBuildDate>
    
	<atom:link href="https://blog.jak-linux.org/post/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Sound Removals</title>
      <link>https://blog.jak-linux.org/2025/10/18/sound-removals/</link>
      <pubDate>Sat, 18 Oct 2025 21:37:17 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2025/10/18/sound-removals/</guid>
      <description>&lt;h2 id=&#34;problem-statement&#34;&gt;Problem statement&lt;/h2&gt;
&lt;p&gt;Currently if you have an automatically installed package A (= 1) where&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A (= 1) Depends B (= 1)&lt;/li&gt;
&lt;li&gt;A (= 2) Depends B (= 2)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and you upgrade B from 1 to 2; then  you can:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Remove A (= 1)&lt;/li&gt;
&lt;li&gt;Upgrade A to version 2&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If A was installed by a chain initiated by Recommends (say X Rec Y, Y Depends A), the solver sometimes preferred removing A (and anything depending on it until it got).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <h2 id="problem-statement">Problem statement</h2>
<p>Currently if you have an automatically installed package A (= 1) where</p>
<ul>
<li>A (= 1) Depends B (= 1)</li>
<li>A (= 2) Depends B (= 2)</li>
</ul>
<p>and you upgrade B from 1 to 2; then  you can:</p>
<ol>
<li>Remove A (= 1)</li>
<li>Upgrade A to version 2</li>
</ol>
<p>If A was installed by a chain initiated by Recommends (say X Rec Y, Y Depends A), the solver sometimes preferred removing A (and anything depending on it until it got).</p>
<p>I have a fix pending to introduce eager Recommends which fixes the practical case, but
this is still not <em>sound</em>.</p>
<p>In fact we can show that the solver produces the wrong result for small
minimal test cases, as well as the right result for some others without the
fix (hooray?).</p>
<p>Ensuring sound removals is more complex, and first of all it begs the question: When
is a removal sound? This, of course, is on us to define.</p>
<p>An easy case can be found in the <a href="https://www.debian.org/doc/debian-policy/ch-relationships.html#replacing-whole-packages-forcing-their-removal">Debian policy, 7.6.2 &ldquo;Replacing whole packages, forcing their removal&rdquo;</a>:</p>
<p>If <code>B (= 2)</code> declares a <code>Conflicts: A (= 1)</code> and <code>Replaces: A (= 1)</code>, then the removal
is valid. However this is incomplete as well, consider it declares <code>Conflicts: A (&lt; 1)</code>
and <code>Replaces: A (&lt; 1)</code>; the solution to remove A rather than upgrade it would still
be wrong.</p>
<p>This indicates that we should only allow removing <code>A</code> if the conflicts could not be solved
by upgrading it.</p>
<p>The other case to explore is package removals. If B is removed, A should be removed as well;
however it there is another package X that <code>Provides: B (= 1)</code> and it is marked for install,
A should not be removed. That said, the solver is not allowed to install X to satisfy the
depends <code>B (= 1)</code> - only to satisfy other dependencies [we do not want to get into endless
loops where we switch between alternatives to keep reverse dependencies installed].</p>
<h2 id="proposed-solution">Proposed solution</h2>
<p>To solve this, I propose the following definition:</p>
<p><strong>Definition (sound removal)</strong>: A removal of package <code>P</code> is sound if either:</p>
<ol>
<li>A version <code>v</code> is installed that <em>package-conflicts</em> with B.</li>
<li>A package <code>Q</code> is removed and the installable versions of P <em>package-depends</em> on Q.</li>
</ol>
<p>where the other definitions are:</p>
<p><strong>Definition (installable version)</strong>: A version <code>v</code> is installable if either it is installed,
or it is newer than an installed version of the same package (you may wish to change this to
accomodate downgrades, or require strict pinning, but here be dragons).</p>
<p><strong>Definition (package-depends):</strong> A version <code>v</code> <em>package-depends</em> on a package B if either:</p>
<ol>
<li>there exists a dependency in <code>v</code> that can be solved by any version of <code>B</code>, or</li>
<li>there exists a package <code>C</code> where <code>v package-depends C</code> and <code>any (c in C) package-depends B</code> (transitivity)</li>
</ol>
<p><strong>Definition (package-conflicts):</strong> A version <code>v</code> <em>package-conflicts</em> with an installed package <code>B</code> if either:</p>
<ol>
<li>it declares a conflicts against an installable version of B; or</li>
<li>there exists a package <code>C</code> where <code>v package-conflicts C</code>,
and <code>b package-depends C</code> for installable versions b.</li>
</ol>
<h2 id="translating-this-into-a-modified-sat-solver">Translating this into a (modified) SAT solver</h2>
<p>One approach may be to implement the logic in the conflict analysis that drives backtracking, i.e.
we assume a package <code>A</code> and when we reach <code>not A</code>, we analyse if the implication graph for <code>not A</code>
constitutes a sound removal, and then replace the assumption <code>A</code> with the assumption
<code>A or &quot;learned reason</code>.</p>
<p>However, while this seems a plausible mechanism for a DPLL solver, for a modern CDCL solver,  it&rsquo;s
not immediately evident how to analyse whether <code>not A</code> is sound if the reason for it is a learned
clause, rather than a problem clause.</p>
<p>Instead we propose a static encoding of the rules into a slightly modified SAT solver:</p>
<p>Given c1, &hellip;, cn that transitive-conflicts A and D1, &hellip;, Dn that A package-depends on,
introduce the rule:</p>
<p><code>A unless c1 or c2 or  ... cn ... or not D1 or not D2 ... or not Dn</code></p>
<p>Rules of the form <code>A... unless B...</code> - where <code>A...</code> and <code>B...</code> are CNF - are
intuitively the same as <code>A... or B...</code>, however the semantic here is different:
We are not allowed to select <code>B...</code> to satisfy this clause.</p>
<p>This requires a SAT solver that tracks a reason for each literal being assigned,
such as solver3, rather than a SAT solver like MiniSAT that only tracks reasons across
propagation (solver3 may track <code>A depends B or C</code> as the reason for <code>B</code> without evaluating
<code>C</code>, whereas MiniSAT would only track it as the reason given <code>not C</code>).</p>
<h2 id="is-it-actually-sound">Is it actually sound?</h2>
<p>The proposed definition of a sound removal may still proof unsound as I either missed
something in the conclusion of the proposed definition that violates my goal I set out
to achieve, or I missed some of the goals.</p>
<p>I challenge you to find cases that cause removals that look wrong :D</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Dependency Tries</title>
      <link>https://blog.jak-linux.org/2025/09/27/dependency-tries/</link>
      <pubDate>Sat, 27 Sep 2025 16:32:19 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2025/09/27/dependency-tries/</guid>
      <description>&lt;p&gt;As I was shopping groceries I had a shocking realization: The active dependencies
of packages in a solver actually form a trie (a dependency &lt;code&gt;A|B&lt;/code&gt; - &amp;ldquo;A or B&amp;rdquo; - of
a package &lt;code&gt;X&lt;/code&gt; is considered active if we marked &lt;code&gt;X&lt;/code&gt; for install).&lt;/p&gt;
&lt;p&gt;Consider the dependencies &lt;code&gt;A|B|C&lt;/code&gt;, &lt;code&gt;A|B&lt;/code&gt;, &lt;code&gt;B|X&lt;/code&gt;.
In most package managers these just express alternatives, that is, the &amp;ldquo;or&amp;rdquo; relationship,
but in Debian packages, it also expresses a preference relationship between its operands,
so in &lt;code&gt;A|B|C&lt;/code&gt;, &lt;code&gt;A&lt;/code&gt; is preferred over &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; over &lt;code&gt;C&lt;/code&gt; (and &lt;code&gt;A&lt;/code&gt; transitively over &lt;code&gt;C&lt;/code&gt;).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>As I was shopping groceries I had a shocking realization: The active dependencies
of packages in a solver actually form a trie (a dependency <code>A|B</code> - &ldquo;A or B&rdquo; - of
a package <code>X</code> is considered active if we marked <code>X</code> for install).</p>
<p>Consider the dependencies <code>A|B|C</code>, <code>A|B</code>, <code>B|X</code>.
In most package managers these just express alternatives, that is, the &ldquo;or&rdquo; relationship,
but in Debian packages, it also expresses a preference relationship between its operands,
so in <code>A|B|C</code>, <code>A</code> is preferred over <code>B</code> and <code>B</code> over <code>C</code> (and <code>A</code> transitively over <code>C</code>).</p>
<p>This means that we can convert the three dependencies into a trie as follows:</p>
<p><img src="trie1.svg" alt="Dependency trie of the three dependencies"></p>
<p>Solving the dependency here becomes a matter of trying to install the package
referenced by the first edge of the root, and seeing if that sticks. In this
case, that would be &lsquo;a&rsquo;. Let&rsquo;s assume that &lsquo;a&rsquo; failed to install, the next
step is to remove the empty node of <code>a</code>, and merging its children into the
root.</p>
<p><img src="trie2.svg" alt="Reduced dependency trie with &ldquo;not A&rdquo; containing b, b|c, b|x"></p>
<p>For ease of visualisation, we remove &ldquo;a&rdquo; from the dependency nodes as well,
leading us to a trie of the dependencies &ldquo;b&rdquo;, &ldquo;b|c&rdquo;, and &ldquo;b|x&rdquo;.</p>
<p>Presenting the Debian dependency problem, or the positive part of it as a
trie allows us for a great visualization of the problem but it may not proof
to be an effective implementation choice.</p>
<p>In the real world we may actually store this as a priority queue that we
can delete from. Since we don&rsquo;t actually want to delete from the queue
for real, our queue items are pairs of a pointer to dependency and an
activitity level, say <code>A|B@1</code>.
Whenever a variable is assigned false, we look at its reverse dependencies
and bump their activity, and reinsert them (the priority of the item being
determined by the leftmost solution still possible, it has now changed).
When we iterate the queue, we remove items with a lower activity level:</p>
<ol>
<li>Our queue is <code>A|B@1</code>, <code>A|B|C@1</code>, <code>B|X@1</code></li>
<li>Rejecting A bump the activity for its reverse dependencies and reinset them:
Our queue is <code>A|B@1</code>, <code>A|B|C@1</code>, <code>(A|)B@2</code>, <code>(A|)B|C@2</code>, <code>B|X@1</code></li>
<li>We visit <code>A|B@1</code> but see the activity of the underlying dependency is now 2 and remove it
Our queue is <code>A|B|C@1</code>, <code>(A|)B@2</code>, <code>(A|)B|C@2</code>, <code>B|X@1</code></li>
<li>We visit <code>A|B|C@1</code> but see the activity of the underlying dependency is now 2 and remove it
Our queue is <code>(A|)B@2</code>, <code>(A|)B|C@2</code>, <code>B|X@1</code></li>
<li>We visit <code>A|B@2</code>, see the activity matches and find B is the solution.</li>
</ol>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>A SomewhatMaxSAT Solver</title>
      <link>https://blog.jak-linux.org/2025/05/24/somewhatmax-sat-solver/</link>
      <pubDate>Sat, 24 May 2025 12:15:50 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2025/05/24/somewhatmax-sat-solver/</guid>
      <description>&lt;p&gt;&lt;strong&gt;As you may recall&lt;/strong&gt; from previous posts and elsewhere I have been busy writing a new solver for APT.
Today I want to share some of the latest changes in how to approach solving.&lt;/p&gt;
&lt;p&gt;The idea for the solver was that manually installed packages are always protected from removals &amp;ndash;
in terms of SAT solving, they are facts. Automatically installed packages become optional unit
clauses. Optional clauses are solved after manual ones, they don&amp;rsquo;t partake in normal unit propagation.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p><strong>As you may recall</strong> from previous posts and elsewhere I have been busy writing a new solver for APT.
Today I want to share some of the latest changes in how to approach solving.</p>
<p>The idea for the solver was that manually installed packages are always protected from removals &ndash;
in terms of SAT solving, they are facts. Automatically installed packages become optional unit
clauses. Optional clauses are solved after manual ones, they don&rsquo;t partake in normal unit propagation.</p>
<p>This worked fine, say you had</p>
<pre tabindex="0"><code>A                                   # install request for A
B                                   # manually installed, keep it
A depends on: conflicts-B | C
</code></pre><p>Installing <code>A</code> on a system with <code>B</code> installed installed <code>C</code>, as it was not allowed to
install the <code>conflicts-B</code> package since <code>B</code> is installed.</p>
<p><strong>However,</strong> I also introduced a mode to allow removing manually installed packages, and that&rsquo;s
where it broke down, now instead of <code>B</code> being a fact, our clauses looked like:</p>
<pre tabindex="0"><code>A                               # install request for A
A depends on: conflicts-B | C
Optional: B                     # try to keep B installed
</code></pre><p>As a result, we installed <code>conflicts-B</code> and removed <code>B</code>; the steps the solver takes are:</p>
<ol>
<li><code>A</code> is a fact, mark it</li>
<li><code>A depends on: conflicts-B | C</code> is the strongest clause, try to install <code>conflicts-B</code></li>
<li>We unit propagate that <code>conflicts-B</code> conflicts with <code>B</code>, so we mark <code>not B</code></li>
<li><code>Optional: B</code> is reached, but not satisfiable, ignore it because it&rsquo;s optional.</li>
</ol>
<p>This isn&rsquo;t correct: Just because we allow removing manually installed packages doesn&rsquo;t mean that we should remove manually installed packages if we don&rsquo;t need to.</p>
<p><strong>Fixing</strong> this turns out to be surprisingly easy. In addition to adding our optional (soft) clauses, let&rsquo;s first assume all of them!</p>
<p>But to explain how this works, we first need to explain some terminology:</p>
<ol>
<li>The solver operates on a stack of decisions</li>
<li>&ldquo;enqueue&rdquo; means a fact is being added at the current decision level, and enqueued for propagation</li>
<li>&ldquo;assume&rdquo; bumps the decision level, and then enqueues the assumed variable</li>
<li>&ldquo;propagate&rdquo; looks at all the facts and sees if any clause becomes unit, and then enqueues it</li>
<li>&ldquo;unit&rdquo; is when a clause has a single literal left to assign</li>
</ol>
<p>To illustrate this in pseudo Python code:</p>
<ol>
<li>
<p>We introduce all our facts, and if they conflict, we are unsat:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python3" data-lang="python3"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> fact <span style="color:#f92672">in</span> facts:
</span></span><span style="display:flex;"><span>    enqueue(fact)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> propagate():
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">False</span>
</span></span></code></pre></div></li>
<li>
<p>For each optional literal, we register a soft clause and assume it. If the assumption fails,
we ignore it. If it succeeds, but propagation fails, we undo the assumption.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python3" data-lang="python3"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> optionalLiteral <span style="color:#f92672">in</span> optionalLiterals:
</span></span><span style="display:flex;"><span>    registerClause(SoftClause([optionalLiteral]))
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> assume(optionalLiteral) <span style="color:#f92672">and</span> <span style="color:#f92672">not</span> propagate():
</span></span><span style="display:flex;"><span>        undo()
</span></span></code></pre></div></li>
<li>
<p>Finally we enter the main solver loop:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python3" data-lang="python3"><span style="display:flex;"><span><span style="color:#66d9ef">while</span> <span style="color:#66d9ef">True</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> propagate():
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> backtrack():
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">elif</span> <span style="color:#f92672">&lt;</span>all clauses are satisfied<span style="color:#f92672">&gt;</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">elif</span> it <span style="color:#f92672">:=</span> find(<span style="color:#e6db74">&#34;best unassigned literal satisfying a hard clause&#34;</span>):
</span></span><span style="display:flex;"><span>        assume(it)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">elif</span> it <span style="color:#f92672">:=</span> find(<span style="color:#e6db74">&#34;best unassigned literal satisfying a soft clause&#34;</span>):
</span></span><span style="display:flex;"><span>        assume(it)
</span></span></code></pre></div></li>
</ol>
<p>The key point to note is that the main loop will undo the assumptions in order; so
if you assume <code>A,B,C</code> and <code>B</code> is not possible, we will have also undone <code>C</code>. But since
<code>C</code> is also enqueued as a soft clause, we will then later find it again:</p>
<ol>
<li>Assume <code>A</code>: <code>State=[Assume(A)]</code>, <code>Clauses=[SoftClause([A])]</code></li>
<li>Assume <code>B</code>: <code>State=[Assume(A),Assume(B)]</code>, <code>Clauses=[SoftClause([A]),SoftClause([B])]</code></li>
<li>Assume <code>C</code>: <code>State=[Assume(A),Assume(B),Assume(C)]</code>, <code>Clauses=[SoftClause([A]),SoftClause([B]),SoftClause([C])]</code></li>
<li>Solve finds a conflict, backtracks, and sets <code>not C</code>: <code>State=[Assume(A),Assume(B),not(C)]</code></li>
<li>Solve finds a conflict, backtracks, and sets <code>not B</code>: <code>State=[Assume(A),not(B)]</code> &ndash; C is no longer assumed either</li>
<li>Solve, assume <code>C</code> as it satisfies <code>SoftClause([C])</code> as next best literal: <code>State=[Assume(A),not(B),Assume(C)]</code></li>
<li>All clauses are satisfied, solution is <code>A</code>, <code>not B</code>, and <code>C</code>.</li>
</ol>
<p><strong>This is not (correct) MaxSAT</strong>, because we actually do not guarantee that we satisfy as many soft clauses as possible. Consider you have the following clauses:</p>
<pre><code>Optional: A
Optional: B
Optional: C
B Conflicts with A
C Conflicts with A
</code></pre>
<p>There are two possible results here:</p>
<ol>
<li><code>{A}</code>   &ndash; If we assume <code>A</code> first, we are unable to satisfy <code>B</code> or <code>C</code>.</li>
<li><code>{B,C}</code> &ndash; If we assume either <code>B</code> or <code>C</code> first, <code>A</code> is unsat.</li>
</ol>
<p>The question to ponder though is whether we actually need a global maximum or whether a local maximum is satisfactory in practice for a dependency solver
If you look at it, a naive MaxSAT solver needs to run the SAT solver <code>2**n</code> times for <code>n</code> soft clauses, whereas our heuristic only needs <code>n</code> runs.</p>
<p>For dependency solving, it seems we do not seem have a strong need for a global maximum:
There are various other preferences between our literals, say priorities;
and empirically, from evaluating hundreds of regressions <em>without</em> the initial assumptions,
I can say that the assumptions do fix those cases and the result is correct.</p>
<p><strong>Further improvements</strong> exist, though, and we can look into them if they are needed, such as:</p>
<ul>
<li>
<p>Use a <em>better heuristic</em>:</p>
<p>If we assume 1 clause and solve, and we cause 2 or more clauses to become unsatisfiable,
then that clause is a local minimum and can be skipped.
This is a more common heuristical MaxSAT solver.
This gives us a <em>better</em> local maximum, but not a global one.</p>
<p>This is more or less what the <a href="https://labix.org/smart">Smart package manager</a> did,
except that in Smart, all packages were optional, and the entire solution was scored.
It calculated a basic solution without optimization and then toggled each variable and saw if the score improved.</p>
</li>
<li>
<p>Implement <em>an actual search for a global maximum</em>:</p>
<p>This involves reading the literature.
There are various versions of this, for example:</p>
<ol>
<li>
<p>Find unsatisfiable cores and use those to guide relaxation of clauses.</p>
</li>
<li>
<p>A bounds-based search, where we translate sum(satisifed clauses) &gt; k into SAT, and then search in one of the following ways:</p>
<ol>
<li>from 0 upward</li>
<li>from n downward</li>
<li>perform a binary search on [0, k] satisfied clauses.</li>
</ol>
<p><em>Actually</em> we do not even need to calculate sum constraints into CNF, because we can just add a specialized new type of constraint to our code.</p>
</li>
</ol>
</li>
</ul>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Observations in Debian dependency solving</title>
      <link>https://blog.jak-linux.org/2024/05/24/observations-in-debsat/</link>
      <pubDate>Fri, 24 May 2024 10:57:00 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2024/05/24/observations-in-debsat/</guid>
      <description>&lt;p&gt;In my previous blog, I explored &lt;a href=&#34;https://blog.jak-linux.org/2024/05/14/solver3/&#34;&gt;The New APT 3.0 solver&lt;/a&gt;.
Since then I have been at work in the test suite making tests pass and fixing some bugs.&lt;/p&gt;
&lt;p&gt;You see for all intents and purposes, the new solver is a very stupid naive DPLL SAT solver (it just
so happens we don&amp;rsquo;t actually have any pure literals in there). We can control it in a bunch of ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We can mark packages as &amp;ldquo;install&amp;rdquo; or &amp;ldquo;reject&amp;rdquo;&lt;/li&gt;
&lt;li&gt;We can order actions/clauses. When backtracking the action that came later will be the first we
try to backtrack on&lt;/li&gt;
&lt;li&gt;We can order the choices of a dependency - we try them left to right.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is about all that we really want to do, we can&amp;rsquo;t go if we reach a conflict, say &amp;ldquo;oh but this
conflict was introduced by that upgrade, and it seems more important, so let&amp;rsquo;s not backtrack on
the upgrade request but on this dependency instead.&amp;rdquo;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>In my previous blog, I explored <a href="https://blog.jak-linux.org/2024/05/14/solver3/">The New APT 3.0 solver</a>.
Since then I have been at work in the test suite making tests pass and fixing some bugs.</p>
<p>You see for all intents and purposes, the new solver is a very stupid naive DPLL SAT solver (it just
so happens we don&rsquo;t actually have any pure literals in there). We can control it in a bunch of ways:</p>
<ol>
<li>We can mark packages as &ldquo;install&rdquo; or &ldquo;reject&rdquo;</li>
<li>We can order actions/clauses. When backtracking the action that came later will be the first we
try to backtrack on</li>
<li>We can order the choices of a dependency - we try them left to right.</li>
</ol>
<p>This is about all that we really want to do, we can&rsquo;t go if we reach a conflict, say &ldquo;oh but this
conflict was introduced by that upgrade, and it seems more important, so let&rsquo;s not backtrack on
the upgrade request but on this dependency instead.&rdquo;.</p>
<p>This forces us to think about lowering the dependency problem into this form, such that not only
do we get formally correct solutions, but also semantically correct ones. This is nice because
we can apply a systematic way to approach the issue rather than introducing ad-hoc rules in the
old solver which had a &ldquo;which of these packages should I flip the opposite way to break the conflict&rdquo;
kind of thinking.</p>
<p>Now our test suite has a whole bunch of these semantics encoded in it, and I&rsquo;m going to share some
problems and ideas for how to solve them. I can&rsquo;t wait to fix these and the error reporting and
then turn it on in Ubuntu and later Debian (the defaults change is a post-trixie change, let&rsquo;s
be honest).</p>
<h2 id="apt-upgrade-is-hard"><code>apt upgrade</code> is hard</h2>
<p>The <code>apt upgrade</code> commands implements a safe version of dist-upgrade that essentially calculates the
dist-upgrade, and then undoes anything that would cause a package to be removed, but it (unlike its
<code>apt-get</code> counterpart) allows the solver to install new packages.</p>
<p>Now, consider the following package is installed:</p>
<pre><code>X Depends: A (= 1) | B
</code></pre>
<p>An upgrade from <code>A=1</code> to <code>A=2</code> is available. What should happen?</p>
<p>The classic solver would choose to remove <code>X</code> in a dist-upgrade, and then upgrade <code>A</code>, so it&rsquo;s answer
is quite clear: Keep back the upgrade of <code>A</code>.</p>
<p>The new solver however sees two possible solutions:</p>
<ol>
<li>Install <code>B</code> to satisfy <code>X Depends A (= 1) | B</code>.</li>
<li>Keep back the upgrade of <code>A</code></li>
</ol>
<p>Which one does it pick? This depends on the order in which it sees the upgrade action for A and the
dependency, as it will backjump chronologically. So</p>
<ol>
<li>
<p>If it gets to the dependency first, it marks <code>A=1</code> for install to satisfy <code>A (= 1)</code>. Then it gets
to the upgrade request, which is just <code>A Depends A (= 2) | A (= 1)</code> and sees it is satisfied
already and is content.</p>
</li>
<li>
<p>If it gets to the upgrade request first, it marks <code>A=2</code> for install to satisfy <code>A (= 2)</code>. Then
later it gets to <code>X Depends: A (= 1) | B</code>, sees that <code>A (= 1)</code> is not satisfiable, and picks <code>B</code>.</p>
</li>
</ol>
<p>We have two ways to approach this issue:</p>
<ol>
<li>We always order upgrade requests last, so they will be kept back in case of conflicting dependencies</li>
<li>We require that, for <code>apt upgrade</code> a currently satisfied dependency must be satisfied by currently installed
packages, hence eliminating <code>B</code> as a choice.</li>
</ol>
<h2 id="recommends-are-hard-too">Recommends are hard too</h2>
<p>See if you have a <code>X Recommends: A (= 1)</code> and a new version of <code>A</code>, <code>A (= 2)</code>, the solver currently
will silently break the <code>Recommends</code> in some cases.</p>
<p>But let&rsquo;s explore what the behavior of a <code>X Recommends: A (= 1)</code> in combination with an available upgrade
of <code>A (= 2)</code> should be. We could say the rule should be:</p>
<ul>
<li>An <code>upgrade</code> should keep back <code>A</code> instead of breaking the <code>Recommends</code></li>
<li>A <code>dist-upgrade</code> should either keep back <code>A</code> or remove <code>X</code> (if it is obsolete)</li>
</ul>
<p>This essentially leaves us the same choices as for the previous problem, but with an interesting twist.
We can change the ordering (and we already did), but we could also introduce a new rule, &ldquo;promotions&rdquo;:</p>
<blockquote>
<p>A Recommends in an installed package, or an upgrade to that installed package, where the Recommends
existed in the installed version, that is currently satisfied, must continue to be satisfied, that is,
it effectively is promoted to a Depends.</p>
</blockquote>
<p>This neatly solves the problem for us. We will never break Recommends that are satisfied.</p>
<p>Likewise, we already have a Recommends demotion rule:</p>
<blockquote>
<p>A Recommends in an installed package, or an upgrade to that installed package, where the Recommends
existed in the installed version, that is currently unsatisfied, will not be further evaluated (it
is treated like a Suggests is in the default configuration).</p>
</blockquote>
<p>Whether we should be allowed to break Suggests with our decisions or not (the old autoremover did not,
for instance) is a different decision. Should we promote currently satisified Suggests to Depends as well?
Should we follow currently satisified Suggests so the solver sees them and doesn&rsquo;t autoremove them,
but treat them as optional?</p>
<h2 id="tightening-of-versioned-dependencies">tightening of versioned dependencies</h2>
<p>Another case of versioned dependencies with alternatives that has complex behavior is something like</p>
<pre><code>X Depends: A (&gt;= 2) | B
X Recommends: A (&gt;= 2) | B
</code></pre>
<p>In both cases, installing <code>X</code> should upgrade an <code>A &lt; 2</code> in favour of installing <code>B</code>. But a naive
SAT solver might not. If your request to keep A installed is encoded as <code>A (= 1) | A (= 2)</code>, then
it first picks <code>A (= 1)</code>. When it sees the Depends/Recommends it will switch to <code>B</code>.</p>
<p>We can solve this again as in the previous example by ordering the &ldquo;keep A installed&rdquo; requests after
any dependencies. Notably, we will enqueue the common dependencies of all A versions first before
selecting a version of A, so something may select a version for us.</p>
<h2 id="version-narrowing-instead-of-version-choosing">version narrowing instead of version choosing</h2>
<p>A different approach to dealing with the issue of version selection is to not select a version
until the very last moment. So instead of selecting a version to satisfy <code>A (&gt;= 2)</code> we instead
translate</p>
<pre><code>Depends: A (&gt;= 2)
</code></pre>
<p>into two rules:</p>
<ol>
<li>
<p>The package selection rule:</p>
<pre><code> Depends: A
</code></pre>
<p>This ensures that any version of <code>A</code> is installed (i.e. it adds a version choice clause, <code>A (= 1) | A (= 2)</code>
in an example with two versions for <code>A</code>.</p>
</li>
<li>
<p>The version narrowing rule:</p>
<pre><code> Conflicts: A (&lt;&lt; 2)
</code></pre>
<p>This outright would reject a choice of <code>A (= 1)</code>.</p>
</li>
</ol>
<p>So now we have 3 kinds of clauses:</p>
<ol>
<li>package selection</li>
<li>version narrowing</li>
<li>version selection</li>
</ol>
<p>If we process them in that order, we should surely be able to find the solution that best matches
the semantics of our Debian dependency model, i.e. selecting earlier choices in a dependency before
later choices in the face of version restrictions.</p>
<p>This still leaves one issue: What if our maintainer did not use <code>Depends: A (&gt;= 2) | B</code> but
e.g. <code>Depends: A (= 3) | B | A (= 2)</code>. He&rsquo;d expect us to fall back to B if <code>A (= 3)</code> is not
installable, and not to B. But we&rsquo;d like to enqueue <code>A</code> and reject all choices other than <code>3</code>
and <code>2</code>. I think it&rsquo;s fair to say: &ldquo;Don&rsquo;t do that, then&rdquo; here.</p>
<h2 id="implementing-strict-pinning-correctly">Implementing strict pinning correctly</h2>
<p>APT knows a single candidate version per package, this makes the solver relatively deterministic:
It will only ever pick the candidate, or an installed version. This also happens to significantly
reduce the search space which is good - less backtracking. An uptodate system will only ever have
one version per package that can be installed, so we never actually have to choose versions.</p>
<p>But of course, APT allows you to specify a non-candidate version of a package to install, for example:</p>
<pre><code>apt install foo/oracular-proposed
</code></pre>
<p>The way this works is that the core component of the previous solver, which is the <code>pkgDepCache</code>
maintains what essentially amounts to an overlay of the policy that you could see with
<code>apt-cache policy</code>.</p>
<p>The solver currently however validates allowed version choices against the policy directly,
and hence finds these versions are not allowed and craps out. This is an interesting problem
because the solver should not be dependent on the <code>pkgDepCache</code> as the <code>pkgDepCache</code> initialization
(<code>Building dependency tree...</code>) accounts for about half of the runtime of APT (until the Y/n prompt)
and I&rsquo;d really like to get rid of it.</p>
<p>But currently the frontend does go via the <code>pkgDepCache</code>. It marks the packages in there, building
up what you could call a transaction, and then we translate it to the new solver, and once it is
done, it translates the result back into the <code>pkgDepCache</code>.</p>
<p>The current implementation of &ldquo;allowed version&rdquo; is implemented by reducing the search space, i.e.
every dependency, we outright ignore any non-allowed versions. So if you have a version 3 of <code>A</code>
that is ignored a <code>Depends: A</code> would be translated into <code>A (= 2) | A (= 1)</code>.</p>
<p>However this has two disadvantages. (1) It means if we show you why <code>A</code> could not be installed,
you don&rsquo;t even see <code>A (= 3)</code> in the list of choices and (2) you would need to keep the <code>pkgDepCache</code>
around for the temporary overrides.</p>
<p>So instead of actually enforcing the allowed version rule by filtering, a more reasonable
model is that we apply the allowed version rule by just marking every other version as not
allowed when discovering the package in the <code>from depcache</code> translation layer. This doesn&rsquo;t
really increase the search space either but it solves both our problem of making overrides
work and giving you a reasonable error message that lists all versions of <code>A</code>.</p>
<h2 id="pulling-up-common-dependencies-to-minimize-backtracking-cost">pulling up common dependencies to minimize backtracking cost</h2>
<p>One of the common issues we have is that when we have a dependency group</p>
<pre><code>`A | B | C | D`
</code></pre>
<p>we try them in order, and if one fails, we undo everything it did, and move on to the next one. However,
this isn&rsquo;t perhaps the best choice of operation.</p>
<p>I explained before that one thing we do is queue the common dependencies of a package (i.e. dependencies
shared in all versions) when marking a package for install, but we don&rsquo;t do this here: We have already
lowered the representation of the dependency group into a list of versions, so we&rsquo;d need to extract the
package back out of it.</p>
<p>This can of course be done, but there may be a more interesting solution to the problem, in that we
simply enqueue all the common dependencies. That is, we add <code>n</code> backtracking levels for <code>n</code> possible
solutions:</p>
<ol>
<li>We enqueue the common dependencies of all possible solutions <code>deps(A)&amp;deps(B)&amp;deps(C)&amp;deps(D)</code></li>
<li>We decide (adding a decision level) <em>not to install D right now</em> and enqueue <code>deps(A)&amp;deps(B)&amp;deps(C)</code></li>
<li>We decide (adding a decision level) <em>not to install C right now</em> and enqueue <code>deps(A)&amp;deps(B)</code></li>
<li>We decide (adding a decision level) <em>not to install B right now</em> and enqueue <code>A</code></li>
</ol>
<p>Now if we need to backtrack from our choice of <code>A</code> we hopefully still have a lot of common dependencies
queued that we do not need to redo. While we have more backtracking levels, each backtracking level
would be significantly cheaper, especially if you have cheap backtracking (which admittedly we do not
have, yet anyway).</p>
<p>The caveat though is: It may be pretty expensive to find the common dependencies. We need to iterate
over all dependency groups of A and see if they are in B, C, and D, so we have a complexity of roughly</p>
<p><code>#A * (#B+#C+#D)</code></p>
<p>Each dependency group we need to check i.e. is <code>X|Y</code> in <code>B</code> meanwhile has linear cost: We need to
compare the memory content of two pointer arrays containing the list of possible versions that
solve the dependency group.
This means that <code>X|Y</code> and <code>Y|X</code> are different dependencies of course, but that is to be expected
&ndash; they are. But any dependency of the same order will have the same memory layout.</p>
<p>So really the cost is roughly <code>N^4</code>. This isn&rsquo;t nice.</p>
<p>You can apply various heuristics here on how to improve that, or you can even apply binary logic:</p>
<ol>
<li>Enqueue common dependencies of <code>A|B|C|D</code></li>
<li>Move into the left half, enqueue of <code>A|B</code></li>
<li>Again divide and conquer and select <code>A</code>.</li>
</ol>
<p>This has a significant advantage in long lists of choices, and also in the common case, where the
first solution should be the right one.</p>
<p>Or again, if you enqueue the package and a version restriction instead, you already get the common
dependencies enqueued for the chosen package at least.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>The new APT 3.0 solver</title>
      <link>https://blog.jak-linux.org/2024/05/14/solver3/</link>
      <pubDate>Tue, 14 May 2024 13:26:05 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2024/05/14/solver3/</guid>
      <description>&lt;p&gt;APT 2.9.3 introduces the first iteration of the new solver codenamed
solver3, and now available with the &amp;ndash;solver 3.0 option. The new solver
works fundamentally different from the old one.&lt;/p&gt;
&lt;h2 id=&#34;how-does-it-work&#34;&gt;How does it work?&lt;/h2&gt;
&lt;p&gt;Solver3 is a fully backtracking dependency solving algorithm that defers
choices to as late as possible. It starts with an empty set of packages,
then adds the manually installed packages, and then installs packages
automatically as necessary to satisfy the dependencies.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>APT 2.9.3 introduces the first iteration of the new solver codenamed
solver3, and now available with the &ndash;solver 3.0 option. The new solver
works fundamentally different from the old one.</p>
<h2 id="how-does-it-work">How does it work?</h2>
<p>Solver3 is a fully backtracking dependency solving algorithm that defers
choices to as late as possible. It starts with an empty set of packages,
then adds the manually installed packages, and then installs packages
automatically as necessary to satisfy the dependencies.</p>
<p>Deferring the choices is implemented multiple ways:</p>
<p>First, all install requests
recursively mark dependencies with a single solution for install, and any
packages that are being rejected due to conflicts or user requests will
cause their reverse dependencies to be transitively marked as rejected,
provided their or group cannot be solved by a different package.</p>
<p>Second, any dependency with more than one choice is pushed to a priority
queue that is ordered by the number of possible solutions, such that we
resolve a|b before a|b|c.</p>
<p>Not <em>just</em> by the number of solutions, though. One important point to
note is that optional dependencies, that is, Recommends, are always
sorting after mandatory dependencies. Do note on that: Recommended
packages do not &ldquo;nest&rdquo; in backtracking - dependencies of a Recommended
package themselves are not optional, so they will have to be resolved
before the next Recommended package is seen in the queue.</p>
<p>Another important step in deferring choices is extracting the common
dependencies of a package across its version and then installing them
before we even decide which of its versions we want to install - one
of the dependencies might cycle back to a specific version after all.</p>
<p>Decisions about package levels are recorded at a certain decision level,
if we reach a conflict we backtrack to the previous decision level,
mark the decision we made (install X) in the inverse (DO NOT INSTALL X),
reset all the state all decisions made at the higher level, and restore
any dependencies that are no longer resolved to the work queue.</p>
<h2 id="comparison-to-sat-solver-design">Comparison to SAT solver design.</h2>
<p>If you have studied SAT solver design, you&rsquo;ll find that essentially
this is a DPLL solver without pure literal elimination. A pure literal
eliminitation phase would not work for a package manager: First negative
pure literals (packages that everything conflicts with) do not exist,
and positive pure literals (packages nothing conflicts with) we do not want
to mark for install - we want to install as little as possible (well subject,
to policy).</p>
<p>As part of the solving phase, we also construct an implication graph, albeit
a partial one: The first package installing another package is marked as the
reason (A -&gt; B), the same thing for conflicts (not A -&gt; not B).</p>
<p>Once we have added the ability to have multiple parents in the implication
graph, it stands to reason that we can also implement the much more advanced
method of conflict-driven clause learning; where we do not jump back to the
previous decision level but exactly to the decision level that caused the
conflict. This would massively speed up backtracking.</p>
<h2 id="what-changes-can-you-expect-in-behavior">What changes can you expect in behavior?</h2>
<p>The most striking difference to the classic APT solver is that solver3 always keeps
manually installed packages around, it never offers to remove them. We will relax that
in a future iteration so that it can <em>replace</em> packages with new ones, that is, if your
package is no longer available in the repository (obsolete), but there is one that
Conflicts+Replaces+Provides it, solver3 will be allowed to install that and remove the
other.</p>
<p>Implementing that policy is rather trivial: We just need to queue <code>obsolete | replacement</code>
as a dependency to solve, rather than mark the obsolete package for install.</p>
<p>Another critical difference is the change in the autoremove behavior: The new solver
currently only knows the strongest dependency chain to each package, and hence it will
not keep around any packages that are only reachable via weaker chains.
A common example is when <code>gcc-&lt;version&gt;</code> packages accumulate on your system over the
years. They all have <code>Provides: c-compiler</code> and the <code>libtool</code> <code>Depends: gcc | c-compiler</code>
is enough to keep them around.</p>
<h1 id="new-features">New features</h1>
<p>The new option <code>--no-strict-pinning</code> instructs the solver to consider all versions of
a package and not just the candidate version. For example, you could use <code>apt install foo=2.0 --no-strict-pinning</code>
to install version 2.0 of foo and upgrade - or downgrade - packages as needed to satisfy <code>foo=2.0</code> dependencies.
This mostly comes in handy in use cases involving Debian experimental or the Ubuntu proposed pockets, where you
want to install a package from there, but try to satisfy from the normal release as much as possible.</p>
<p>The implication graph building allows us to implement an <code>apt why</code> command, that while not as nicely
detailed as aptitude, at least tells you the exact reason why a package is installed. It will only show
the strongest dependency chain at first of course, since that is what we record.</p>
<h2 id="what-is-left-to-do">What is left to do?</h2>
<p>At the moment, error information is not stored across backtracking in any way, but we generally
will want to show you the first conflict we reach as it is the most natural one; or all conflicts.
Currently you get the last conflict which may not be particularly useful.</p>
<p>Likewise, errors currently are just rendered as implication graphs of the form <code>[not] A -&gt; [not] B -&gt; ...</code>,
and we need to put in some work to present those nicely.</p>
<p>The test suite is not passing yet, I haven&rsquo;t really started working on it. A challenge is that most
packages in the test suite are manually installed as they are mocked, and the solver now doesn&rsquo;t remove
those.</p>
<p>We plan to implement the replacement logic such that foo can be replaced by <code>foo2 Conflicts/Replaces/Provides foo</code>
without needing to be automatically installed.</p>
<p>Improving the backtracking to be non-chronological conflict-driven clause learning would vastly
enhance our backtracking performance. Not that it seems to be an issue right now in my limited
testing (mostly noble 64-bit-time_t upgrades). A lot of that complexity you have normally is not
there because the manually installed packages and resulting unit propagation (single-solution
Depends/Reverse-Depends for Conflicts) already ground us fairly far in what changes we can actually make.</p>
<p>Once all the stuff has landed, we need to start rolling it out and gather feedback. On Ubuntu I&rsquo;d like
automated feedback on regressions (running solver3 in parallel, checking if result is worse and then
submitting an error to the error tracker), on Debian this could just be a role email address to send
solver dumps to.</p>
<p>At the same time, we can also incrementally start rolling this out. Like phased updates in Ubuntu,
we can also roll out the new solver as the default to 10%, 20%, 50% of users before going to the
full 100%. This will allow us to capture regressions early and fix them.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Divergence - A case for different upgrade approaches</title>
      <link>https://blog.jak-linux.org/2023/10/10/a-case-for-different-upgrades/</link>
      <pubDate>Tue, 10 Oct 2023 19:22:49 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2023/10/10/a-case-for-different-upgrades/</guid>
      <description>&lt;p&gt;APT currently knows about three types of upgrades:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;upgrade without new packages (apt-get upgrade)&lt;/li&gt;
&lt;li&gt;upgrade with new packages (apt upgrade)&lt;/li&gt;
&lt;li&gt;upgrade with new packages and deletions (apt{,-get} {dist,full}-upgrade)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these upgrade types are necessary to deal with upgrades within a
distribution release. Yes, sometimes even removals may be needed because
bug fixes require adding a Conflicts somewhere.&lt;/p&gt;
&lt;p&gt;In Ubuntu we have a third type of upgrades, handled by a separate tool: release
upgrades. &lt;code&gt;ubuntu-release-upgrader&lt;/code&gt; changes your sources.list, and applies various
quirks to the upgrade.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>APT currently knows about three types of upgrades:</p>
<ul>
<li>upgrade without new packages (apt-get upgrade)</li>
<li>upgrade with new packages (apt upgrade)</li>
<li>upgrade with new packages and deletions (apt{,-get} {dist,full}-upgrade)</li>
</ul>
<p>All of these upgrade types are necessary to deal with upgrades within a
distribution release. Yes, sometimes even removals may be needed because
bug fixes require adding a Conflicts somewhere.</p>
<p>In Ubuntu we have a third type of upgrades, handled by a separate tool: release
upgrades. <code>ubuntu-release-upgrader</code> changes your sources.list, and applies various
quirks to the upgrade.</p>
<p>In this post, I want to look not at the quirk aspects but discuss how dependency
solving should differ between intra-release and inter-release upgrades.</p>
<p>Previous solver projects (such as Mancoosi) operated under the assumption that minimizing
the number of changes performed should ultimately be the main goal of a solver. This makes
sense as every change causes risks.
However it ignores a different risk, which especially applies when upgrading from one
distribution release to a newer one: Increasing divergence from the norm.</p>
<p>Consider a person installs <code>foo</code> in Debian 12. <code>foo</code> depends on <code>a | b</code>, so <code>a</code> will
be automatically installed to satisfy the dependency. A release later, <code>a</code> has some
known issues and <code>b</code> is prefered, the dependency now reads: <code>b|a</code>.</p>
<p>A classic solver would continue to keep <code>a</code> installed because it was installed before,
leading upgraded installs to have <code>foo, a</code> installed whereas new systems have <code>foo, b</code>
installed. As systems get upgraded over and over, they continue to diverge further and
further from new installs to the point that it adds substantial support effort.</p>
<p>My proposal for the new APT solver is that when we perform release upgrades, we forget
which packages where previously automatically installed.
We effectively perform a normalization: All systems with the same set of manually installed packages will end up with the same set of automatically installed packages.
Consider the solving starting with an empty set and then installing the latest version of each previously manually installed package: It will see now that <code>foo</code> depends
<code>b|a</code> and install <code>b</code> (and <code>a</code> will be removed later on as its not part of the solution).</p>
<p>Another case of divergence is <code>Suggests</code> handling. Consider that <code>foo</code> also Suggests
<code>s</code>. You now install another package <code>bar</code> that depends <code>s</code>, hence <code>s</code> gets installed.
Upon removing <code>bar</code>, <code>s</code> is not being removed automatically because <code>foo</code> still suggests
it (and you may have grown used to <code>foo</code>&rsquo;s integration of <code>s</code>). This is because apt considers
Suggests to be important - they won&rsquo;t be automatically installed, but will not be automatically
removed.</p>
<p>In Ubuntu, we unset that policy on release upgrades to normalize the systems. The reasoning
for that is simple: While you may have grown to use <code>s</code> as part of <code>foo</code> during the release,
an upgrade to the next release already is big enough that removing <code>s</code> is going to have
less of an impact - breakage of workflows is expected between release upgrades.</p>
<p>I believe that <code>apt release-upgrade</code> will benefit from both of these design choices,
and in the end it boils down to a simple mantra:</p>
<ul>
<li>On upgrades within a release, minimize changes.</li>
<li>On upgrades between releases, minimize divergence from fresh installs.</li>
</ul>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Ubuntu 2022v1 secure boot key rotation and friends</title>
      <link>https://blog.jak-linux.org/2023/02/01/ubuntu-key-rotation/</link>
      <pubDate>Wed, 01 Feb 2023 14:40:27 +0100</pubDate>
      
      <guid>https://blog.jak-linux.org/2023/02/01/ubuntu-key-rotation/</guid>
      <description>&lt;p&gt;This is the story of the currently progressing changes to secure boot
on Ubuntu and the history of how we got to where we are.&lt;/p&gt;
&lt;h1 id=&#34;taking-a-step-back-how-does-secure-boot-on-ubuntu-work&#34;&gt;taking a step back: how does secure boot on Ubuntu work?&lt;/h1&gt;
&lt;p&gt;Booting on Ubuntu involves three components after the firmware:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;shim&lt;/li&gt;
&lt;li&gt;grub&lt;/li&gt;
&lt;li&gt;linux&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each of these is a PE binary signed with a key. The shim is signed by Microsoft&amp;rsquo;s
3rd party key and embeds a self-signed Canonical CA certificate, and optionally a
vendor dbx (a list of revoked certificates or binaries). grub and linux (and fwupd)
are then signed by a certificate issued by that CA&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>This is the story of the currently progressing changes to secure boot
on Ubuntu and the history of how we got to where we are.</p>
<h1 id="taking-a-step-back-how-does-secure-boot-on-ubuntu-work">taking a step back: how does secure boot on Ubuntu work?</h1>
<p>Booting on Ubuntu involves three components after the firmware:</p>
<ol>
<li>shim</li>
<li>grub</li>
<li>linux</li>
</ol>
<p>Each of these is a PE binary signed with a key. The shim is signed by Microsoft&rsquo;s
3rd party key and embeds a self-signed Canonical CA certificate, and optionally a
vendor dbx (a list of revoked certificates or binaries). grub and linux (and fwupd)
are then signed by a certificate issued by that CA</p>
<p>In Ubuntu&rsquo;s case, the CA certificate is sharded: Multiple people each have a part
of the key and they need to meet to be able to combine it and sign things, such as
new code signing certificates.</p>
<h2 id="boothole">BootHole</h2>
<p>When BootHole happened in 2020, travel was suspended and we hence could not rotate
to a new signing certificate. So when it came to updating our shim for the CVEs, we
had to revoke all previously signed kernels, grubs, shims, fwupds by their hashes.</p>
<p>This generated a very large vendor dbx which caused lots of issues as shim exported
them to a UEFI variable, and not everyone had enough space for such large variables.
Sigh.</p>
<p>We decided we want to rotate our signing key next time.</p>
<p>This was also when upstream added SBAT metadata to shim and grub. This gives
a simple versioning scheme for security updates and easy revocation using a
simple EFI variable that shim writes to and reads from.</p>
<h2 id="spring-2022-cves">Spring 2022 CVEs</h2>
<p>We still were not ready for travel in 2021, but during BootHole we developed the
SBAT mechanism, so one could revoke a grub or shim by setting a single EFI variable.</p>
<p>We actually missed rotating the shim this cycle as a new vulnerability was reported
immediately after it, and we decided to hold on to it.</p>
<h2 id="2022-key-rotation-and-the-fall-cves">2022 key rotation and the fall CVEs</h2>
<p>This caused some problems when the 2nd CVE round came, as we did not have a shim
with the latest SBAT level, and neither did a lot of others, so we ended up deciding
upstream to not bump the shim SBAT requirements just yet. Sigh.</p>
<p>Anyway, in October we were meeting again for the first time at a Canonical sprint,
and the shardholders got together and created three new signing keys: 2022v1, 2022v2,
and 2022v3. It took us until January before they were installed into the signing service
and PPAs setup to sign with them.</p>
<p>We also submitted a shim 15.7 with the old keys revoked which came back at around
the same time.</p>
<p>Now we were in a hurry. The 22.04.2 point release was scheduled for around middle
of February, and we had nothing signed with the new keys yet, but our new shim
which we need for the point release (so the point release media remains bootable
after the next round of CVEs), required new keys.</p>
<p>So how do we ensure that users have kernels, grubs, and fwupd signed with the
new key before we install the new shim?</p>
<h2 id="upgrade-ordering">upgrade ordering</h2>
<p>grub and fwupd are simple cases: For grub, we depend on the new version. We decided
to backport grub 2.06 to all releases (which moved focal and bionic up from 2.04), and
kept the versioning of the -signed packages the same across all releases, so we were
able to simply bump the Depends for grub to specify the new minimum version. For fwupd-efi,
we added Breaks.</p>
<p>(Actually, we also had a backport of the CVEs for 2.04 based grub, and we did publish that
for 20.04 signed with the old keys before backporting 2.06 to it.)</p>
<p>Kernels are a different story: There are about 60 kernels out there. My initial idea was
that we could just add Breaks for all of them. So our meta package linux-image-generic which
depends on linux-image-$(uname -r)-generic, we&rsquo;d simply add Breaks: linux-image-generic (&laquo; 5.19.0-31)
and then adjust those breaks for each series. This would have been super annoying, but
ultimately I figured this would be the safest option. This however caused concern, because
it could be that apt decides to remove the kernel metapackage.</p>
<p>I explored checking the kernels at runtime and aborting if we don&rsquo;t have a trusted
kernel in preinst. This ensures that if you try to upgrade shim without having a kernel,
it would fail to install. But this ultimately has a couple of issues:</p>
<ol>
<li>It aborts the entire transaction at that point, so users will be unable to run
<code>apt upgrade</code> until they have a recent kernel.</li>
<li>We cannot even guarantee that a kernel would be unpacked first. So even if you got
a new kernel, apt/dpkg might attempt to unpack it first and then the preinst would fail
because no kernel is present yet.</li>
</ol>
<p>Ultimately we believed the danger to be too large given that no kernels had yet been released
to users. If we had kernels pushed out for 1-2 months already, this would have been a viable
choice.</p>
<p>So in the end, I ended up modifying the shim packaging to install both the latest shim <em>and</em>
the previous one, and an update-alternatives alternative to select between the two:</p>
<p>In it&rsquo;s post-installation maintainer script, shim-signed checks whether all kernels with a
version greater or equal to the running one are not revoked, and if so, it will setup the
latest alternative with priority 100 and the previous with a priority of 50.
If one or more of those kernels was signed with a revoked key, it will swap the priorities
around, so that the previous version is preferred.</p>
<p>Now this is fairly static, and we do want you to switch to the latest shim eventually, so
I also added hooks to the kernel install to trigger the shim-signed postinst script when
a new kernel is being installed. It will then update the alternatives based on the current
set of kernels, and if it now points to the latest shim, reinstall shim and grub to the
ESP.</p>
<p>Ultimately this means that once you install your 2nd non-revoked kernel, or you install
a non-revoked kernel and then reconfigure shim or the kernel, you will get the latest
shim. When you install your first non-revoked kernel, your currently booted kernel is
still revoked, so it&rsquo;s not upgraded immediately. This has a benefit in that you will
most likely have two kernels you can boot without disabling secure boot.</p>
<h2 id="regressions">regressions</h2>
<p>Of course, the first version I uploaded had still some remaining hardcoded &ldquo;shimx64&rdquo;
in the scripts and so failed to install on arm64 where &ldquo;shimaa64&rdquo; is used. And if that
were not enough, I also forgot to include support for gzip compressed kernels there.
Sigh, I need better testing infrastructure to be able to easily run arm64 tests as
well (I only tested the actual booting there, not the scripts).</p>
<p>shim-signed migrated to the release pocket in lunar fairly quickly, but this caused
images to stop working, because the new shim was installed into images, but no
kernel was available yet, so we had to demote it to proposed and block migration.
Despite all the work done for end users, we need to be careful to roll this out for
image building.</p>
<h2 id="another-grub-update-for-oom-issues">another grub update for OOM issues.</h2>
<p>We had two grubs to release: First there was the security update for the recent set
of CVEs, then there also was an OOM issue for large initrds which was blocking critical
OEM work.</p>
<p>We fixed the OOM issue by cherry-picking all 2.12 memory management patches, as well
as the red hat patches to the loader we take from there. This ended up a fairly large
patch set and I was hesitant to tie the security update to that, so I ended up pushing
the security update everywhere first, and then pushed the OOM fixes this week.</p>
<p>With the OOM patches, you should be able to boot initrds of between 400M and 1GB, it
also depends on the memory layout of your machine and your screen resolution and background
images. So OEM team had success testing 400MB irl, and I tested up to I think it was 1.2GB
in qemu, I ran out of FAT space then and stopped going higher :D</p>
<h2 id="other-features-in-this-round">other features in this round</h2>
<ul>
<li>Intel TDX support in grub and shim</li>
<li>Kernels are allocated as CODE now not DATA as per the upstream mm changes, might fix boot on X13s</li>
</ul>
<h2 id="am-i-using-this-yet">am I using this yet?</h2>
<p>The new signing keys are used in:</p>
<ul>
<li>shim-signed 1.54 on 22.10+, 1.51.3 on 22.04, 1.40.9 on 20.04, 1.37~18.04.13 on 18.04</li>
<li>grub2-signed 1.187.2~ or newer (binary packages grub-efi-amd64-signed or grub-efi-arm64-signed),
1.192 on 23.04.</li>
<li>fwupd-signed 1.51~ or newer</li>
<li>various linux updates. Check <code>apt changelog linux-image-unsigned-$(uname -r)</code> to see if
<code> Revoke &amp; rotate to new signing key (LP: #2002812)</code> is mentioned in there to see if it
signed with the new key.</li>
</ul>
<p>If you were able to install shim-signed, your grub and fwupd-efi will have the correct
version as that is ensured by packaging. However your shim may still point to the old one.
To check which shim will be used by grub-install, you can check the status of the <code>shimx64.efi.signed</code>
or (on arm64) <code>shimaa64.efi.signed</code> alternative. The best link needs to point to the file ending in
latest:</p>
<pre tabindex="0"><code>$ update-alternatives --display shimx64.efi.signed
shimx64.efi.signed - auto mode
  link best version is /usr/lib/shim/shimx64.efi.signed.latest
  link currently points to /usr/lib/shim/shimx64.efi.signed.latest
  link shimx64.efi.signed is /usr/lib/shim/shimx64.efi.signed
/usr/lib/shim/shimx64.efi.signed.latest - priority 100
/usr/lib/shim/shimx64.efi.signed.previous - priority 50
</code></pre><p>If it does not, but you have installed a new kernel compatible with the new shim, you can
switch immediately to the new shim after rebooting into the kernel by running <code>dpkg-reconfigure shim-signed</code>. You&rsquo;ll see in the output if the shim was updated, or you can check the output
of <code>update-alternatives</code> as you did above after the reconfiguration has finished.</p>
<p>For the out of memory issues in grub, you need grub2-signed 1.187.3~ (same binaries
as above).</p>
<h2 id="how-do-i-test-this-while-its-in-proposed">how do I test this (while it&rsquo;s in proposed)?</h2>
<ol>
<li>upgrade your kernel to proposed and reboot into that</li>
<li>upgrade your grub-efi-amd64-signed, shim-signed, fwupd-signed to proposed.</li>
</ol>
<p>If you already upgraded your shim before your kernel, don&rsquo;t worry:</p>
<ol>
<li>upgrade your kernel and reboot</li>
<li>run dpkg-reconfigure shim-signed</li>
</ol>
<p>And you&rsquo;ll be all good to go.</p>
<h2 id="deep-dive-uploading-signed-boot-assets-to-ubuntu">deep dive: uploading signed boot assets to Ubuntu</h2>
<p>For each signed boot asset, we build one version in the latest stable release and the
development release. We then binary copy the built binaries from the latest stable release
to older stable releases. This process ensures two things: We know the next stable release
is able to build the assets and we also minimize the number of signed assets.</p>
<p>OK, I lied. For shim, we actually do not build in the development release but copy the
binaries upward from the latest stable, as each shim needs to go through external signing.</p>
<p>The entire workflow looks something like this:</p>
<ol>
<li>
<p>Upload the unsigned package to one of the following “build” PPAs:</p>
<ul>
<li><a href="https://launchpad.net/~ubuntu-uefi-team/+archive/ubuntu/ppa">https://launchpad.net/~ubuntu-uefi-team/+archive/ubuntu/ppa</a> for non-embargoed updates</li>
<li><a href="https://launchpad.net/~ubuntu-security-embargoed-shared/+archive/ubuntu/grub2">https://launchpad.net/~ubuntu-security-embargoed-shared/+archive/ubuntu/grub2</a> for embargoed updates</li>
</ul>
</li>
<li>
<p>Upload the signed package to the same PPA</p>
</li>
<li>
<p>For stable release uploads:</p>
<ul>
<li>Copy the unsigned package back across all stable releases in the PPA</li>
<li>Upload the signed package for stable releases to the same PPA with <code>~&lt;release&gt;.1</code> appended to the version</li>
</ul>
</li>
<li>
<p>Submit a request to canonical-signing-jobs to sign the uploads.</p>
<p>The signing job helper copies the binary -unsigned packages to the primary-2022v1 PPA where they are
signed, creating a signing tarball, then it copies the source package for the -signed package to the
same PPA which then downloads the signing tarball during build and places the signed assets into
the -signed deb.</p>
<p>Resulting binaries will be placed into the proposed PPA: <a href="https://launchpad.net/~ubuntu-uefi-team/+archive/ubuntu/proposed">https://launchpad.net/~ubuntu-uefi-team/+archive/ubuntu/proposed</a></p>
</li>
<li>
<p>Review the binaries themselves</p>
</li>
<li>
<p>Unembargo and binary copy the binaries from the proposed PPA to the proposed-public PPA: <a href="https://launchpad.net/~ubuntu-uefi-team/+archive/ubuntu/proposed-public">https://launchpad.net/~ubuntu-uefi-team/+archive/ubuntu/proposed-public</a>.</p>
<p>This step is not strictly necessary, but it enables tools like sru-review to work, as they cannot access the packages from the normal private “proposed” PPA.</p>
</li>
<li>
<p>Binary copy from proposed-public to the proposed queue(s) in the primary archive</p>
</li>
</ol>
<p>Lots of steps!</p>
<h2 id="wip">WIP</h2>
<p>As of writing, only the grub updates have been released, other updates are still being
verified in proposed. An update for fwupd in bionic will be issued at a later point, removing
the EFI bits from the fwupd 1.2 packaging and using the separate fwupd-efi project instead
like later release series.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>APT Z3 Solver Basics</title>
      <link>https://blog.jak-linux.org/2021/11/21/apt-z3-solver-basics/</link>
      <pubDate>Sun, 21 Nov 2021 20:49:34 +0100</pubDate>
      
      <guid>https://blog.jak-linux.org/2021/11/21/apt-z3-solver-basics/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://github.com/Z3Prover/z3&#34;&gt;Z3&lt;/a&gt; is a theorem prover developed at Microsoft research and available as
a dynamically linked C++ library in Debian-based distributions. While the
library is a whopping 16 MB, and the solver is a tad slow, it&amp;rsquo;s permissive
licensing, and number of tactics offered give it a huge potential for use
in solving dependencies in a wide variety of applications.&lt;/p&gt;
&lt;p&gt;Z3 does not need normalized formulas, but offers higher level abstractions
like &lt;code&gt;atmost&lt;/code&gt; and &lt;code&gt;atleast&lt;/code&gt; and &lt;code&gt;implies&lt;/code&gt;, that we will make use of together
with boolean variables to translate the dependency problem to a form Z3
understands.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p><a href="https://github.com/Z3Prover/z3">Z3</a> is a theorem prover developed at Microsoft research and available as
a dynamically linked C++ library in Debian-based distributions. While the
library is a whopping 16 MB, and the solver is a tad slow, it&rsquo;s permissive
licensing, and number of tactics offered give it a huge potential for use
in solving dependencies in a wide variety of applications.</p>
<p>Z3 does not need normalized formulas, but offers higher level abstractions
like <code>atmost</code> and <code>atleast</code> and <code>implies</code>, that we will make use of together
with boolean variables to translate the dependency problem to a form Z3
understands.</p>
<p>In this post, we&rsquo;ll see how we can apply Z3 to the dependency resolution
in APT. We&rsquo;ll only discuss the basics here, a future post will explore
optimization criteria and recommends.</p>
<h2 id="translating-the-universe">Translating the universe</h2>
<p>APT&rsquo;s package universe consists of 3 relevant things: packages (the tuple
of name and architecture), versions (basically a .deb), and dependencies
between versions.</p>
<p>While we could translate our entire universe to Z3 problems, we instead will
construct a root set from packages that were manually installed and versions
marked for installation, and then build the transitive root set from it by
translating all versions reachable from the root set.</p>
<p>For each package P in the transitive root set, we create a boolean literal <code>P</code>. We then
translate each version P1, P2, and so on. Translating a version means building
a boolean literal for it, e.g. <code>P1</code>, and then translating the dependencies as shown below.</p>
<p>We now need to create two more clauses to satisfy the basic requirements for debs:</p>
<ol>
<li>If a version is installed, the package is installed; and vice versa. We can encode
this requirement for P above as <code>P == atleast({P1,P2}, 1)</code>.</li>
<li>There can only be one version installed. We add an additional constraint of the
form <code>atmost({P1,P2}, 1)</code>.</li>
</ol>
<p>We also encode the requirements of the operation.</p>
<ol>
<li>For each package P that is manually installed, add a constraint <code>P</code>.</li>
<li>For each version V that is marked for install, add a constraint <code>V</code>.</li>
<li>For each package P that is marked for removal, add a constraint <code>!P</code>.</li>
</ol>
<h3 id="dependencies">Dependencies</h3>
<p>Packages in APT have dependencies of two basic forms: Depends and Conflicts,
as well as variations like Breaks (identical to Conflicts in solving terms),
and Recommends (soft Depends) - we&rsquo;ll ignore those for now. We&rsquo;ll discuss
Conflicts in the next section.</p>
<p>Let&rsquo;s take a basic dependency list: <code>A Depends: X|Y, Z</code>. To represent that
dependency, we expand each name to a list of versions that can satisfy
the dependency, for example <code>X1|X2|Y1, Z1</code>.</p>
<p>Translating this dependency list to our Z3 solver, we create boolean variables
<code>X1,X2,Y1,Z1</code> and define two rules:</p>
<ol>
<li><code>A implies atleast({X1,X2,Y1}, 1)</code></li>
<li><code>A implies atleast({Z1}, 1)</code></li>
</ol>
<p>If there actually was nothing that satisfied the Z requirement, we&rsquo;d have added
a rule <code>not A</code>. It would be possible to simply not tell Z3 about the version at
all as an optimization, but that adds more complexity, and the <code>not A</code> constraint
should not cause too many problems.</p>
<h3 id="conflicts">Conflicts</h3>
<p>Conflicts cannot have <code>or</code> in them. A dependency <code>B Conflicts: X, Y</code> means that only
one of B, X, and Y can be installed. We can directly encode this in Z3 by using the
constraint <code>atmost({B,X,Y}, 1)</code>. This is an optimized encoding of the constraint: We
could have encoded each conflict in the form <code>!B or !X</code>, <code>!B or !X</code>, and so on. Usually
this leads to worse performance as it introduces additional clauses.</p>
<h2 id="complete-example">Complete example</h2>
<p>Let&rsquo;s assume we start with an empty install and want to install the package <code>a</code> below.</p>
<pre tabindex="0"><code>Package: a
Version: 1
Depends: c | b

Package: b
Version: 1

Package: b
Version: 2
Conflicts: x

Package: d
Version: 1

Package: x
Version: 1
</code></pre><p>The translation in Z3 rules looks like this:</p>
<ol>
<li>Package rules for <code>a</code>:
<ol>
<li><code>a == atleast({a1}, 1)</code> - package is installed iff one version is</li>
<li><code>atmost({a1}, 1)</code> - only one version may be installed</li>
<li><code>a</code> &ndash; a must be installed</li>
</ol>
</li>
<li>Dependency rules for <code>a</code>
<ol>
<li><code>implies(a1, atleast({b2, b1}, 1))</code> &ndash; the translated dependency above. note that <code>c</code> is gone, it&rsquo;s not reachable.</li>
</ol>
</li>
<li>Package rules for <code>b</code>:
<ol>
<li><code>b == atleast({b1,b2}, 1)</code> - package is installed iff one version is</li>
<li><code>atmost({b1, b2}, 1)</code> - only one version may be installed</li>
</ol>
</li>
<li>Dependencies for <code>b (= 2)</code>:
<ol>
<li><code>atmost({b2, x1}, 1)</code> - the conflicts between x and b = 2 above</li>
</ol>
</li>
<li>Package rules for <code>x</code>:
<ol>
<li><code>x == atleast({x1}, 1)</code> - package is installed iff one version is</li>
<li><code>atmost({x1}, 1)</code> - only one version may be installed</li>
</ol>
</li>
</ol>
<p>The package <code>d</code> is not translated, as it is not reachable from the root
set <code>{a1}</code>, the transitive root set is <code>{a1,b1,b2,x1}</code>.</p>
<h2 id="next-iteration-optimization">Next iteration: Optimization</h2>
<p>We have now constructed the basic set of rules that allows us to
solve solve our dependency problems (equivalent to SAT), however
it might lead to suboptimal solutions where it removes automatically
installed packages, or installs more packages than necessary, to
name a few examples.</p>
<p>In our next iteration, we have to look at introducing optimization;
for example, have the minimum number of removals, the minimal
number of changed packages, or satisfy as many recommends as possible.
We will also look at the upgrade problem (upgrade as many packages as
possible), the autoremove problem (remove as many automatically installed
packages as possible).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Migrating away from apt-key</title>
      <link>https://blog.jak-linux.org/2021/06/20/migrating-away-apt-key/</link>
      <pubDate>Sun, 20 Jun 2021 09:42:22 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2021/06/20/migrating-away-apt-key/</guid>
      <description>&lt;p&gt;This is an edited copy of an email I sent to provide guidance to users of apt-key as to how to handle things in a post apt-key world.&lt;/p&gt;
&lt;p&gt;The manual page already provides all you need to know for replacing &lt;code&gt;apt-key add&lt;/code&gt; usage:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: Instead of using this command a keyring should be placed directly in the /etc/apt/trusted.gpg.d/ directory with a descriptive name and either &amp;ldquo;gpg&amp;rdquo; or &amp;ldquo;asc&amp;rdquo; as file extension&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>This is an edited copy of an email I sent to provide guidance to users of apt-key as to how to handle things in a post apt-key world.</p>
<p>The manual page already provides all you need to know for replacing <code>apt-key add</code> usage:</p>
<blockquote>
<p>Note: Instead of using this command a keyring should be placed directly in the /etc/apt/trusted.gpg.d/ directory with a descriptive name and either &ldquo;gpg&rdquo; or &ldquo;asc&rdquo; as file extension</p>
</blockquote>
<p>So it&rsquo;s kind of surprising people need step by step instructions for how to copy/download a file into a directory.</p>
<p>I&rsquo;ll also discuss the alternative security snakeoil approach with signed-by that&rsquo;s become popular. Maybe we should not have added <code>signed-by</code>, people seem to forget that debs still run maintainer scripts as root.</p>
<p>Aside from this email, Debian users should look into <code>extrepo</code>, which manages curated external repositories for you.</p>
<h2 id="direct-translation">Direct translation</h2>
<p>Assume you currently have:</p>
<pre><code>wget -qO- https://myrepo.example/myrepo.asc | sudo apt-key add –
</code></pre>
<p>To translate this directly for bionic and newer, you can use:</p>
<pre><code>sudo wget -qO /etc/apt/trusted.gpg.d/myrepo.asc https://myrepo.example/myrepo.asc
</code></pre>
<p>or to avoid downloading as root:</p>
<pre><code>wget -qO-  https://myrepo.example/myrepo.asc | sudo tee -a /etc/apt/trusted.gpg.d/myrepo.asc
</code></pre>
<p>Older (and all) releases only support unarmored files with an extension .gpg. If you care about them, provide one, and use</p>
<pre><code>sudo wget -qO /etc/apt/trusted.gpg.d/myrepo.gpg https://myrepo.example/myrepo.gpg
</code></pre>
<p>Some people will tell you to download the <code>.asc</code> and pipe it to <code>gpg --dearmor</code>, but <code>gpg</code> might not be installed, so really, just offer a <code>.gpg</code> one instead that is supported on all systems.</p>
<p>wget might not be available everywhere so you can use apt-helper:</p>
<pre><code>sudo /usr/lib/apt/apt-helper download-file https://myrepo.example/myrepo.asc /etc/apt/trusted.gpg.d/myrepo.asc
</code></pre>
<p>or, to avoid downloading as root:</p>
<pre><code>/usr/lib/apt/apt-helper download-file https://myrepo.example/myrepo.asc /tmp/myrepo.asc &amp;&amp; sudo mv /tmp/myrepo.asc /etc/apt/trusted.gpg.d
</code></pre>
<h2 id="pretending-to-be-safer-by-using-signed-by">Pretending to be safer by using signed-by</h2>
<p>People say it&rsquo;s good practice to <em>not</em> use <code>trusted.gpg.d</code> and install the file elsewhere and then refer to it from the <code>sources.list</code> entry
by using <code>signed-by=&lt;path to the file&gt;</code>. So this looks a lot safer, because now your key can&rsquo;t sign other unrelated repositories. In
practice, security increase is minimal, since package maintainer scripts run as root anyway. But I guess it&rsquo;s better for publicity :)</p>
<p>As an example, here are the instructions to install <code>signal-desktop</code> from signal.org. As mentioned, <code>gpg --dearmor</code> use in there is not a good idea, and I&rsquo;d personally not tell people to modify <code>/usr</code> as it&rsquo;s supposed to be managed by the package manager, but we don&rsquo;t have an <code>/etc/apt/keyrings</code> or similar at the moment; it&rsquo;s fine though if the keyring is installed by the package. You can also just add the file there as a starting point, and then install
a keyring package overriding it (pretend there is a signal-desktop-keyring package below that would override the .gpg we added).</p>
<pre><code># NOTE: These instructions only work for 64 bit Debian-based
# Linux distributions such as Ubuntu, Mint etc.

# 1. Install our official public software signing key
wget -O- https://updates.signal.org/desktop/apt/keys.asc | gpg --dearmor &gt; signal-desktop-keyring.gpg
cat signal-desktop-keyring.gpg | sudo tee -a /usr/share/keyrings/signal-desktop-keyring.gpg &gt; /dev/null

# 2. Add our repository to your list of repositories
echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/signal-desktop-keyring.gpg] https://updates.signal.org/desktop/apt xenial main' |\
  sudo tee -a /etc/apt/sources.list.d/signal-xenial.list

# 3. Update your package database and install signal
sudo apt update &amp;&amp; sudo apt install signal-desktop
</code></pre>
<p>I do wonder why they do <code>wget | gpg --dearmor</code>, pipe that into the file and then <code>cat | sudo tee</code> it, instead of having that all in one pipeline. Maybe they want nicer progress reporting.</p>
<h2 id="scenario-specific-guidance">Scenario-specific guidance</h2>
<p>We have three scenarios:</p>
<p>For system image building, shipping the key in <code>/etc/apt/trusted.gpg.d</code> seems reasonable to me; you are the vendor sort of, so it can be globally trusted.</p>
<p>Chrome-style debs and repository config debs: If you ship a deb, embedding the <code>sources.list.d</code> snippet (calling it <code>$myrepo.list</code>) and shipping a <code>$myrepo.gpg </code>in <code>/usr/share/keyrings</code> is the best approach. Whether you ship that in product debs aka <code>vscode</code>/<code>chromium</code> or provide a repository configuration deb (let&rsquo;s call it <code>myrepo-repo.deb</code>) and then tell people to run <code>apt update</code> followed by <code>apt install &lt;package inside the repo&gt;</code> depends on how many packages are in the repo, I guess.</p>
<p>Manual instructions (signal style): The third case, where you tell people to run <code>wget</code> themselves, I find tricky.
As we see in signal, just stuffing keyring files into <code>/usr/share/keyrings</code> is popular, despite <code>/usr</code> supposed to be managed by the package manager.
We don&rsquo;t have another dir inside <code>/etc</code> (or <code>/usr/local</code>), so it&rsquo;s hard to suggest something else.
There&rsquo;s no significant benefit from actually using <code>signed-by</code>, so it&rsquo;s kind of extra work for little gain, though.</p>
<h2 id="addendum-future-work">Addendum: Future work</h2>
<p>This part is new, just for this blog post. Let&rsquo;s look at upcoming changes and how they make things easier.</p>
<h3 id="bundled-sources-files">Bundled <code>.sources</code> files</h3>
<p>Assuming I get my <a href="https://salsa.debian.org/apt-team/apt/-/merge_requests/176">merge request</a> merged, the next version of APT (2.4/2.3.something) will do away with all the complexity and allow you to embed the key directly into a deb822 <code>.sources</code> file (which have been available for some time now):</p>
<pre><code>Types: deb
URIs: https://myrepo.example/ https://myotherrepo.example/
Suites: stable not-so-stable
Components: main
Signed-By:
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 .
 mDMEYCQjIxYJKwYBBAHaRw8BAQdAD/P5Nvvnvk66SxBBHDbhRml9ORg1WV5CvzKY
 CuMfoIS0BmFiY2RlZoiQBBMWCgA4FiEErCIG1VhKWMWo2yfAREZd5NfO31cFAmAk
 IyMCGyMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQREZd5NfO31fbOwD6ArzS
 dM0Dkd5h2Ujy1b6KcAaVW9FOa5UNfJ9FFBtjLQEBAJ7UyWD3dZzhvlaAwunsk7DG
 3bHcln8DMpIJVXht78sL
 =IE0r
 -----END PGP PUBLIC KEY BLOCK-----
</code></pre>
<p>Then you can just provide a <code>.sources</code> files to users,
they place it into `sources.list.d,
and everything magically works</p>
<p>Probably adding a nice <code>apt add-source</code> command for it I guess.</p>
<p>Well, python-apt&rsquo;s <code>aptsources</code> package still does not support deb822 sources, and
never will, we&rsquo;ll need an <code>aptsources2</code> for that for backwards-compatibility reasons,
and then port <code>software-properties</code> and other users to it.</p>
<h3 id="openpgp-vs-aptsign">OpenPGP vs aptsign</h3>
<p>We do have a better, tighter replacement for gpg in the works which uses Ed25519
keys to sign Release files. It&rsquo;s temporarily named <code>aptsign</code>, but it&rsquo;s a generic
signer for single-section deb822 files, similar to <code>signify</code>/<code>minisign</code>.</p>
<ul>
<li>Reference implementation: <a href="https://salsa.debian.org/apt-team/python-aptsign">https://salsa.debian.org/apt-team/python-aptsign</a></li>
<li>Specification: <a href="https://wiki.debian.org/Teams/Apt/Spec/AptSign">https://wiki.debian.org/Teams/Apt/Spec/AptSign</a></li>
</ul>
<p>We believe that this solves the security nightmare that our OpenPGP integration
is while reducing complexity at the same time. Keys are much shorter, so the
bundled sources file above will look much nicer.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>APT 2.2 released</title>
      <link>https://blog.jak-linux.org/2021/02/18/apt-2.2/</link>
      <pubDate>Thu, 18 Feb 2021 21:09:27 +0100</pubDate>
      
      <guid>https://blog.jak-linux.org/2021/02/18/apt-2.2/</guid>
      <description>&lt;p&gt;APT 2.2.0 marks the freeze of the 2.1 development series and the start of the 2.2 stable series.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s have a look at what changed compared to 2.2. Many of you who run Debian testing or unstable,
or Ubuntu groovy or hirsute will already have seen most of those changes.&lt;/p&gt;
&lt;h2 id=&#34;new-features&#34;&gt;New features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Various patterns related to dependencies, such as ?depends are now available (2.1.16)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Protected&lt;/code&gt; field is now supported.
It replaces the previous &lt;code&gt;Important&lt;/code&gt; field and is like Essential,
but only for installed packages
(some minor more differences maybe in terms of ordering the installs).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;update&lt;/code&gt; command has gained an &lt;code&gt;--error-on=any&lt;/code&gt; option that makes it error out on any failure,
not just what it considers persistent ons.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;rred&lt;/code&gt; method can now be used as a standalone program to merge pdiff files&lt;/li&gt;
&lt;li&gt;APT now implements &lt;a href=&#34;https://wiki.ubuntu.com/PhasedUpdates&#34;&gt;phased updates&lt;/a&gt;.
Phasing is used in Ubuntu to slow down and control the roll out of updates in the -updates pocket,
but has previously only been available to desktop users using update-manager.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;other-behavioral-changes&#34;&gt;Other behavioral changes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The kernel autoremoval helper code has been rewritten from shell in C++ and now runs at run-time,
rather than at kernel install time,
in order to correctly protect the kernel that is running now,
rather than the kernel that was running when we were installing the newest one.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>APT 2.2.0 marks the freeze of the 2.1 development series and the start of the 2.2 stable series.</p>
<p>Let&rsquo;s have a look at what changed compared to 2.2. Many of you who run Debian testing or unstable,
or Ubuntu groovy or hirsute will already have seen most of those changes.</p>
<h2 id="new-features">New features</h2>
<ul>
<li>Various patterns related to dependencies, such as ?depends are now available (2.1.16)</li>
<li>The <code>Protected</code> field is now supported.
It replaces the previous <code>Important</code> field and is like Essential,
but only for installed packages
(some minor more differences maybe in terms of ordering the installs).</li>
<li>The <code>update</code> command has gained an <code>--error-on=any</code> option that makes it error out on any failure,
not just what it considers persistent ons.</li>
<li>The <code>rred</code> method can now be used as a standalone program to merge pdiff files</li>
<li>APT now implements <a href="https://wiki.ubuntu.com/PhasedUpdates">phased updates</a>.
Phasing is used in Ubuntu to slow down and control the roll out of updates in the -updates pocket,
but has previously only been available to desktop users using update-manager.</li>
</ul>
<h2 id="other-behavioral-changes">Other behavioral changes</h2>
<ul>
<li>
<p>The kernel autoremoval helper code has been rewritten from shell in C++ and now runs at run-time,
rather than at kernel install time,
in order to correctly protect the kernel that is running now,
rather than the kernel that was running when we were installing the newest one.</p>
<p>It also now protects only up to 3 kernels, instead of up to 4, as was originally intended,
and was the case before 1.1 series.
This avoids /boot partitions from running out of space, especially on Ubuntu which has boot
partitions sized for the original spec.</p>
</li>
</ul>
<h2 id="performance-improvements">Performance improvements</h2>
<ul>
<li>The cache is now hashed using XXH3 instead of Adler32 (or CRC32c on SSE4.2 platforms)</li>
<li>The hash table size has been increased</li>
</ul>
<h2 id="bug-fixes">Bug fixes</h2>
<ul>
<li><code>*</code> wildcards work normally again (since 2.1.0)</li>
<li>The cache file now includes all translation files in /var/lib/apt/lists,
so multi-user systems with different locales correctly show translated descriptions now.</li>
<li>URLs are no longer dequoted on redirects only to be requoted again,
fixing some redirects where servers did not expect different quoting.</li>
<li>Immediate configuration is now best-effort, and failure is no longer fatal.</li>
<li>various changes to solver marking leading to different/better results in some cases (since 2.1.0)</li>
<li>The lower level I/O bits of the HTTP method have been rewritten to hopefully improve stability</li>
<li>The HTTP method no longer infinitely retries downloads on some connection errors</li>
<li>The pkgnames command no longer accidentally includes source packages</li>
<li>Various fixes from fuzzing efforts by David</li>
</ul>
<h2 id="security-fixes">Security fixes</h2>
<ul>
<li>Out-of-bound reads in ar and tar implementations (CVE-2020-3810, 2.1.2)</li>
<li>Integer overflows in ar and tar (CVE-2020-27350, 2.1.13)</li>
</ul>
<p>(all of which have been backported to all stable series,
back all the way to 1.0.9.8.* series in jessie eLTS)</p>
<h2 id="incompatibilities">Incompatibilities</h2>
<ul>
<li>N/A - there were no breaking changes in apt 2.2 that we are aware of.</li>
</ul>
<h2 id="deprecations">Deprecations</h2>
<ul>
<li>
<p><code>apt-key(1)</code> is scheduled to be removed for Q2/2022, and several new warnings have been added.</p>
<p>apt-key was made obsolete in version 0.7.25.1, released in January 2010, by
<code>/etc/apt/trusted.gpg.d</code> becoming a supported place to drop additional keyring files,
and was since then only intended for deleting keys in the legacy <code>trusted.gpg</code> keyring.</p>
<p>Please manage files in <code>trusted.gpg.d</code> yourself;
or place them in a different location such as
<code>/etc/apt/keyrings</code> (or make up your own, there&rsquo;s no standard location)
or <code>/usr/share/keyrings</code>,
and use signed-by in the sources.list.d files.</p>
<p>The legacy <code>trusted.gpg</code> keyring still works, but will also stop working eventually.
Please make sure you have all your keys in <code>trusted.gpg.d</code>.
Warnings might be added in the upcoming months when a signature could not be verified using just trusted.gpg.d.</p>
<p>Future versions of APT might <a href="https://wiki.debian.org/Teams/Apt/Spec/AptSign">switch away from GPG</a>.</p>
</li>
<li>
<p>As a reminder, regular expressions and wildcards other than <code>*</code> inside package names are deprecated (since 2.0).
They are not available anymore in apt(8), and will be removed for safety reasons in apt-get in a later release.</p>
</li>
</ul>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Google Pixel 4a: Initial Impressions</title>
      <link>https://blog.jak-linux.org/2020/10/03/pixel4a-initial-impressions/</link>
      <pubDate>Sat, 03 Oct 2020 13:16:02 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2020/10/03/pixel4a-initial-impressions/</guid>
      <description>&lt;p&gt;Yesterday I got a fresh new Pixel 4a, to replace my dying OnePlus 6.
The OnePlus had developed some faults over time: It repeatedly loses connection to the AP and the network, and it got a bunch of scratches and scuffs from falling on various surfaces without any protection over the past year.&lt;/p&gt;
&lt;h2 id=&#34;why-get-a-pixel&#34;&gt;Why get a Pixel?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Camera&lt;/strong&gt;: OnePlus focuses on stuffing as many sensors as it can into a phone, rather than a good main sensor, resulting in pictures that are mediocre blurry messes - the dreaded oil painting effect.
Pixel have some of the best camera in the smartphone world. Sure, other hardware is far more capable, but the Pixels manage consistent results, so you need to take less pictures because they don&amp;rsquo;t come out blurry half the time, and the post processing is so good that the pictures you get are just great. Other phones can shoot better pictures, sure - on a tripod.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Yesterday I got a fresh new Pixel 4a, to replace my dying OnePlus 6.
The OnePlus had developed some faults over time: It repeatedly loses connection to the AP and the network, and it got a bunch of scratches and scuffs from falling on various surfaces without any protection over the past year.</p>
<h2 id="why-get-a-pixel">Why get a Pixel?</h2>
<p><strong>Camera</strong>: OnePlus focuses on stuffing as many sensors as it can into a phone, rather than a good main sensor, resulting in pictures that are mediocre blurry messes - the dreaded oil painting effect.
Pixel have some of the best camera in the smartphone world. Sure, other hardware is far more capable, but the Pixels manage consistent results, so you need to take less pictures because they don&rsquo;t come out blurry half the time, and the post processing is so good that the pictures you get are just great. Other phones can shoot better pictures, sure - on a tripod.</p>
<p><strong>Security updates</strong>: Pixels provide 3 years of monthly updates, with security updates being published on the 5th of each month. OnePlus only provides updates every 2 months, and then the updates they do release are almost a month out of date, not counting that they are only 1st-of-month patches, meaning vendor blob updates included in the 5th-of-month updates are even a month older. Given that all my banking runs on the phone, I don&rsquo;t want it to be constantly behind.</p>
<p><strong>Feature updates</strong>: Of course, Pixels also get Beta Android releases and the newest Android release faster than any other phone, which is advantageous for Android development and being nerdy.</p>
<p><strong>Size and weight</strong>: OnePlus phones keep getting bigger and bigger. By today&rsquo;s standards, the OnePlus 6 at 6.18&quot; and 177g is a small an lightweight device. Their latest phone, the Nord, has 6.44&quot; and weighs 184g, the OnePlus 8 comes in at 180g with a 6.55&quot; display. This is becoming unwieldy. Eschewing glass and aluminium for plastic, the Pixel 4a comes in at 144g.</p>
<h2 id="first-impressions">First impressions</h2>
<h3 id="accessories">Accessories</h3>
<p>The Pixel 4a comes in a small box with a charger, USB-C to USB-C cable, a USB-OTG adapter, sim tray ejector. No pre-installed screen protector or bumper are provided, as we&rsquo;ve grown accustomed to from Chinese manufacturers like OnePlus or Xiaomi. The sim tray ejector has a circular end instead of the standard oval one - I assume so it looks like the &lsquo;o&rsquo; in Google?</p>
<p>Google sells you fabric cases for 45€. That seems a bit excessive, although I like that a lot of it is recycled.</p>
<h3 id="haptics">Haptics</h3>
<p>Coming from a 6.18&quot; phablet, the Pixel 4a with its 5.81&quot; feels tiny. In fact, it&rsquo;s so tiny my thumb and my index finger can touch while holding it. Cute! Bezels are a bit bigger, resulting in slightly less screen to body. The bottom chin is probably impracticably small, this was already a problem on the OnePlus 6, but this one is even smaller. Oh well, form over function.</p>
<p>The buttons on the side are very loud and clicky. As is the vibration motor. I wonder if this Pixel thinks it&rsquo;s a Model M. It just feels great.</p>
<p>The plastic back feels really good, it&rsquo;s that sort of high quality smooth plastic you used to see on those high-end Nokia devices.</p>
<p>The finger print reader, is super fast. Setup just takes a few seconds per finger, and it works reliably. Other phones (OnePlus 6, Mi A1/A2) take like half a minute or a minute to set up.</p>
<h3 id="software">Software</h3>
<p>The software - stock Android 11 - is fairly similar to OnePlus&rsquo; OxygenOS. It&rsquo;s a clean experience, without a ton of added bloatware (even OnePlus now ships Facebook out of box, eww). It&rsquo;s cleaner than OxygenOS in some way - there are no duplicate photos apps, for example. On the other hand, it also has quite a bunch of Google stuff I could not care less about like YT Music. To be fair, those are minor noise once all 130 apps were transferred from the old phone.</p>
<p>There are various things I miss coming from OnePlus such as off-screen gestures, network transfer rate indicator in quick settings, or a circular battery icon. But the Pixel has an always on display, which is kind of nice. Most of the cool Pixel features, like call screening or live transcriptions are unfortunately not available in Germany.</p>
<p>The display is set to display the same amount of content as my 6.18&quot; OnePlus 6 did, so everything is a bit tinier. This usually takes me a week or two to adjust too, and then when I look at the OnePlus again I&rsquo;ll be like &ldquo;Oh the font is huge&rdquo;, but right now, it feels a bit small on the Pixel.</p>
<p>You can configure three colour profiles for the Pixel 4a: Natural, Boosted, and Adaptive. I have mine set to adaptive. I&rsquo;d love to see stock Android learn what OnePlus has here: the ability to adjust the colour temperature manually, as I prefer to keep my devices closer to 5500K than 6500K, as I feel it&rsquo;s a bit easier on the eyes. Or well, just give me the ability to load a ICM profile (though, I&rsquo;d need to calibrate the screen then - work!).</p>
<h3 id="migration-experience">Migration experience</h3>
<p>Restoring the apps from my old phone only restore settings for a few handful out of 130, which is disappointing. I had to spent an hour or two logging in to all the other apps, and I had to fiddle far too long with openScale to get it to take its data over. It&rsquo;s a mystery to me why people do not allow their apps to be backed up, especially something innocent like a weight tracking app. One of my banking apps restored its logins, which I did not really like. KeePass2Android settings were restored as well, but at least the key file was not restored.</p>
<p>I did not opt in to restoring my device settings, as I feel that restoring device settings when changing manufactures is bound to mess up some things. For example, I remember people migrating to OnePlus phones and getting their old DND schedule without any way to change it, because OnePlus had hidden the DND stuff. I assume that&rsquo;s the reason some accounts, like my work GSuite account were not migrated (it said it would migrate accounts during setup).</p>
<p>I&rsquo;ve setup Bitwarden as my auto-fill service, so I could login into most of my apps and websites using the stored credentials. I found that often that did not work. Like Chrome does autofill fine once, but if I then want to autofill again, I have to kill and restart it, otherwise I don&rsquo;t get the auto-fill menu. Other apps did not allow any auto-fill at all, and only gave me the option to copy and paste. Yikes - auto-fill on Android still needs a lot of work.</p>
<h3 id="performance">Performance</h3>
<p>It hangs a bit sometimes, but this was likely due to me having set 2 million iterations on my Bitwarden KDF and using Bitwarden a lot, and then opening up all 130 apps to log into them which overwhelmed the phone a bit. Apart from that, it does not feel worse than the OnePlus 6 which was to be expected, given that the benchmarks only show a slight loss in performance.</p>
<p>Photos do take a few seconds to process after taking them, which is annoying, but understandable given how much Google relies on computation to provide decent pictures.</p>
<h3 id="audio">Audio</h3>
<p>The Pixel has dual speakers, with the earpiece delivering a tiny sound and the bottom firing speaker doing most of the work. Still, it&rsquo;s better than just having the bottom firing speaker, as it does provide a more immersive experience. Bass makes this thing vibrate a lot. It does not feel like a resonance sort of thing, but you can feel the bass in your hands. I&rsquo;ve never had this before, and it will take some time getting used to.</p>
<h2 id="final-thoughts">Final thoughts</h2>
<p>This is a boring phone. There&rsquo;s no wow factor at all. It&rsquo;s neither huge, nor does it have high-res 48 or 64 MP cameras, nor does it have a ton of sensors. But everything it does, it does well. It does not pretend to be a flagship like its competition, it doesn&rsquo;t want to wow you, it just wants to be the perfect phone for you. The build is solid, the buttons make you think of a Model M, the camera is one of the best in any smartphone, and you of course get the latest updates before anyone else. It does not feel like a &ldquo;only 350€&rdquo; phone, but yet it is. 128GB storage is plenty, 1080p resolution is plenty, 12.2MP is &hellip; you guessed it, plenty.</p>
<p>The same applies to the other two Pixel phones - the 4a 5G and 5. Neither are particularly exciting phones, and I personally find it hard to justify spending 620€ on the Pixel 5 when the Pixel 4a does job for me, but the 4a 5G might appeal to users looking for larger phones. As to 5G, I wouldn&rsquo;t get much use out of it, seeing as its not available anywhere I am. Because I&rsquo;m on Vodafone. If you have a Telekom contract or live outside of Germany, you might just have good 5G coverage already and it might make sense to get a 5G phone rather than sticking to the budget choice.</p>
<h2 id="outlook">Outlook</h2>
<p>The big question for me is whether I&rsquo;ll be able to adjust to the smaller display. I now have a tablet, so I&rsquo;m less often using the phone (which my hands thank me for), which means that a smaller phone is probably a good call.</p>
<p>Oh while we&rsquo;re talking about calls - I only have a data-only SIM in it, so I could not test calling. I&rsquo;m transferring to a new phone contract this month, and I&rsquo;ll give it a go then. This will be the first time I get VoLTE and WiFi calling, although it is Vodafone, so quality might just be worse than Telekom on 2G, who knows. A big shoutout to congstar for letting me cancel with a simple button click, and to @vodafoneservice on twitter for quickly setting up my benefits of additional 5GB per month and 10€ discount for being an existing cable customer.</p>
<p>I&rsquo;m also looking forward to playing around with the camera (especially night sight), and eSIM. And I&rsquo;m getting a case from China, which was handed over to the Airline on Sep 17 according to Aliexpress, so I guess it should arrive in the next weeks. Oh, and screen protector is not here yet, so I can&rsquo;t really judge the screen quality much, as I still have the factory protection film on it, and that&rsquo;s just a blurry mess - but good enough for setting it up. Please Google, pre-apply a screen protector on future phones and include a simple bumper case.</p>
<p>I might report back in two weeks when I have spent some more time with the device.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Review: Chromebook Duet</title>
      <link>https://blog.jak-linux.org/2020/06/09/review-chromebook-duet/</link>
      <pubDate>Tue, 09 Jun 2020 21:23:59 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2020/06/09/review-chromebook-duet/</guid>
      <description>&lt;p&gt;Sporting a beautiful 10.1&amp;quot; 1920x1200 display, the Lenovo IdeaPad Duet
Chromebook or Duet Chromebook, is one of the latest Chromebooks released,
and one of the few slate-style tablets, and it&amp;rsquo;s only about 300 EUR (300 USD).
I&amp;rsquo;ve had one for about 2 weeks now, and here are my thoughts.&lt;/p&gt;
&lt;h2 id=&#34;build--accessories&#34;&gt;Build &amp;amp; Accessories&lt;/h2&gt;
&lt;p&gt;The tablet is a fairly Pixel-style affair, in that the back has two components,
one softer blue one housing the camera and a metal feeling gray one. Build quality
is fairly good.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Sporting a beautiful 10.1&quot; 1920x1200 display, the Lenovo IdeaPad Duet
Chromebook or Duet Chromebook, is one of the latest Chromebooks released,
and one of the few slate-style tablets, and it&rsquo;s only about 300 EUR (300 USD).
I&rsquo;ve had one for about 2 weeks now, and here are my thoughts.</p>
<h2 id="build--accessories">Build &amp; Accessories</h2>
<p>The tablet is a fairly Pixel-style affair, in that the back has two components,
one softer blue one housing the camera and a metal feeling gray one. Build quality
is fairly good.</p>
<p>The volume and power buttons are located on the right side of the tablet, and
this is one of the main issues: You end up accidentally pressing the power button
when you want to turn your volume lower, despite the power button having a different
texture.</p>
<p>Alongside the tablet, you also find a kickstand with a textile back, and a
keyboard, both of which attach via magnets (and pogo pins for the keyboard).
The keyboard is crammed, with punctuation keys being halfed in size, and it
feels mushed compared to my usual experiences of ThinkPads and Model Ms, but
it&rsquo;s on par with other Chromebooks, which is surprising, given it&rsquo;s a tablet
attachment.</p>
<figure><img src="/2020/06/09/review-chromebook-duet/chromebook-duet-assembled.jpg"
    alt="fully assembled chromebook duet"><figcaption>
      <p>fully assembled chromebook duet</p>
    </figcaption>
</figure>

<p>I mostly use the Duet as a tablet, and only attach the keyboard occasionally.
Typing with the keyboard on your lap is suboptimal.</p>
<p>My first Duet had a few bunches of dead pixels, so I returned it, as I had
a second one I could not cancel ordered as well. Oh dear. That one was fine!</p>
<h2 id="hardware--connectivity">Hardware &amp; Connectivity</h2>
<p>The Chromebook Duet is powered by a Mediatek Helio P60T SoC, 4GB of RAM,
and a choice of 64 or 128 GB of main storage.</p>
<p>The tablet provides one USB-C port for charging, audio output (a 3.5mm adapter
is provided in the box), USB hub, and video output; though, sadly, the latter
is restricted to a maximum of 1080p30, or 1440x900 at 60 Hz. It can be charged
using the included 10W charger, or use up to I believe 18W from a higher powered
USB-C PD charger. I&rsquo;ve successfully used the Chromebook with a USB-C monitor
with attached keyboard, mouse, and DAC without any issues.</p>
<p>On the wireless side, the tablet provides 2x2 Wifi AC and Bluetooth 4.2. WiFi
reception seemed just fine, though I have not done any speed testing, missing
a sensible connection at the moment. I used Bluetooth to connect to my smartphone
for instant tethering, and my Sony WH1000XM2 headphones, both of which worked
without any issues.</p>
<p>The screen is a bright 400 nit display with excellent viewing angles,
and the speakers do a decent job, meaning you can use easily use this
for watching a movie when you&rsquo;re alone in a room and idling around. It has
a resolution of 1920x1200.</p>
<p>The device supports styluses following the USI standard. As of right now, the
only such stylus I know about is an HP one, and it costs about 70€ or so.</p>
<p>Cameras are provided on the front and the rear, but produce terrible images.</p>
<h2 id="software-the-tablet-experience">Software: The tablet experience</h2>
<p>The Chromebook Duet runs Chrome OS, and comes with access to Android apps
using the play store (and sideloading in dev mode) and access to full Linux
environments powered by LXD inside VMs.</p>
<p>The screen which has 1920x1200 is scaled to a ridiculous 1080x675 by default
which is good for being able to tap buttons and stuff, but provides next to no
content. Scaling it to 1350x844 makes things more balanced.</p>
<p>The Linux integration is buggy. Touches register in different places than where
they happened, and the screen is cut off in full screen extremetuxracer, making
it hard to recommend for such uses.</p>
<p>Android apps generally work fine. There are some issues with the back gesture
not registering, but otherwise I have not found issues I can remember.</p>
<p>One major drawback as a portable media consumption device is that Android apps
only work in Widevine level 3, and hence do not have access to HD content, and
the web apps of Netflix and co do not support downloading. Though one of the Duets
actually said L1 in check apps at some point (reported in <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1090330">issue 1090330</a>).
It&rsquo;s also worth
noting that Amazon Prime Video only renders in HD, unless you change your
user agent to say you are Chrome on Windows - bad Amazon!</p>
<p>The tablet experience also lags in some other ways, as the palm rejection is
overly extreme, causing it to reject valid clicks close to the edge of the display
(reported in <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1090326">issue 1090326</a>).</p>
<p>The on screen keyboard is terrible. It only does one language at a time, forcing
me to switch between German and English all the time, and does not behave as you&rsquo;d
expect it when editing existing words - it does not know about them and thinks
you are starting a new one. It does provide a small keyboard that you can
move around, as well as a draw your letters keyboard, which could come in
handy for stylus users, I guess. In any case, it&rsquo;s miles away from gboard on
Android.</p>
<p>Stability is a mixed bag right now. As of Chrome OS 83, sites (well only Disney+
so far&hellip;) sometimes get killed with SIGILL or SIGTRAP, and the device rebooted
on its own once or twice. Android apps that use the DRM sometimes do not start,
and the Netflix Android app sometimes reports it cannot connect to the servers.</p>
<h2 id="performance">Performance</h2>
<p>Performance is decent to sluggish, with micro stuttering in a lot of places. The
Mediatek CPU is comparable to Intel Atoms, and with only 4GB of RAM, and an entire
Android container running, it&rsquo;s starting to show how weak it is.</p>
<p>I found that Google Docs worked perfectly fine, as did websites such as
Mastodon, Twitter, Facebook. Where the device really struggled was Reddit,
where closing or opening a post, or getting a reply box could take 5 seconds
or more. If you are looking for a Reddit browsing device, this is not for you.
Performance in Netflix was fine, and Disney+ was fairly slow but still usable.</p>
<p>All in all, it&rsquo;s acceptable, and given the price point and the build quality,
probably the compromise you&rsquo;d expect.</p>
<h2 id="summary">Summary</h2>
<p>tl;dr:</p>
<ul>
<li>good: Build quality, bright screen, low price, included accessories</li>
<li>bad: DRM issues, performance, limited USB-C video output, charging speed, on-screen keyboard, software bugs</li>
</ul>
<p>The Chromebook Duet or IdeaPad Duet Chromebook is a decent tablet that is built
well above its price point. It&rsquo;s lackluster performance and DRM woes make it
hard to give a general recommendation, though. It&rsquo;s not a good laptop.</p>
<p>I can see this as the perfect note taking device for students, and as a
cheap tablet for couch surfing, or as your on-the-go laptop replacement,
if you need it only occasionally.</p>
<p>I cannot see anyone using this as their main laptop, although I guess some
people only have phones these days, so: what do I know?</p>
<p>I can see you getting this device if you want to tinker with Linux on ARM, as
Chromebooks are quite nice to tinker with, and a tablet is super nice.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>An - EPYC - Focal Upgrade</title>
      <link>https://blog.jak-linux.org/2020/04/25/an-epyc-focal-upgrade/</link>
      <pubDate>Sat, 25 Apr 2020 21:28:04 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2020/04/25/an-epyc-focal-upgrade/</guid>
      <description>&lt;p&gt;Ubuntu &amp;ldquo;Focal Fossa&amp;rdquo; 20.04 was released two days ago, so I took the opportunity yesterday
and this morning to upgrade my VPS from Ubuntu 18.04 to 20.04. The VPS provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SMTP via Postfix&lt;/li&gt;
&lt;li&gt;Spam filtering via rspamd&lt;/li&gt;
&lt;li&gt;HTTP(S) via nginx and letsencrypt (certbot)&lt;/li&gt;
&lt;li&gt;Weechat relay&lt;/li&gt;
&lt;li&gt;OpenVPN server&lt;/li&gt;
&lt;li&gt;Shadowsocks proxy&lt;/li&gt;
&lt;li&gt;Unbound recursive DNS resolver, for the spam filtering&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I rebooted one more time than necessary, though, as my cloud provider
&lt;a href=&#34;https://www.hetzner.de/cloud&#34;&gt;Hetzner&lt;/a&gt;
recently started offering 2nd generation EPYC instances which I upgraded to
from my Skylake Xeon based instance. I switched from the CX21 for 5.83€/mo
to the CPX11 for 4.15€/mo. This involved a RAM downgrade - from 4GB to 2GB,
but that&amp;rsquo;s fine, the maximum usage I saw was about 1.3 GB when running
dose-distcheck (running hourly); and it&amp;rsquo;s good for everyone that AMD is
giving Intel some good competition, I think.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Ubuntu &ldquo;Focal Fossa&rdquo; 20.04 was released two days ago, so I took the opportunity yesterday
and this morning to upgrade my VPS from Ubuntu 18.04 to 20.04. The VPS provides:</p>
<ul>
<li>SMTP via Postfix</li>
<li>Spam filtering via rspamd</li>
<li>HTTP(S) via nginx and letsencrypt (certbot)</li>
<li>Weechat relay</li>
<li>OpenVPN server</li>
<li>Shadowsocks proxy</li>
<li>Unbound recursive DNS resolver, for the spam filtering</li>
</ul>
<p>I rebooted one more time than necessary, though, as my cloud provider
<a href="https://www.hetzner.de/cloud">Hetzner</a>
recently started offering 2nd generation EPYC instances which I upgraded to
from my Skylake Xeon based instance. I switched from the CX21 for 5.83€/mo
to the CPX11 for 4.15€/mo. This involved a RAM downgrade - from 4GB to 2GB,
but that&rsquo;s fine, the maximum usage I saw was about 1.3 GB when running
dose-distcheck (running hourly); and it&rsquo;s good for everyone that AMD is
giving Intel some good competition, I think.</p>
<p>Anyway, to get back to the distribution upgrade - it was fairly boring. I
started yesterday by taking a copy of the server and launching it locally
in a lxd container, and then tested the upgrade in there; to make sure I&rsquo;m
prepared for the real thing :)</p>
<p>I got a confusing prompt from postfix as to which site I&rsquo;m operating
(which is a normal prompt, but I don&rsquo;t know why I see it on an upgrade);
and a few config files I had changed locally.</p>
<p>As the server is managed by ansible, I just installed the distribution
config files and dropped my changes (setting <code>DPkg::Options { &quot;--force-confnew&quot;; };&quot;</code> in apt.conf),
and then after the upgrade, ran ansible to redeploy the changes (after checking
what changes it would do and adjusting a few things).</p>
<p>There are two remaining flaws:</p>
<ol>
<li>
<p>I run rspamd from the upstream repository, and that&rsquo;s not built for focal
yet. So I&rsquo;m still using the bionic binary, and have to keep bionic&rsquo;s icu 60
and libhyperscan4 around for it.</p>
<p>This is still preventing CI of the ansible config from passing for focal,
because it won&rsquo;t have the needed bionic packages around.</p>
</li>
<li>
<p>I run weechat from the upstream repository, and apt can&rsquo;t tell the versions
apart. Well, it can for the repositories, because they have <code>Size</code> fields -
but <code>status</code> does not. Hence, it merges the installed version with the
first repository it sees.</p>
<p>What happens is that it installs from weechat.org, but then it believes the installed version
is from archive.ubuntu.com and replaces it each dist-upgrade.</p>
<p>I worked around it by moving the weechat.org repo to the front of sources.list,
so that the it gets merged with that instead of the archive.ubuntu.com one, as
it should be, but that&rsquo;s a bit ugly.</p>
</li>
</ol>
<p>I also should start the migration to EC certificates for TLS, and 0-RTT handshakes,
so that the initial visit experience is faster. I guess I&rsquo;ll have to move away
from certbot for that, but I have not investigated this recently.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>APT 2.0 released</title>
      <link>https://blog.jak-linux.org/2020/03/07/apt-2.0/</link>
      <pubDate>Sat, 07 Mar 2020 21:43:01 +0100</pubDate>
      
      <guid>https://blog.jak-linux.org/2020/03/07/apt-2.0/</guid>
      <description>&lt;p&gt;After brewing in experimental for a while, and getting a first outing in
the Ubuntu 19.10 release; both as 1.9, APT 2.0 is now landing in unstable.
1.10 would be a boring, weird number, eh?&lt;/p&gt;
&lt;p&gt;Compared to the 1.8 series, the APT 2.0 series features several new features,
as well as improvements in performance, hardening. A lot of code has been
removed as well, reducing the size of the library.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>After brewing in experimental for a while, and getting a first outing in
the Ubuntu 19.10 release; both as 1.9, APT 2.0 is now landing in unstable.
1.10 would be a boring, weird number, eh?</p>
<p>Compared to the 1.8 series, the APT 2.0 series features several new features,
as well as improvements in performance, hardening. A lot of code has been
removed as well, reducing the size of the library.</p>
<h2 id="highlighted-changes-since-18">Highlighted Changes Since 1.8</h2>
<h3 id="new-features">New Features</h3>
<ul>
<li>
<p>Commands accepting package names now accept aptitude-style patterns. The
syntax of patterns is mostly a subset of aptitude, see <code>apt-patterns(7)</code> for
more details.</p>
</li>
<li>
<p><code>apt(8)</code> now waits for the dpkg locks - indefinitely, when connected
to a tty, or for 120s otherwise.</p>
</li>
<li>
<p>When apt cannot acquire the lock, it prints the name and pid of the process
that currently holds the lock.</p>
</li>
<li>
<p>A new <code>satisfy</code> command has been added to <code>apt(8)</code> and <code>apt-get(8)</code></p>
</li>
<li>
<p>Pins can now be specified by source package, by prepending <code>src:</code> to the
name of the package, e.g.:</p>
<pre><code>Package: src:apt
Pin: version 2.0.0
Pin-Priority: 990
</code></pre>
<p>Will pin all binaries of the native architecture produced by the source
package <code>apt</code> to version 2.0.0. To pin packages across all architectures,
append <code>:any</code>.</p>
</li>
</ul>
<h3 id="performance">Performance</h3>
<ul>
<li>
<p>APT now uses libgcrypt for hashing instead of embedded reference
implementations of MD5, SHA1, and SHA2 hash families.</p>
</li>
<li>
<p>Distribution of rred and decompression work during update has been
improved to take into account the backlog instead of randomly
assigning a worker, which should yield higher parallelization.</p>
</li>
</ul>
<h3 id="incompatibilities">Incompatibilities</h3>
<ul>
<li>The apt(8) command no longer accepts regular expressions or wildcards as
package arguments, use patterns (see New Features).</li>
</ul>
<h3 id="hardening">Hardening</h3>
<ul>
<li>Credentials specified in auth.conf now only apply to HTTPS sources,
preventing malicious actors from reading credentials after they redirected
users from a  HTTP source to an http url matching the credentials in
auth.conf. Another protocol can be specified, see apt_auth.conf(5) for
the syntax.</li>
</ul>
<h3 id="developer-changes">Developer changes</h3>
<ul>
<li>
<p>A more extensible cache format, allowing us to add new fields without
breaking the ABI</p>
</li>
<li>
<p>All code marked as deprecated in 1.8 has been removed</p>
</li>
<li>
<p>Implementations of CRC16, MD5, SHA1, SHA2 have been removed</p>
</li>
<li>
<p>The apt-inst library has been merged into the apt-pkg library.</p>
</li>
<li>
<p>apt-pkg can now be found by pkg-config</p>
</li>
<li>
<p>The apt-pkg library now compiles with hidden visibility by default.</p>
</li>
<li>
<p>Pointers inside the cache are now statically typed. They cannot be
compared against integers (except 0 via nullptr) anymore.</p>
</li>
</ul>
<h3 id="python-apt-20">python-apt 2.0</h3>
<p>python-apt 2.0 is not yet ready, I&rsquo;m hoping to add a new cleaner
API for cache access before making the jump from 1.9 to 2.0 versioning.</p>
<h3 id="libept-12">libept 1.2</h3>
<p>I&rsquo;ve moved the maintenance of libept to the APT team. We need to investigate
how to EOL this properly and provide facilities inside APT itself to
replace it. There are no plans to provide new features, only bugfixes
/ rebuilds for new apt versions.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>APT Patterns</title>
      <link>https://blog.jak-linux.org/2019/08/15/apt-patterns/</link>
      <pubDate>Thu, 15 Aug 2019 15:55:47 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2019/08/15/apt-patterns/</guid>
      <description>&lt;p&gt;If you have ever used aptitude a bit more extensively on the command-line, you&amp;rsquo;ll probably have come across its patterns. This week I spent some time implementing (some) patterns for apt, so you do not need aptitude for that, and I want to let you in on the details of this &lt;a href=&#34;https://salsa.debian.org/apt-team/apt/merge_requests/74&#34;&gt;merge request !74&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;so-what-are-patterns&#34;&gt;so, what are patterns?&lt;/h2&gt;
&lt;p&gt;Patterns allow you to specify complex search queries to select the packages you want to install/show.
For example, the pattern &lt;code&gt;?garbage&lt;/code&gt; can be used to find all packages that have been automatically installed but are no longer depended upon by manually installed packages.
Or the pattern &lt;code&gt;?automatic&lt;/code&gt; allows you find all automatically installed packages.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>If you have ever used aptitude a bit more extensively on the command-line, you&rsquo;ll probably have come across its patterns. This week I spent some time implementing (some) patterns for apt, so you do not need aptitude for that, and I want to let you in on the details of this <a href="https://salsa.debian.org/apt-team/apt/merge_requests/74">merge request !74</a>.</p>
<h2 id="so-what-are-patterns">so, what are patterns?</h2>
<p>Patterns allow you to specify complex search queries to select the packages you want to install/show.
For example, the pattern <code>?garbage</code> can be used to find all packages that have been automatically installed but are no longer depended upon by manually installed packages.
Or the pattern <code>?automatic</code> allows you find all automatically installed packages.</p>
<p>You can combine patterns into more complex ones; for example, <code>?and(?automatic,?obsolete)</code> matches all automatically installed packages that do not exist any longer in a repository.</p>
<p>There are also explicit targets, so you can perform queries like <code>?for x: ?depends(?recommends(x))</code>:
Find all packages <code>x</code> that depend on another package that recommends <code>x</code>.
I do not fully comprehend those yet - I did not manage to create a pattern that matches all manually installed packages that a meta-package depends upon. I am not sure it is possible.</p>
<h2 id="reducing-pattern-syntax">reducing pattern syntax</h2>
<p>aptitude&rsquo;s syntax for patterns is quite context-sensitive. If you have a pattern <code>?foo(?bar)</code> it can have two possible meanings:</p>
<ol>
<li>If <code>?foo</code> takes arguments (like <code>?depends</code> did), then <code>?bar</code> is the argument.</li>
<li>Otherwise, <code>?foo(?bar)</code> is equivalent to <code>?foo?bar</code> which is short for <code>?and(?foo,?bar)</code></li>
</ol>
<p>I find that very confusing.
So, when looking at implementing patterns in APT, I went for a different approach.
I first parse the pattern into a generic parse tree, without knowing anything about the semantics, and then I convert the parse tree into a <code>APT::CacheFilter::Matcher</code>, an object that can match against packages.</p>
<p>This is useful, because the syntactic structure of the pattern can be seen, without having to know which patterns have arguments and which do not - basically, for the parser <code>?foo</code> and <code>?foo()</code> are the same thing.
That said, the second pass knows whether a pattern accepts arguments or not and insists on you adding them if required and not having them if it does not accept any, to prevent you from confusing yourself.</p>
<p>aptitude also supports shortcuts. For example, you could write <code>~c</code> instead of config-files, or <code>~m</code> for automatic; then combine them like <code>~m~c</code> instead of using <code>?and</code>. I have not implemented these short patterns for now, focusing instead on getting the basic functionality working.</p>
<p>So in our example <code>?foo(?bar)</code> above, we can immediately dismiss parsing that as <code>?foo?bar</code>:</p>
<ol>
<li>we do not support concatenation instead of <code>?and</code>.</li>
<li>we automatically parse <code>(</code> as the argument list, no matter whether <code>?foo</code> supports arguments or not</li>
</ol>
<figure><img src="/2019/08/15/apt-patterns/parser-error.png"
    alt="apt not understanding invalid patterns"><figcaption>
      <p>apt not understanding invalid patterns</p>
    </figcaption>
</figure>

<h2 id="supported-syntax">Supported syntax</h2>
<p>At the moment, APT supports two kinds of patterns: Basic logic ones like <code>?and</code>, and patterns that apply to an entire package as opposed to a specific version.
This was done as a starting point for the merge, patterns for versions will come in the next round.</p>
<p>We also do not have any support for explicit search targets such as <code>?for x: ...</code> yet - as explained, I do not yet fully understand them, and hence do not want to commit on them.</p>
<p>The full list of the first round of patterns is below, helpfully converted from the <code>apt-patterns(7)</code> docbook to markdown by pandoc.</p>
<h3 id="logic-patterns">logic patterns</h3>
<p>These patterns provide the basic means to combine other patterns into
more complex expressions, as well as <code>?true</code> and <code>?false</code> patterns.</p>
<dl>
<dt><code>?and(PATTERN, PATTERN, ...)</code></dt>
<dd>
<p>Selects objects where all specified patterns match.</p>
</dd>
<dt><code>?false</code></dt>
<dd>
<p>Selects nothing.</p>
</dd>
<dt><code>?not(PATTERN)</code></dt>
<dd>
<p>Selects objects where PATTERN does not match.</p>
</dd>
<dt><code>?or(PATTERN, PATTERN, ...)</code></dt>
<dd>
<p>Selects objects where at least one of the specified patterns match.</p>
</dd>
<dt><code>?true</code></dt>
<dd>
<p>Selects all objects.</p>
</dd>
</dl>
<h3 id="package-patterns">package patterns</h3>
<p>These patterns select specific packages.</p>
<dl>
<dt><code>?architecture(WILDCARD)</code></dt>
<dd>
<p>Selects packages matching the specified architecture, which may
contain wildcards using any.</p>
</dd>
<dt><code>?automatic</code></dt>
<dd>
<p>Selects packages that were installed automatically.</p>
</dd>
<dt><code>?broken</code></dt>
<dd>
<p>Selects packages that have broken dependencies.</p>
</dd>
<dt><code>?config-files</code></dt>
<dd>
<p>Selects packages that are not fully installed, but have solely
residual configuration files left.</p>
</dd>
<dt><code>?essential</code></dt>
<dd>
<p>Selects packages that have Essential: yes set in their control file.</p>
</dd>
<dt><code>?exact-name(NAME)</code></dt>
<dd>
<p>Selects packages with the exact specified name.</p>
</dd>
<dt><code>?garbage</code></dt>
<dd>
<p>Selects packages that can be removed automatically.</p>
</dd>
<dt><code>?installed</code></dt>
<dd>
<p>Selects packages that are currently installed.</p>
</dd>
<dt><code>?name(REGEX)</code></dt>
<dd>
<p>Selects packages where the name matches the given regular
expression.</p>
</dd>
<dt><code>?obsolete</code></dt>
<dd>
<p>Selects packages that no longer exist in repositories.</p>
</dd>
<dt><code>?upgradable</code></dt>
<dd>
<p>Selects packages that can be upgraded (have a newer candidate).</p>
</dd>
<dt><code>?virtual</code></dt>
<dd>
<p>Selects all virtual packages; that is packages without a version.
These exist when they are referenced somewhere in the archive, for
example because something depends on that name.</p>
</dd>
</dl>
<h2 id="examples">examples</h2>
<dl>
<dt><code>apt remove ?garbage</code></dt>
<dd>
<p>Remove all packages that are automatically installed and no longer
needed - same as apt autoremove</p>
</dd>
<dt><code>apt purge ?config-files</code></dt>
<dd>
<p>Purge all packages that only have configuration files left</p>
</dd>
</dl>
<h2 id="oddities">oddities</h2>
<p>Some things are not yet where I want them:</p>
<ul>
<li><code>?architecture</code> does not support <code>all</code>, <code>native</code>, or <code>same</code></li>
<li><code>?installed</code> should match only the installed version of the package, not the entire package (that is what aptitude does, and it&rsquo;s a bit surprising that <code>?installed</code> implies a version and <code>?upgradable</code> does not)</li>
</ul>
<h2 id="the-future">the future</h2>
<p>Of course, I do want to add support for the missing version patterns and explicit search patterns. I might even add support for some of the short patterns, but no promises. Some of those explicit search patterns might have <em>slightly</em> different syntax, e.g. <code>?for(x, y)</code> instead of <code>?for x: y</code> in order to make the language more uniform and easier to parse.</p>
<p>Another thing I want to do ASAP is to disable fallback to regular expressions when specifying package names on the command-line: <code>apt install g++</code> should always look for a package called <code>g++</code>, and not for any package containing <code>g</code> (<code>g++</code> being a valid regex) when there is no <code>g++</code> package. I think continuing to allow regular expressions if they start with <code>^</code> or end with <code>$</code> is fine - that prevents any overlap with package names, and would avoid breaking most stuff.</p>
<p>There also is the fallback to <code>fnmatch()</code>: Currently, if apt cannot find a package with the specified name using the exact name or the regex, it would fall back to interpreting the argument as a <code>glob(7)</code> pattern. For example, <code>apt install apt*</code> would fallback to installing every package starting with <code>apt</code> if there is no package matching that as a regular expression. We can actually keep those in place, as the <code>glob(7)</code> syntax does not overlap with valid package names.</p>
<p>Maybe I should allow using <code>[]</code> instead of <code>()</code> so larger patterns become more readable, and/or some support for comments.</p>
<p>There are also plans for <em>AppStream</em> based patterns. This would allow you to use <code>apt install ?provides-mimetype(text/xml)</code> or <code>apt install ?provides-lib(libfoo.so.2)</code>. It&rsquo;s not entirely clear how to package this though, we probably don&rsquo;t want to have <code>libapt-pkg</code> depend directly on <code>libappstream</code>.</p>
<h2 id="feedback">feedback</h2>
<p>Talk to me on IRC, comment on the <a href="https://mastodon.social/@juliank/102622465371813752">Mastodon thread</a>, or send me an email if there&rsquo;s anything you think I&rsquo;m missing or should be looking at.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Encrypted Email Storage, or DIY ProtonMail</title>
      <link>https://blog.jak-linux.org/2019/06/13/encrypted-email-storage/</link>
      <pubDate>Thu, 13 Jun 2019 22:47:11 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2019/06/13/encrypted-email-storage/</guid>
      <description>&lt;p&gt;In the &lt;a href=&#34;https://blog.jak-linux.org/2019/01/05/setting-up-an-email-server-part1/&#34;&gt;previous post&lt;/a&gt; about setting up a
email server, I explained how I setup a forwarder using Postfix. This post will look at setting
up Dovecot to store emails (and provide IMAP and authentication) on the server using GPG encryption
to make sure intruders can&amp;rsquo;t read our precious data!&lt;/p&gt;
&lt;h2 id=&#34;architecture&#34;&gt;Architecture&lt;/h2&gt;
&lt;p&gt;The basic architecture chosen for encrypted storage is that every incoming email is delivered
to postfix via LMTP, and then postfix runs a sieve script that invokes a filter that encrypts the email with
PGP/MIME using a user-specific key, before processing it further. Or short:&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>In the <a href="https://blog.jak-linux.org/2019/01/05/setting-up-an-email-server-part1/">previous post</a> about setting up a
email server, I explained how I setup a forwarder using Postfix. This post will look at setting
up Dovecot to store emails (and provide IMAP and authentication) on the server using GPG encryption
to make sure intruders can&rsquo;t read our precious data!</p>
<h2 id="architecture">Architecture</h2>
<p>The basic architecture chosen for encrypted storage is that every incoming email is delivered
to postfix via LMTP, and then postfix runs a sieve script that invokes a filter that encrypts the email with
PGP/MIME using a user-specific key, before processing it further. Or short:</p>
<pre tabindex="0"><code>postfix --ltmp--&gt; dovecot --sieve--&gt; filter --&gt; gpg --&gt; inbox
</code></pre><p>Security analysis:
This means that the message will be on the system unencrypted as long as it is in a Postfix
queue. This further means that the message plain text should be recoverable for quite some
time after Postfix deleted it, by investigating in the file system. However, given enough time,
the probability of being able to recover the messages should reduce substantially. Not sure how
to improve this much.</p>
<p>And yes, if the email is already encrypted we&rsquo;re going to encrypt it a second time, because
we can nest encryption and signature as much as we want! Makes the code easier.</p>
<h2 id="encrypting-an-email-with-pgpmime">Encrypting an email with PGP/MIME</h2>
<p>PGP/MIME is a trivial way to encrypt an email. Basically, we take the entire email message,
armor-encrypt it with GPG, and stuff it into a multipart mime message with the same headers
as the second attachment; the first attachment is a control information.</p>
<p>Technically, this means that we keep headers twice, once encrypted and once decrypted. But
the advantage compared to doing it more like most normal clients is clear: The code is a lot
easier, and we can reverse the encryption and get back the original!</p>
<p>And when I say easy, I mean easy - the function to encrypt the email is just a few lines long:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python3" data-lang="python3"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">encrypt</span>(message: email<span style="color:#f92672">.</span>message<span style="color:#f92672">.</span>Message, recipients: typing<span style="color:#f92672">.</span>List[str]) <span style="color:#f92672">-&gt;</span> str:
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;Encrypt given message&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    encrypted_content <span style="color:#f92672">=</span> gnupg<span style="color:#f92672">.</span>GPG()<span style="color:#f92672">.</span>encrypt(message<span style="color:#f92672">.</span>as_string(), recipients)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> encrypted_content:
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">raise</span> <span style="color:#a6e22e">ValueError</span>(encrypted_content<span style="color:#f92672">.</span>status)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Build the parts</span>
</span></span><span style="display:flex;"><span>    enc <span style="color:#f92672">=</span> email<span style="color:#f92672">.</span>mime<span style="color:#f92672">.</span>application<span style="color:#f92672">.</span>MIMEApplication(
</span></span><span style="display:flex;"><span>        _data<span style="color:#f92672">=</span>str(encrypted_content)<span style="color:#f92672">.</span>encode(),
</span></span><span style="display:flex;"><span>        _subtype<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;octet-stream&#39;</span>,
</span></span><span style="display:flex;"><span>        _encoder<span style="color:#f92672">=</span>email<span style="color:#f92672">.</span>encoders<span style="color:#f92672">.</span>encode_7or8bit)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    control <span style="color:#f92672">=</span> email<span style="color:#f92672">.</span>mime<span style="color:#f92672">.</span>application<span style="color:#f92672">.</span>MIMEApplication(
</span></span><span style="display:flex;"><span>        _data<span style="color:#f92672">=</span><span style="color:#e6db74">b</span><span style="color:#e6db74">&#39;Version: 1</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#39;</span>,
</span></span><span style="display:flex;"><span>        _subtype<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;pgp-encrypted; name=&#34;msg.asc&#34;&#39;</span>,
</span></span><span style="display:flex;"><span>        _encoder<span style="color:#f92672">=</span>email<span style="color:#f92672">.</span>encoders<span style="color:#f92672">.</span>encode_7or8bit)
</span></span><span style="display:flex;"><span>    control[<span style="color:#e6db74">&#39;Content-Disposition&#39;</span>] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;inline; filename=&#34;msg.asc&#34;&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Put the parts together</span>
</span></span><span style="display:flex;"><span>    encmsg <span style="color:#f92672">=</span> email<span style="color:#f92672">.</span>mime<span style="color:#f92672">.</span>multipart<span style="color:#f92672">.</span>MIMEMultipart(
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#39;encrypted&#39;</span>,
</span></span><span style="display:flex;"><span>        protocol<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;application/pgp-encrypted&#39;</span>)
</span></span><span style="display:flex;"><span>    encmsg<span style="color:#f92672">.</span>attach(control)
</span></span><span style="display:flex;"><span>    encmsg<span style="color:#f92672">.</span>attach(enc)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Copy headers</span>
</span></span><span style="display:flex;"><span>    headers_not_to_override <span style="color:#f92672">=</span> {key<span style="color:#f92672">.</span>lower() <span style="color:#66d9ef">for</span> key <span style="color:#f92672">in</span> encmsg<span style="color:#f92672">.</span>keys()}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> key, value <span style="color:#f92672">in</span> message<span style="color:#f92672">.</span>items():
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> key<span style="color:#f92672">.</span>lower() <span style="color:#f92672">not</span> <span style="color:#f92672">in</span> headers_not_to_override:
</span></span><span style="display:flex;"><span>            encmsg[key] <span style="color:#f92672">=</span> value
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> encmsg<span style="color:#f92672">.</span>as_string()
</span></span></code></pre></div><p>Decypting the email is even easier: Just pass the entire thing
to GPG, it will decrypt the encrypted part, which, as mentioned,
contains the entire original email with all headers :)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python3" data-lang="python3"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">decrypt</span>(message: email<span style="color:#f92672">.</span>message<span style="color:#f92672">.</span>Message) <span style="color:#f92672">-&gt;</span> str:
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;Decrypt the given message&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> str(gnupg<span style="color:#f92672">.</span>GPG()<span style="color:#f92672">.</span>decrypt(message<span style="color:#f92672">.</span>as_string()))
</span></span></code></pre></div><p>(now, not sure if it&rsquo;s a feature that GPG.decrypt ignores any
unencrypted data in the input, but well, that&rsquo;s GPG for you).</p>
<p>Of course, if you don&rsquo;t actually need IMAP access, you could drop
PGP/MIME and just pipe emails through <code>gpg --encrypt --armor</code> before
dropping them <em>somewhere</em> on the filesystem, and then sync them via
ssh somehow (e.g. patching <code>maildirsync</code> to encrypt emails it uploads
to the server, and decrypting emails it downloads).</p>
<h3 id="pretty-easy-privacy-pp">Pretty Easy privacy (p≡p)</h3>
<p>Now, we <em>almost</em> have a file conforming to
<a href="https://tools.ietf.org/html/draft-marques-pep-email-02">draft-marques-pep-email-02</a>,
the Pretty Easy privacy (p≡p) format, version 2.
That format allows us to encrypt headers, thus preventing people from
snooping on our metadata!</p>
<p>Basically it relies on the fact that we have all the headers in the
inner (encrypted) message. To mark an email as conforming to that
format we just have to set the subject to p≡p and add a header describing
the format version:</p>
<pre tabindex="0"><code>       Subject: =?utf-8?Q?p=E2=89=A1p?=
       X-Pep-Version: 2.0
</code></pre><p>A client conforming to p≡p will, when seeing this email, read any
headers from the inner (encrypted) message.</p>
<p>We also might want to change the code to only copy a limited amount of
headers, instead of basically every header, but I&rsquo;m going to leave that
as an exercise for the reader.</p>
<h2 id="putting-it-together">Putting it together</h2>
<p>Assume we have a Postfix and a Dovecot configured, and a script
<code>gpgmymail</code> written using the function above, like this:</p>
<pre tabindex="0"><code>def main() -&gt; None:
    &#34;&#34;&#34;Program entry&#34;&#34;&#34;
    parser = argparse.ArgumentParser(
        description=&#34;Encrypt/Decrypt mail using GPG/MIME&#34;)
    parser.add_argument(&#39;-d&#39;, &#39;--decrypt&#39;, action=&#34;store_true&#34;,
                        help=&#34;Decrypt rather than encrypt&#34;)
    parser.add_argument(&#39;recipient&#39;, nargs=&#39;*&#39;,
                        help=&#34;key id or email of keys to encrypt for&#34;)
    args = parser.parse_args()
    msg = email.message_from_file(sys.stdin)

    if args.decrypt:
        sys.stdout.write(decrypt(msg))
    else:
        sys.stdout.write(encrypt(msg, args.recipient))


if __name__ == &#39;__main__&#39;:
    main()
</code></pre><p>(don&rsquo;t forget to add missing imports, or see the end of the blog
post for links to full source code)</p>
<p>Then, all we have to is edit our <code>.dovecot.sieve</code> to add</p>
<pre tabindex="0"><code>filter &#34;gpgmymail&#34; &#34;myemail@myserver.example&#34;;
</code></pre><p>and all incoming emails are automatically encrypted.</p>
<h2 id="outgoing-emails">Outgoing emails</h2>
<p>To handle outgoing emails, do not store them via IMAP, but instead
configure your client to add a <code>Bcc</code> to yourself, and then filter
that <em>somehow</em> in sieve. You probably want to set Bcc to something
like <code>myemail+sent@myserver.example</code>, and then filter on the detail
(the <code>sent</code>).</p>
<h2 id="encrypt-or-not-encrypt">Encrypt or not Encrypt?</h2>
<p>Now do you actually want to encrypt? The disadvantages are clear:</p>
<ul>
<li>
<p>Server-side search becomes useless, especially if you use p≡p with encrypted Subject.</p>
<p>Such a shame, you could have built your own GMail by writing a notmuch FTS plugin for dovecot!</p>
</li>
<li>
<p>You can&rsquo;t train your spam filter via IMAP, because the spam trainer won&rsquo;t be able
to decrypt the email it is supposed to learn from</p>
</li>
</ul>
<p>There are probably other things I have not thought about, so
let me know on mastodon, email, or IRC!</p>
<h2 id="more-source-code">More source code</h2>
<p>You can find the source code of the script, and the setup for
dovecot in my <a href="https://github.com/julian-klode/ansible.jak-linux.org/compare/dovecot">git repository</a>.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Setting up an email server, part 1: The Forwarder</title>
      <link>https://blog.jak-linux.org/2019/01/05/setting-up-an-email-server-part1/</link>
      <pubDate>Sat, 05 Jan 2019 16:34:29 +0100</pubDate>
      
      <guid>https://blog.jak-linux.org/2019/01/05/setting-up-an-email-server-part1/</guid>
      <description>&lt;p&gt;This week, I&amp;rsquo;ve been working on rolling out mail services on my server.
I started working on a mail server setup at the end of November, while the server was not yet in use, but only for about two days, and then let it rest.&lt;/p&gt;
&lt;p&gt;As my old shared hosting account expired on January 1, I had to move mail forwarding duties over to the new server.
Yes forwarding - I do plan to move hosting the actual email too, but at the moment it&amp;rsquo;s &amp;ldquo;just&amp;rdquo; forwarding to gmail.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>This week, I&rsquo;ve been working on rolling out mail services on my server.
I started working on a mail server setup at the end of November, while the server was not yet in use, but only for about two days, and then let it rest.</p>
<p>As my old shared hosting account expired on January 1, I had to move mail forwarding duties over to the new server.
Yes forwarding - I do plan to move hosting the actual email too, but at the moment it&rsquo;s &ldquo;just&rdquo; forwarding to gmail.</p>
<h2 id="the-software">The Software</h2>
<p>As you might know from the web server story, my server runs on Ubuntu 18.04.
I set up a mail server on this system using</p>
<ul>
<li><a href="http://www.postfix.org/">Postfix</a> for SMTP duties (warning, they oddly do not have an https page)</li>
<li><a href="https://rspamd.com/">rspamd</a> for spam filtering, and signing DKIM / ARC</li>
<li><a href="https://www.isc.org/downloads/bind/">bind9</a> for DNS resolving</li>
<li><a href="https://github.com/roehling/postsrsd">postsrsd</a> for SRS</li>
</ul>
<p>You might wonder why bind9 is in there.
It turns out that DNS blacklists used by spam filters block the caching DNS servers you usually use, so you have to use your own recursive DNS server.
Ubuntu offers you the choice between bind9 and dnsmasq in main, and it seems like bind9 is more appropriate here than dnsmasq.</p>
<h2 id="setting-up-postfix">Setting up postfix</h2>
<p>Most of the postfix configuration is fairly standard. So, let&rsquo;s skip TLS configuration and
outbound SMTP setups (this is email, and while they support TLS, it&rsquo;s all optional, so let&rsquo;s
not bother that much here).</p>
<p>The most important part is restrictions in <code>main.cf</code>.</p>
<p>First of all, relay restrictions prevent us from relaying emails to weird domains:</p>
<pre tabindex="0"><code># Relay Restrictions
smtpd_relay_restrictions = reject_non_fqdn_recipient reject_unknown_recipient_domain permit_mynetworks permit_sasl_authenticated defer_unauth_destination
</code></pre><p>We also only accept mails from hosts that know their own full qualified name:</p>
<pre tabindex="0"><code># Helo restrictions (hosts not having a proper fqdn)
smtpd_helo_required = yes
smtpd_helo_restrictions = permit_mynetworks reject_invalid_helo_hostname reject_non_fqdn_helo_hostname reject_unknown_helo_hostname
</code></pre><p>We also don&rsquo;t like clients (other servers) that send data too early, or
have an unknown hostname:</p>
<pre tabindex="0"><code>smtpd_data_restrictions = reject_unauth_pipelining
smtpd_client_restrictions = permit_mynetworks reject_unknown_client_hostname
</code></pre><p>I also set up a custom apparmor profile that&rsquo;s pretty lose, I plan to migrate to
the one in the apparmor git eventually but it needs more testing and some
cleanup.</p>
<h2 id="sender-rewriting-scheme">Sender rewriting scheme</h2>
<p>For SRS using postsrsd, we define the <code>SRS_DOMAIN</code> in <code>/etc/default/postsrsd</code> and
then configure postfix to talk to it:</p>
<pre tabindex="0"><code># Handle SRS for forwarding
recipient_canonical_maps = tcp:localhost:10002
recipient_canonical_classes= envelope_recipient,header_recipient

sender_canonical_maps = tcp:localhost:10001
sender_canonical_classes = envelope_sender
</code></pre><p>This has a minor issue that it also rewrites the <code>Return-Path</code> when it
delivers emails locally, but as I am only forwarding, I&rsquo;m worrying about
that later.</p>
<h2 id="rspamd-basics">rspamd basics</h2>
<p>rspamd is a great spam filtering system. It uses a small core written in C
and a bunch of Lua plugins, such as:</p>
<ul>
<li>IP score, which keeps track of how good a specific server was in the past</li>
<li>Replies, which can check whether an email is a reply to another one</li>
<li>DNS blacklisting</li>
<li>DKIM and ARC validation and signing</li>
<li>DMARC validation</li>
<li>SPF validation</li>
</ul>
<p>It also has a nice web UI:</p>
<p><figure><img src="/2019/01/05/setting-up-an-email-server-part1/rspamd-status.png"
    alt="rspamd web ui status"><figcaption>
      <p>rspamd web ui status</p>
    </figcaption>
</figure>

<figure><img src="/2019/01/05/setting-up-an-email-server-part1/rspamd-spam.png"
    alt="rspamd web ui investigating a spam message"><figcaption>
      <p>rspamd web ui investigating a spam message</p>
    </figcaption>
</figure>
</p>
<p>Setting up rspamd is quite easy. You basically just drop a bunch of configuration
overrides into <code>/etc/rspamd/local.d</code> and you&rsquo;re done. Heck, it mostly works out of
the box. There&rsquo;s a fancy <code>rspamadm configwizard</code> too.</p>
<p>What you do want for rspamd is a redis server. redis is needed in <a href="https://rspamd.com/doc/configuration/redis.html">many places</a>,
such as rate limiting, greylisting, dmarc, reply tracking, ip scoring, neural networks.</p>
<p>I made a few changes to the defaults:</p>
<ul>
<li>
<p>I enabled subject rewriting instead of adding headers, so spam mail subjects get <code>[SPAM]</code> prepended, in <code>local.d/actions.conf</code>:</p>
<pre tabindex="0"><code>reject = 15;
rewrite_subject = 6;
add_header = 6;
greylist = 4;
subject = &#34;[SPAM] %s&#34;;
</code></pre></li>
<li>
<p>I set <code>autolearn = true; </code> in <code>local.d/classifier-bayes.conf</code> to make it learn that an email that has
a score of at least 15 (those that are rejected) is spam, and emails with negative scores are ham.</p>
</li>
<li>
<p>I set <code>extended_spam_headers = true;</code> in <code>local.d/milter_headers.conf</code> to get a report from rspamd in the
header seeing the score and how the score came to be.</p>
</li>
</ul>
<h2 id="arc-setup">ARC setup</h2>
<p><a href="http://arc-spec.org/">ARC</a> is the &lsquo;Authenticated Received Chain&rsquo; and is currently a DMARC
working group work item. It allows forwarders / mailing lists to authenticate their forwarding
of the emails and the checks they have performed.</p>
<p>rspamd is capable of validating and signing emails with ARC, but I&rsquo;m not sure how much
influence ARC has on gmail at the moment, for example.</p>
<p>There are three parts to setting up ARC:</p>
<ol>
<li>Generate a DKIM key pair (use <code>rspamadm dkim_keygen</code>)</li>
<li>Setup rspamd to sign incoming emails using the private key</li>
<li>Add a DKIM <code>TXT</code> record for the public key. <code>rspamadm</code> helpfully tells you how it looks like.</li>
</ol>
<p>For step two, what we need to do is configure <code>local.d/arc.conf</code>. You can basically use the example
configuration from the <a href="https://rspamd.com/doc/modules/arc.html">rspamd page</a>, the key point for signing
incoming email is to specifiy <code>sign_incoming = true;</code> and <code>use_domain_sign_inbound = &quot;recipient&quot;;</code> (FWIW,
none of these options are documented, they are fairly new, and nobody updated the documentation for them).</p>
<p>My configuration looks like this at the moment:</p>
<pre tabindex="0"><code># If false, messages with empty envelope from are not signed
allow_envfrom_empty = true;
# If true, envelope/header domain mismatch is ignored
allow_hdrfrom_mismatch = true;
# If true, multiple from headers are allowed (but only first is used)
allow_hdrfrom_multiple = false;
# If true, username does not need to contain matching domain
allow_username_mismatch = false;
# If false, messages from authenticated users are not selected for signing
auth_only = true;
# Default path to key, can include &#39;$domain&#39; and &#39;$selector&#39; variables
path = &#34;${DBDIR}/arc/$domain.$selector.key&#34;;
# Default selector to use
selector = &#34;arc&#34;;
# If false, messages from local networks are not selected for signing
sign_local = true;
#
sign_inbound = true;
# Symbol to add when message is signed
symbol_signed = &#34;ARC_SIGNED&#34;;
# Whether to fallback to global config
try_fallback = true;
# Domain to use for ARC signing: can be &#34;header&#34; or &#34;envelope&#34;
use_domain = &#34;header&#34;;
use_domain_sign_inbound = &#34;recipient&#34;;
# Whether to normalise domains to eSLD
use_esld = true;
# Whether to get keys from Redis
use_redis = false;
# Hash for ARC keys in Redis
key_prefix = &#34;ARC_KEYS&#34;;
</code></pre><p>This would also sign any outgoing email, but I&rsquo;m not sure that&rsquo;s necessary - my understanding
is that we only care about ARC when forwarding/receiving incoming emails, not when sending them
(at least that&rsquo;s what gmail does).</p>
<h2 id="other-issues">Other Issues</h2>
<p>There are few other things to keep in mind when running your own mail server. I probably
don&rsquo;t know them all yet, but here we go:</p>
<ul>
<li>
<p>You must have a fully qualified hostname resolving to a public IP address</p>
</li>
<li>
<p>Your public IP address must resolve back to the fully qualified host name</p>
</li>
<li>
<p>Again, you should run a recursive DNS resolver so your DNS blacklists work (thanks waldi for pointing that out)</p>
</li>
<li>
<p>Setup an SPF record. Mine looks like this:</p>
<p><code>jak-linux.org.                  3600  IN  TXT     &quot;v=spf1 +mx ~all&quot;</code></p>
<p>this states that all my mail servers may send email, but others probably
should not (a softfail). Not having an SPF record can punish you; for example,
rspamd gives missing SPF and DKIM a score of 1.</p>
</li>
<li>
<p>All of that software is sandboxed using AppArmor. Makes you question its security a bit less!</p>
</li>
</ul>
<h2 id="source-code-outlook">Source code, outlook</h2>
<p>As always, you can find the Ansible roles on <a href="https://github.com/julian-klode/ansible.jak-linux.org">GitHub</a>.
Feel free to point out bugs! 😉</p>
<p>In the next installment of this series, we will be looking at setting up Dovecot, and
configuring DKIM. We probably also want to figure out how to run notmuch
on the server, keep messages in matching maildirs, and have my laptop
synchronize the maildir and notmuch state with the server. Ugh, sounds
like a lot of work.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>An Introduction to Go</title>
      <link>https://blog.jak-linux.org/2018/12/24/introduction-to-go/</link>
      <pubDate>Mon, 24 Dec 2018 15:15:29 +0100</pubDate>
      
      <guid>https://blog.jak-linux.org/2018/12/24/introduction-to-go/</guid>
      <description>&lt;p&gt;(What follows is an excerpt from my master&amp;rsquo;s thesis, almost all of section
2.1, quickly introducing Go to people familiar with CS)&lt;/p&gt;
&lt;p&gt;Go is an imperative programming language for concurrent programming created at and mainly developed by Google, initially mostly by Robert Griesemer, Rob Pike, and Ken Thompson.
Design of the language started in 2007, and an initial version was released in 2009; with the first stable version, 1.0 released in 2012 &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>(What follows is an excerpt from my master&rsquo;s thesis, almost all of section
2.1, quickly introducing Go to people familiar with CS)</p>
<p>Go is an imperative programming language for concurrent programming created at and mainly developed by Google, initially mostly by Robert Griesemer, Rob Pike, and Ken Thompson.
Design of the language started in 2007, and an initial version was released in 2009; with the first stable version, 1.0 released in 2012 <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>Go has a C-like syntax (without a preprocessor), garbage collection, and, like its predecessors devloped at Bell Labs &ndash; Newsqueak (Rob Pike), Alef (Phil Winterbottom), and Inferno (Pike, Ritchie, et al.) &ndash; provides built-in support for concurrency using so-called goroutines and channels, a form of co-routines, based on the idea of Hoare&rsquo;s &lsquo;Communicating Sequential Processes&rsquo; <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</p>
<p>Go programs are organised in packages. A package is essentially a directory containing Go files. All files in a package share the same namespace, and there are two visibilities for symbols in a package: Symbols starting with an upper case character are visible to other packages, others are private to the package:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">PublicFunction</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">&#34;Hello world&#34;</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">privateFunction</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">&#34;Hello package&#34;</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="types">Types</h2>
<p>Go has a fairly simple type system: There is no subtyping (but there are conversions), no generics, no polymorphic functions, and there are only a few basic categories of types:</p>
<ol>
<li>
<p>base types: <code>int</code>, <code>int64</code>, <code>int8</code>, <code>uint</code>, <code>float32</code>, <code>float64</code>, etc.</p>
</li>
<li>
<p><code>struct</code></p>
</li>
<li>
<p><code>interface</code> - a set of methods</p>
</li>
<li>
<p><code>map[K, V]</code> - a map from a key type to a value type</p>
</li>
<li>
<p><code>[number]Type</code> - an array of some element type</p>
</li>
<li>
<p><code>[]Type</code> - a slice (pointer to array with length and capability) of some type</p>
</li>
<li>
<p><code>chan Type</code> - a thread-safe queue</p>
</li>
<li>
<p>pointer <code>*T</code> to some other type</p>
</li>
<li>
<p>functions</p>
</li>
<li>
<p>named type - aliases for other types that may have associated methods:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">T</span> <span style="color:#66d9ef">struct</span> { <span style="color:#a6e22e">foo</span> <span style="color:#66d9ef">int</span> }
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">T</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">T</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">T</span> <span style="color:#a6e22e">OtherNamedType</span>
</span></span></code></pre></div><p>Named types are mostly distinct from their underlying types, so you cannot
assign them to each other, but some operators like <code>+</code> do work on objects of
named types with an underlying numerical type (so you could add two <code>T</code> in the example above).</p>
</li>
</ol>
<p>Maps, slices, and channels are reference-like types - they essentially are structs containing pointers. Other types are passed by value (copied), including arrays (which have a fixed length and are copied).</p>
<h3 id="conversions">Conversions</h3>
<p>Conversions are the similar to casts in C and other languages. They are written like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span>    <span style="color:#a6e22e">TypeName</span>(<span style="color:#a6e22e">value</span>)
</span></span></code></pre></div><h3 id="constants">Constants</h3>
<p>Go has &ldquo;untyped&rdquo; literals and constants.</p>
<pre tabindex="0"><code>    1    // untyped integer literal
    const foo = 1 // untyped integer constant
    const foo int = 1 // int constant
</code></pre><p>Untyped values are classified into the following categories: <code>UntypedBool</code>, <code>UntypedInt</code>, <code>UntypedRune</code>, <code>UntypedFloat</code>, <code>UntypedComplex</code>, <code>UntypedString</code>, and <code>UntypedNil</code> (Go calls them <em>basic kinds</em>,
other basic kinds are available for the concrete types like <code>uint8</code>). An untyped value can be assigned to a named type derived from a base type; for example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">someType</span> <span style="color:#66d9ef">int</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">untyped</span> = <span style="color:#ae81ff">2</span>             <span style="color:#75715e">// UntypedInt</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">bar</span> <span style="color:#a6e22e">someType</span> = <span style="color:#a6e22e">untyped</span>  <span style="color:#75715e">// OK: untyped can be assigned to someType</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">typed</span> <span style="color:#66d9ef">int</span> = <span style="color:#ae81ff">2</span>           <span style="color:#75715e">// int</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">bar2</span> <span style="color:#a6e22e">someType</span> = <span style="color:#a6e22e">typed</span>   <span style="color:#75715e">// error: int cannot be assigned to someType</span>
</span></span></code></pre></div><h2 id="interfaces-and-objects">Interfaces and &lsquo;objects&rsquo;</h2>
<p>As mentioned before, interfaces are a set of methods.
Go is not an object-oriented language per se, but it has some support for associating methods with
named types: When declaring a function, a <em>receiver</em> can be provided - a receiver is an additional
function argument that is passed before the function and involved in the function lookup, like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">SomeType</span> <span style="color:#66d9ef">struct</span> { <span style="color:#f92672">...</span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> (<span style="color:#a6e22e">s</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">SomeType</span>) <span style="color:#a6e22e">MyMethod</span>() {
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">s</span> <span style="color:#a6e22e">SomeType</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">s</span>.<span style="color:#a6e22e">MyMethod</span>()
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>An object implements an interface if it implements all methods; for example, the following interface <code>MyMethoder</code> is implemented by <code>*SomeType</code> (note the pointer), and values of <code>*SomeType</code> can thus be used as values of <code>MyMethoder</code>. The most basic interface is <code>interface{}</code>, that is an interface with an empty method set - any object satisfies that interface.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">MyMethoder</span> <span style="color:#66d9ef">interface</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">MyMethod</span>()
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>There are some restrictions on valid receiver types; for example, while a named type could be a pointer (for example, <code>type MyIntPointer *int</code>), such a type is not a valid receiver type.</p>
<h2 id="control-flow">Control flow</h2>
<p>Go provides three primary statements for control flow: <code>if</code>, <code>switch</code>, and <code>for</code>.
The statements are fairly similar to their equivalent in other C-like languages, with some exceptions:</p>
<ul>
<li>
<p>There are no parentheses around conditions, so it is <code>if a == b {}</code>, not <code>if (a == b) {}</code>. The braces are mandatory.</p>
</li>
<li>
<p>All of them can have initialisers, like this</p>
<p><code>if result, err := someFunction(); err == nil { // use result }</code></p>
</li>
<li>
<p>The <code>switch</code> statement can use arbitrary expressions in cases</p>
</li>
<li>
<p>The <code>switch</code> statement can switch over nothing (equals switching over true)</p>
</li>
<li>
<p>Cases do not fall through by default (no <code>break</code> needed), use <code>fallthrough</code> at the end of a block to fall through.</p>
</li>
<li>
<p>The <code>for</code> loop can loop over ranges: <code>for key, val := range map { do something }</code></p>
</li>
</ul>
<h2 id="goroutines">Goroutines</h2>
<p>The keyword <code>go</code> spawns a new goroutine, a concurrently executed function. It can be used with any function call, even a function literal:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">...</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">go</span> <span style="color:#66d9ef">func</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">...</span>
</span></span><span style="display:flex;"><span>    }()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">go</span> <span style="color:#a6e22e">some_function</span>(<span style="color:#a6e22e">some_argument</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="channels">Channels</h2>
<p>Goroutines are often combined with channels to provide an extended form of Communicating Sequential Processes <sup id="fnref1:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. A channel is a concurrent-safe queue, and can be buffered or unbuffered:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">unbuffered</span> = make(<span style="color:#66d9ef">chan</span> <span style="color:#66d9ef">int</span>)  <span style="color:#75715e">// sending blocks until value has been read</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">buffered</span> = make(<span style="color:#66d9ef">chan</span> <span style="color:#66d9ef">int</span>, <span style="color:#ae81ff">5</span>) <span style="color:#75715e">// may have up to 5 unread values queued</span>
</span></span></code></pre></div><p>The <code>&lt;-</code> operator is used to communicate with a single channel.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">valueReadFromChannel</span> <span style="color:#f92672">:=</span> <span style="color:#f92672">&lt;-</span> <span style="color:#a6e22e">channel</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">otherChannel</span> <span style="color:#f92672">&lt;-</span> <span style="color:#a6e22e">valueToSend</span>
</span></span></code></pre></div><p>The <code>select</code> statement allows communication with multiple channels:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">select</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> <span style="color:#a6e22e">incoming</span> <span style="color:#f92672">:=</span> <span style="color:#f92672">&lt;-</span> <span style="color:#a6e22e">inboundChannel</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// A new message for me</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> <span style="color:#a6e22e">outgoingChannel</span> <span style="color:#f92672">&lt;-</span> <span style="color:#a6e22e">outgoing</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// Could send a message, yay!</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="the-defer-statement">The <code>defer</code> statement</h2>
<p>Go provides a <code>defer</code> statement that allows a function call to be scheduled for execution when the function exits. It can be used for resource clean-up, for example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">myFunc</span>(<span style="color:#a6e22e">someFile</span> <span style="color:#a6e22e">io</span>.<span style="color:#a6e22e">ReadCloser</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">someFile</span>.close()
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/* Do stuff with file */</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>It is of course possible to use function literals as the function to call, and any variables can be used as usual when writing the call.</p>
<h2 id="error-handling">Error handling</h2>
<p>Go does not provide exceptions or structured error handling. Instead, it handles errors by returning them in a second or later return value:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">Read</span>(<span style="color:#a6e22e">p</span> []<span style="color:#66d9ef">byte</span>) (<span style="color:#a6e22e">n</span> <span style="color:#66d9ef">int</span>, <span style="color:#a6e22e">err</span> <span style="color:#66d9ef">error</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Built-in type:</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#66d9ef">error</span> <span style="color:#66d9ef">interface</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">Error</span>() <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Errors have to be checked in the code, or can be assigned to <code>_</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">n0</span>, <span style="color:#a6e22e">_</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">Read</span>(<span style="color:#a6e22e">Buffer</span>)   <span style="color:#75715e">// ignore error</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">n</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">Read</span>(<span style="color:#a6e22e">buffer</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>There are two functions to quickly unwind and recover the call stack, though: <code>panic()</code> and <code>recover()</code>.
When <code>panic()</code> is called, the call stack is unwound, and any deferred functions are run as usual.
When a deferred function invokes <code>recover()</code>, the unwinding stops, and the value given to <code>panic()</code> is returned.
If we are unwinding normally and not due to a panic, <code>recover()</code> simply returns <code>nil</code>.
In the example below, a function is deferred and any <code>error</code> value that is given to <code>panic()</code> will be recovered and stored in an error return value.
Libraries sometimes use that approach to make highly recursive code like parsers more readable, while still maintaining the usual error return value for public functions.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">Function</span>() (<span style="color:#a6e22e">err</span> <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">defer</span> <span style="color:#66d9ef">func</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">s</span> <span style="color:#f92672">:=</span> recover()
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">switch</span> <span style="color:#a6e22e">s</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">s</span>.(<span style="color:#66d9ef">type</span>) {  <span style="color:#75715e">// type switch</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> <span style="color:#66d9ef">error</span>:
</span></span><span style="display:flex;"><span>                <span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">s</span>         <span style="color:#75715e">// s has type error now</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">default</span>:
</span></span><span style="display:flex;"><span>                panic(<span style="color:#a6e22e">s</span>)
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="arrays-and-slices">Arrays and slices</h2>
<p>As mentioned before, an array is a value type and a slice is a pointer into an array, created either by slicing an existing array or by using <code>make()</code> to create a slice, which will create an anonymous array to hold the elements.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">slice1</span> <span style="color:#f92672">:=</span> make([]<span style="color:#66d9ef">int</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">5</span>) <span style="color:#75715e">// 5 elements allocated, 2 initialized to 0</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">slice2</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">array</span>[:]          <span style="color:#75715e">// sliced entire array</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">slice3</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">array</span>[<span style="color:#ae81ff">1</span>:]         <span style="color:#75715e">// slice of array without first element</span>
</span></span></code></pre></div><p>There are some more possible combinations for the slicing operator than mentioned above, but this should give a good first impression.</p>
<p>A slice can be used as a dynamically growing array, using the <code>append()</code> function.</p>
<pre tabindex="0"><code>slice = append(slice, value1, value2)
slice = append(slice, arrayOrSlice...)
</code></pre><p>Slices are also used internally to represent variable parameters in variable length functions.</p>
<h2 id="maps">Maps</h2>
<p>Maps are simple key-value stores and support indexing and assigning. They are <em>not</em> thread-safe.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">someValue</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">someMap</span>[<span style="color:#a6e22e">someKey</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">someValue</span>, <span style="color:#a6e22e">ok</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">someMap</span>[<span style="color:#a6e22e">someKey</span>]   <span style="color:#75715e">// ok is false if key not in someMap</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">someMap</span>[<span style="color:#a6e22e">someKey</span>] = <span style="color:#a6e22e">someValue</span>
</span></span></code></pre></div><div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Frequently Asked Questions (FAQ) - The Go Programming Language <a href="https://golang.org/doc/faq#history">https://golang.org/doc/faq#history</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>HOARE, Charles Antony Richard. Communicating sequential processes. Communications of the ACM, 1978, 21. Jg., Nr. 8, S. 666-677.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Migrating web servers</title>
      <link>https://blog.jak-linux.org/2018/12/01/migrating-servers/</link>
      <pubDate>Sat, 01 Dec 2018 23:40:21 +0100</pubDate>
      
      <guid>https://blog.jak-linux.org/2018/12/01/migrating-servers/</guid>
      <description>&lt;p&gt;As of today, I migrated various services from shared hosting on
uberspace.de to a VPS hosted by &lt;a href=&#34;https://www.hetzner.de&#34;&gt;hetzner&lt;/a&gt;.
This includes my weechat client, this blog, and the following other
websites:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;jak-linux.org&lt;/li&gt;
&lt;li&gt;dep.debian.net redirector&lt;/li&gt;
&lt;li&gt;mirror.fail&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;rationale&#34;&gt;Rationale&lt;/h2&gt;
&lt;p&gt;Uberspace runs CentOS 6. This was causing more and more issues for me,
as I was trying to run up-to-date weechat binaries. In the final stages,
I ran weechat and tmux inside a debian proot. It certainly beat compiling
half a system with linuxbrew.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>As of today, I migrated various services from shared hosting on
uberspace.de to a VPS hosted by <a href="https://www.hetzner.de">hetzner</a>.
This includes my weechat client, this blog, and the following other
websites:</p>
<ul>
<li>jak-linux.org</li>
<li>dep.debian.net redirector</li>
<li>mirror.fail</li>
</ul>
<h2 id="rationale">Rationale</h2>
<p>Uberspace runs CentOS 6. This was causing more and more issues for me,
as I was trying to run up-to-date weechat binaries. In the final stages,
I ran weechat and tmux inside a debian proot. It certainly beat compiling
half a system with linuxbrew.</p>
<p>The web performance was suboptimal. Webpages are served with Pound and Apache,
TLS connection overhead was just huge, there was only HTTP/1.1, and no
keep-alive.</p>
<p>Security-wise things were interesting: Everything ran as my user, obviously,
whether that&rsquo;s scripts, weechat, or mail delivery helpers. Ugh. There was
also only a single certificate, meaning that all domains shared it, even
if they were completely distinct like jak-linux.org and dep.debian.net</p>
<h2 id="enter-hetzner-vps">Enter Hetzner VPS</h2>
<p>I launched a VPS at hetzner and configured it with Ubuntu 18.04, the
latest Ubuntu LTS.  It is a CX21, so it has 2 vcores, 4 GB RAM, 40 GB
SSD storage, and 20 TB of traffic. For 5.83€/mo, you can&rsquo;t complain.</p>
<p>I went on to build a repository of ansible roles (see <a href="https://github.com/julian-klode/ansible.jak-linux.org">repo on github.com</a>),
that configured the system with a few key characteristics:</p>
<ul>
<li>http is served by nginx</li>
<li>certificates are per logical domain - each domain has a canonical name
and a set of aliases; and the certificate is generated for them all</li>
<li>HTTPS is configured according to Mozilla&rsquo;s modern profile, meaning
TLSv1.2-only, and a very restricted list of ciphers. I can revisit that
if it&rsquo;s causing problems, but I&rsquo;ve not seen huge issues.</li>
<li>Log files are anonymized to 24 bits for IPv4 addresses, and 32 bit for
IPv6 addresses, which should allow me to identify an ISP, but not an
individual user.</li>
</ul>
<p>I don&rsquo;t think the roles are particularly reusable for others, but it&rsquo;s
nice to have a central repository containing all the configuration for
the server.</p>
<h2 id="go-server-to-serve-comments">Go server to serve comments</h2>
<p>When I started self-hosting the blog and added commenting via mastodon,
it was via a third-party PHP script. This has been replaced by a Go
program (<a href="https://github.com/julian-klode/mastodon-comments">GitHub repo</a>).
The new Go program scales a lot better than a PHP script, and provides
better security properties due to AppArmor and systemd-based sandboxing;
it even uses systemd&rsquo;s DynamicUser.</p>
<p>Special care has been taken to have time outs for talking to upstream
servers, so the program cannot hang with open connections and will
respond eventually.</p>
<p>The Go binary is connected to nginx via a UNIX domain socket that
serves FastCGI. The service is activated via systemd socket activation,
allowing it to be owned by www-data, while the binary runs as a dynamic
user. Nginx&rsquo;s native fastcgi caching mechanism is enabled so
the Go process is only contacted every 10 minutes at the most (for a given
post). Nice!</p>
<h2 id="performance">Performance</h2>
<p>Performance is a lot better than the old shared server. Pages load
in up to half the time of the old one. Scalability also seems better:
I tried various benchmarks, and achieved consistently higher concurrency
ratings. A simple curl via https now takes 100ms instead of 200ms.</p>
<p>Performance is still suboptimal from the west coast of the US or other
places far away from Germany, but got a lot better than before:
Measuring from Oregon using webpagetest, it took 1.5s  for a page to
fully render vs ~3.4s before. A CDN would surely be faster, but would
lose the end-to-end encryption.</p>
<h2 id="upcoming-mail-server">Upcoming mail server</h2>
<p>The next step is to enable email. Setting up postfix with dovecot
is quite easy it turns out. Install them, tweak a few settings, setup
SPF, DKIM, DMARC, and a PTR record, and off you go.</p>
<p>I mostly expect to read my email by tagging it on the server using
notmuch somehow, and then syncing it to my laptop using muchsync. The
IMAP access should allow some notifications or reading on the phone.</p>
<p>Spam filtering will be handled with <a href="https://rspamd.com">rspamd</a>. It
seems to be the hot new thing on the market, is integrated with postfix
as a milter, and handles a lot of stuff, such as:</p>
<ul>
<li>greylisting</li>
<li>IP scoring</li>
<li>DKIM verification and signing</li>
<li>ARC verification</li>
<li>SPF verification</li>
<li>DNS lists</li>
<li>Rate limiting</li>
</ul>
<p>It also has fancy stuff like neural networks. Woohoo!</p>
<p>As another bonus point: It&rsquo;s trivial to confine with AppArmor, which
I really love. Postfix and Dovecot are a mess to confine with their
hundreds of different binaries.</p>
<p>I found it via uberspace, which plan on using it for their next
uberspace7 generation. It is also used by some large installations
like rambler.ru and locaweb.com.br.</p>
<p>I plan to migrate mail from uberspace in the upcoming weeks, and will
post more details about it.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Migrated website from ikiwiki to Hugo</title>
      <link>https://blog.jak-linux.org/2018/10/25/migrated-website-from-ikiwiki-to-hugo/</link>
      <pubDate>Thu, 25 Oct 2018 20:42:16 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2018/10/25/migrated-website-from-ikiwiki-to-hugo/</guid>
      <description>&lt;p&gt;So, I&amp;rsquo;ve been using ikiwiki for my website since 2011. At the time, I was hosting
the website on a tiny hosting package included in a DSL contract - nothing dynamic
possible, so a static site generator seemed like a good idea.
ikiwiki was a good social fit at the time, as it was packaged in Debian and developed
by a Debian Developer.&lt;/p&gt;
&lt;p&gt;Today, I finished converting it to &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;why&#34;&gt;Why?&lt;/h2&gt;
&lt;p&gt;I did not really have a huge problem with ikiwiki, but I recently converted my blog
from wordpress to hugo and it seemed to make sense to have one technology for both,
especially since I don&amp;rsquo;t update the website very often and forget ikiwiki&amp;rsquo;s special
things.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>So, I&rsquo;ve been using ikiwiki for my website since 2011. At the time, I was hosting
the website on a tiny hosting package included in a DSL contract - nothing dynamic
possible, so a static site generator seemed like a good idea.
ikiwiki was a good social fit at the time, as it was packaged in Debian and developed
by a Debian Developer.</p>
<p>Today, I finished converting it to <a href="https://gohugo.io">Hugo</a>.</p>
<h2 id="why">Why?</h2>
<p>I did not really have a huge problem with ikiwiki, but I recently converted my blog
from wordpress to hugo and it seemed to make sense to have one technology for both,
especially since I don&rsquo;t update the website very often and forget ikiwiki&rsquo;s special
things.</p>
<p>One thing that was somewhat annoying is that I built a custom ikiwiki plugin for the
menu in my template, so I had to clone it&rsquo;s repository into <code>~/.ikiwiki</code> every time,
rather than having a self-contained website. Well, it was a submodule of my dotfiles
repo.</p>
<p>Another thing was that ikiwiki had a lot of git integration, and when you build your
site it tries to push things to git repositories and all sorts of weird stuff &ndash; Hugo
just does one thing: It builds your page.</p>
<p>One thing that Hugo does a lot better than ikiwiki is the built-in server which allows
you to run `hugo server´ and get a local http URL you can open in the browser with
live-reload as you save files. Super convenient to check changes (and of course, for
writing this blog post)!</p>
<p>Also, in general, Hugo feels a lot more <em>modern</em>. ikiwiki is from 2006, Hugo is from
2013. Especially recent Hugo versions added quite a few features for asset management.</p>
<ul>
<li>Fingerprinting of assets like css (inserting hash into filename) - ikiwiki just contains
its style in <code>style.css</code> (and your templates in other statically named files), so if you
switch theming details, you could break things because the CSS the browser has cached does
not match the CSS the page expects.</li>
<li>Asset minification - Hugo can minimize CSS and JavaScript for you. This means browers have
to fetch less data.</li>
<li>Asset concatenation - Hugo can concatenate CSS and JavaScript. This allows you to serve
only one file per type, reducing the number of round trips a client has to make.</li>
</ul>
<p>There&rsquo;s also proper theming support, so you can easily clone a theme into the <code>themes/</code>
directory, or add it as a submodule like I do for my blog. But I don&rsquo;t use it for the
website yet.</p>
<p>Oh, and Hugo automatically generates <code>sitemap.xml</code> files for your website, teaching
search engines which pages exist and when they have been modified.</p>
<p>I also like that it&rsquo;s written in Go vs in Perl, but I think that&rsquo;s just another <em>more modern</em>
type of thing. Gotta keep up with the world!</p>
<h2 id="basic-conversion">Basic conversion</h2>
<p>The first part to the conversion was to split the repository of the website: ikiwiki
puts templates into a <code>templates/</code> subdirectory of the repository and mixes all other
content. Hugo on the other hand splits things into <code>content/</code> (where pages go),
<code>layouts</code> (page templates), and <code>static/</code> (other files).</p>
<p>The second part was to inject the frontmatter into the markdown files. See, ikiwiki
uses shortcuts like this to set up the title, and gets its dates from git:</p>
<pre tabindex="0"><code>[[!meta title=&#34;My page title&#34;]]
</code></pre><p>on the other hand, Hugo uses frontmatter - some YAML at the beginning of the markdown,
and specifies the creation date in there:</p>
<pre tabindex="0"><code>---
title: &#34;My page title&#34;
date: Thu, 18 Oct 2018 21:36:18 +0200
---
</code></pre><p>You can also have <code>lastmod</code> in there when modifying it, but I set <code>enableGitInfo = true</code>
in config.toml so Hugo picks up the mtime from the git repo.</p>
<p>I wrote a <a href="ikiwiki-to-hugo.py">small script</a> to automatize those steps, but it was obviously
not perfect (also, it inserted lastmod, which it should not have).</p>
<p>One thing it took me some time to figure out was that <code>index.mdown</code> needs to become
<code>_index.md</code> in the <code>content/</code> directory of Hugo, otherwise no pages below it are
rendered - not entirely obvious.</p>
<h2 id="the-theme">The theme</h2>
<p>Converting the template was surprisingly easy, it was just a matter of replacing
<code>&lt;TMPL_VAR BASEURL&gt;</code> and friends with <code>{ .Site.BaseURL }</code> and friends - the names
are basically the same, just sometimes there&rsquo;s <code>.Site</code> at the front of it.</p>
<p>Then I had to take care of the menu generation loop. I had my <code>bootmenu</code> plugin for ikiwiki which
allowed me to generate menus from the configuration file. The template for it looked like this:</p>
<pre tabindex="0"><code>&lt;TMPL_LOOP BOOTMENU&gt;
    &lt;TMPL_IF FIRSTNAV&gt;
        &lt;li &lt;TMPL_IF ACTIVE&gt;class=&#34;active&#34;&lt;/TMPL_IF&gt;&gt;&lt;a href=&#34;&lt;TMPL_VAR URL&gt;&#34;&gt;&lt;TMPL_VAR PAGE&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;/TMPL_IF&gt;
&lt;/TMPL_LOOP&gt;
</code></pre><p>I converted this to:</p>
<pre tabindex="0"><code>{{ $currentPage := . }}
{{ range .Site.Menus.main }}
    &lt;li class=&#34;{{ if $currentPage.IsMenuCurrent &#34;main&#34; . }}active{{ end }}&#34;&gt;
        &lt;a href=&#34;{{ .URL }}&#34;&gt;
            {{ .Pre | safeHTML }}
            &lt;span&gt;{{ .Name }}&lt;/span&gt;
        &lt;/a&gt;
        {{ .Post }}
    &lt;/li&gt;
{{ end }}
</code></pre><p>this allowed me to configure my menu in config.toml like this:</p>
<pre tabindex="0"><code>[menu]

  [[menu.main]]
    name = &#34;dh-autoreconf&#34;
    url = &#34;/projects/dh-autoreconf&#34;
    weight = -110
</code></pre><p>I can also specify <code>pre</code> and <code>post</code> parts and a <code>right</code> menu, and I use <code>pre</code> and
<code>post</code> in the right menu to render a few icons before and after items, for example:</p>
<pre tabindex="0"><code>  [[menu.right]]
    pre = &#34;&lt;i class=&#39;fab fa-mastodon&#39;&gt;&lt;/i&gt;&#34;
    post = &#34;&lt;i class=&#39;fas fa-external-link-alt&#39;&gt;&lt;/i&gt;&#34;
    url = &#34;https://mastodon.social/@juliank&#34;
    name = &#34;Mastodon&#34;
    weight = -70
</code></pre><p>Setting <code>class=&quot;active&quot;</code> on the menu item does not seem to work yet, though; I think
I need to find out the right code for that&hellip;</p>
<h2 id="fixing-up-the-details">Fixing up the details</h2>
<p>Once I was done with that steps, the next stage was to convert ikiwiki <em>shortcodes</em>
to something hugo understands. This took 4 parts:</p>
<p>The first part was converting tables. In ikiwiki, tables look like this:</p>
<pre tabindex="0"><code>[[!table format=dsv data=&#34;&#34;&#34;
Status|License|Language|Reference
Active|GPL-3+|Java|[github](https://github.com/julian-klode/dns66)
&#34;&#34;&#34;]]
</code></pre><p>The generated HTML table had the <code>class=&quot;table&quot;</code> set, which the bootstrap framework
needs to render a nice table. Converting that to a straightforward markdown hugo table
did not work: Hugo did not add the class, so I had to convert pages with tables in them
to the <code>mmark</code> variant of markdown, which allows classes to be set like this <code>{.table}</code>,
so the end result then looked like this:</p>
<pre tabindex="0"><code>{.table}
Status|License|Language|Reference
------|-------|--------|---------
Active|GPL-3+|Java|[github](https://github.com/julian-klode/dns66)
</code></pre><p>I&rsquo;ll be able to get rid of this in the future by using the bootstrap sources and
then having <code>table</code> inherit <code>.table</code> properties, but this requires saas or less, and
I only have the CSS at the moment, so using mmark was slightly easier.</p>
<p>The second part was converting ikiwiki links like <code>[[MyPage]]</code> and <code>[[my title|MyPage]]</code>
to Markdown links. This was quite easy, the first one became <code>[MyPage](MyPage)</code> and
the second one <code>[my title](my page)</code>.</p>
<p>The third part was converting custom shortcuts: I had <code>[[!lp &lt;number&gt;]]</code> to generate
a link <code>LP: #&lt;number&gt;</code> to the corresponding launchpad bug, and <code>[[!Closes &lt;number&gt;]]</code>
to generate <code>Closes: #&lt;number&gt;</code> links to the Debian bug tracker. I converted those
to normal markdown links, but I could have converted them to <a href="https://gohugo.io/templates/shortcode-templates/">Hugo shortcodes</a>.
But meh.</p>
<p>The fourth part was about converting some directory indexes I had. For example,
<code>[[!map pages=&quot;projects/dir2ogg/0.12/* and ! projects/dir2ogg/0.12/*/*&quot;]]</code> generated
a list of all files in <code>projects/dir2ogg/0.12</code>. There was a very useful shortcode
for that posted on the Hugo documentation, I used <a href="https://github.com/julian-klode/jak-linux.org/blob/f1d5e4d48046ff08d7612de5fa44e06b3c8c6be6/layouts/shortcodes/directoryindex.html">a variant of it</a> and then converted
pages like this to <code>{{&lt; directoryindex path=&quot;/static/projects/dir2ogg/0.12&quot; pathURL=&quot;/projects/dir2ogg/0.12&quot; &gt;}}</code>. As
a bonus, the new directory index also generates SHA256 hashes for all files!</p>
<h2 id="further-work">Further work</h2>
<p>The website is using an old version of bootstrap, and the theme is not split out yet. I&rsquo;m
not sure if I want to keep a bootstrap theme for the website, seeing as the blog theme is
Bulma-based - it would be easier to have both use bulma.</p>
<p>I also might want to update both the website and the blog by pushing to GitHub and then
using CI to build and push it. That would allow me to write blog posts when I don&rsquo;t have
my laptop with me. But I&rsquo;m not sure, I might lose control if there&rsquo;s a breach at travis.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>The demise of G&#43; and return to blogging (w/ mastodon integration)</title>
      <link>https://blog.jak-linux.org/2018/10/13/new-blog/</link>
      <pubDate>Sat, 13 Oct 2018 23:03:14 +0200</pubDate>
      
      <guid>https://blog.jak-linux.org/2018/10/13/new-blog/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m back to blogging, after shutting down my wordpress.com hosted
blog in spring. This time, fully privacy aware, self hosted, and
integrated with mastodon.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s talk details: In spring, I shutdown my wordpress.com hosted
blog, due to concerns about GDPR implications with comment hosting
and ads and stuff. I&amp;rsquo;d like to apologize for using that, back when I
did this (in &lt;a href=&#34;https://blog.jak-linux.org/2007/12/20/hello-world/&#34;&gt;2007&lt;/a&gt;), it was the easiest way
to get into blogging. Please forgive me for subjecting you to that!&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I&rsquo;m back to blogging, after shutting down my wordpress.com hosted
blog in spring. This time, fully privacy aware, self hosted, and
integrated with mastodon.</p>
<p>Let&rsquo;s talk details: In spring, I shutdown my wordpress.com hosted
blog, due to concerns about GDPR implications with comment hosting
and ads and stuff. I&rsquo;d like to apologize for using that, back when I
did this (in <a href="/2007/12/20/hello-world/">2007</a>), it was the easiest way
to get into blogging. Please forgive me for subjecting you to that!</p>
<p>Recently, Google announced the end of Google+. As some of you might
know, I posted a lot of medium-long posts there, rather than doing
blog posts; especially after I disabled the wordpress site.</p>
<p>With the end of Google+, I want to try something new: I&rsquo;ll host longer
pieces on this blog, and post shorter messages on
<a href="https://mastodon.social/@juliank">@juliank@mastodon.social</a>. If you
follow the Mastodon account, you will see toots for each new blog post
as well, linking to the blog post.</p>
<h2 id="mastodon-integration-and-privacy">Mastodon integration and privacy</h2>
<p>Now comes the interesting part: If you reply to the toot, your reply
will be shown on the blog itself. This works with a tiny bit of JavaScript
that talks to a simple server-side script that finds toots from me
mentioning the blog post, and then replies to that.</p>
<p>This protects your privacy, because mastodon.social does not see which
blog post you are looking at, because it is contacted by the server, not
by you. Rendering avatars requires loading images from mastodon.social&rsquo;s
file server, however - to improve your privacy, all avatars are loaded
with <code>referrerpolicy='no-referrer'</code>, so assuming your browser is half-way
sane, it should not be telling mastodon.social which post you visited
either. In fact, the entire domain also sets <code>Referrer-Policy: no-referrer</code>
as an http header, so any link you follow will not have a referrer set.</p>
<p>The integration was originally written by <a href="https://mastodon.social/@bjoern">@bjoern@mastodon.social</a>
&ndash; I have done some moderate improvements to adapt it to my theme,
make it more reusable, and replace and extend the caching done in
a JSON file with a Redis database.</p>
<h2 id="source-code">Source code</h2>
<p>This blog is free software; generated by the <a href="https://gohugo.io">Hugo</a> snap. All
source code for it is available:</p>
<ul>
<li>
<p>The blog posts are provided at <a href="https://github.com/julian-klode/blog.jak-linux.org">github.com/julian-klode/blog.jak-linux.org</a>.
under the terms of the <a href="http://creativecommons.org/licenses/by-sa/4.0/">CC BY-SA 4.0</a> license.</p>
</li>
<li>
<p>The theme is called Ernest, and is a fork of the Hemingway theme. You
can find it at <a href="https://github.com/julian-klode/ernest">github.com/julian-klode/ernest</a>. It
is licensed under the MIT license, with server-side scripts under the AGPL,
and some vendorized parts under different licenses.</p>
</li>
</ul>
<p>(Yes I am aware that hosting the repositories on GitHub is a bit ironic
given the whole focus on privacy and self-hosting).</p>
<p>The theme makes use of Hugo pipes to minify and fingerprint JavaScript,
and vendorizes all dependencies instead of embedding CDN links, to, again,
protect your privacy.</p>
<h2 id="future-work">Future work</h2>
<p>I think I want to make the theme dark, to be more friendly to the
eyes. I also might want to make the mastodon integration a bit more
friendly to use. And I want to get rid of jQuery, it&rsquo;s only used for
a handful of calls in the Mastodon integration JavaScript.</p>
<p>If you have any other idea for improvements, feel free to join the conversation in the
mastodon toot, send me an email, or open an issue at the github projects.</p>
<h2 id="closing-thoughts">Closing thoughts</h2>
<p>I think the end of Google+ will be an interesting time, requring a lot
of people in the open source world to replace one of their main
communication channels with a different approach.</p>
<p>Mastodon and Diaspora are both in the race, and I fear the community
will split or everyone will have two accounts in the end. I personally
think that Mastodon + syndicated blogs provide a good balance: You can
quickly write short posts (up to 500 characters), and you can host long
articles on your own and link to them.</p>
<p>I hope that one day diaspora* and mastodon federate together. If we
end up with one federated network that would be the best outcome.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>A year ends, a new year begins</title>
      <link>https://blog.jak-linux.org/2018/01/01/a-year-ends-a-new-year-begins/</link>
      <pubDate>Sun, 31 Dec 2017 23:01:10 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2018/01/01/a-year-ends-a-new-year-begins/</guid>
      <description>&lt;p&gt;2017 is ending. It&amp;rsquo;s been a rather uneventful year, I&amp;rsquo;d say. About 6 months ago I started working on my master&amp;rsquo;s thesis - it plays with adding linear types to Go - and I handed that in about 1.5 weeks ago. It&amp;rsquo;s not really complete, though - you cannot actually use it on a complete Go program. The source code is of course &lt;a href=&#34;https://github.com/julian-klode/lingolang&#34;&gt;available on GitHub&lt;/a&gt;, it&amp;rsquo;s a bunch of Go code for the implementation and a bunch of Markdown and LaTex for the document. I&amp;rsquo;m happy about the code coverage, though: As a properly developed software project, it achieves about 96% code coverage - the missing parts happening at the end, when time ran out ;)&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>2017 is ending. It&rsquo;s been a rather uneventful year, I&rsquo;d say. About 6 months ago I started working on my master&rsquo;s thesis - it plays with adding linear types to Go - and I handed that in about 1.5 weeks ago. It&rsquo;s not really complete, though - you cannot actually use it on a complete Go program. The source code is of course <a href="https://github.com/julian-klode/lingolang">available on GitHub</a>, it&rsquo;s a bunch of Go code for the implementation and a bunch of Markdown and LaTex for the document. I&rsquo;m happy about the code coverage, though: As a properly developed software project, it achieves about 96% code coverage - the missing parts happening at the end, when time ran out ;)</p>
<p>I released apt 1.5 this year, and started 1.6 with seccomp sandboxing for methods.</p>
<p>I went to DebConf17 in Montreal. I unfortunately did not make it to DebCamp, nor the first day, but I at least made the rest of the conference. There, I gave a talk about APT development in the past year, and had a few interesting discussions. One thing that directly resulted from such a discusssion was a new proposal for delta upgrades, with a very simple delta format based on a variant of bsdiff (with external compression, streamable patches, and constant memory use rather than linear). I hope we can implement this - the savings are enormous with practically no slowdown (there is no reconstruction phase, upgrades are streamed directly to the file system), which is especially relevant for people with slow or data capped connections.</p>
<p>This month, I&rsquo;ve been buying a few &ldquo;toys&rdquo;: I got a pair of speakers (JBL LSR 305), and I got a noise cancelling headphone (a Sony WH-1000XM2). Nice stuff. Been wearing the headphones most of today, and they&rsquo;re quite comfortable and really make things quite, except for their own noise ;) Well, both the headphone and the speakers have a white noise issue, but oh well, the prices were good.</p>
<p>This time of the year is not only a time to look back at the past year, but also to look forward to the year ahead. In one week, I&rsquo;ll be joining Canonical to work on Ubuntu foundation stuff. It&rsquo;s going to be interesting. I&rsquo;ll also be moving places shortly, having partially lived in student housing for 6 years (one room, and a shared kitchen), I&rsquo;ll be moving to a complete apartement.</p>
<p>On the APT front, I plan to introduce a few interesting changes. One of them involves automatic removal of unused packages: This should be happening automatically during install, upgrade, and whatever. Maybe not for all packages, though - we might have a list of &ldquo;safe&rdquo; autoremovals. I&rsquo;d also be interested in adding metadata for transitions: Like if <code>libfoo1</code> replaces <code>libfoo0</code>, we can safely remove <code>libfoo0</code> if nothing depends on it anymore. Maybe not for all &ldquo;garbage&rdquo; either. It might make sense to restrict it to new garbage - that is packages that become unused as part of the operation. This is important for safe handling of existing setups with automatically removable packages: We don&rsquo;t suddenly want to remove them all when you run upgrade.</p>
<p>The other change is about sandboxing. You might have noticed that sometimes, sandboxing is disabled with a warning because the method would not be able access the source or the target. The goal is to open these files in the main program and send file descriptors to the methods via a socket. This way, we can avoid permission problems, and we can also make the sandbox stronger - for example, by not giving it access to the partial/ directory anymore.</p>
<p>Another change we need to work on is standardising the <code>Important</code> field, which is sort of like essential - it marks an installed package as extra-hard to remove (but unlike <code>Essential</code>, does not cause apt to install it automatically). The latest draft calls it <code>Protected</code>, but I don&rsquo;t think we have a consensus on that yet.</p>
<p>I also need to get happy eyeballs done - fast fallback from IPv6 to IPv4. I had a completely working solution some months ago, but it did not pass CI, so I decided to start from scratch with a cleaner design to figure out if I went wrong somewhere. Testing this is kind of hard, as it basically requires a broken IPv6 setup (well, unreachable IPv6 servers).</p>
<p>Oh well, 2018 has begun, so I&rsquo;m going to stop now. Let&rsquo;s all do our best to make it awesome!</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>APT 1.6 alpha 1 - seccomp and more</title>
      <link>https://blog.jak-linux.org/2017/10/23/apt-1-6-alpha-1-uploaded/</link>
      <pubDate>Mon, 23 Oct 2017 00:44:01 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2017/10/23/apt-1-6-alpha-1-uploaded/</guid>
      <description>&lt;p&gt;I just uploaded APT 1.6 alpha 1, introducing a very scary thing: Seccomp sandboxing for methods, the programs downloading files from the internet and decompressing or compressing stuff. With seccomp I reduced the number of system calls these methods can use to 149 from 430. Specifically we excluded most ways of IPC, xattrs, and most importantly, the ability for methods to &lt;code&gt;clone(2)&lt;/code&gt;, &lt;code&gt;fork(2)&lt;/code&gt;, &lt;code&gt;execve(2)&lt;/code&gt;, and &lt;code&gt;execveat(2)&lt;/code&gt;. Yes, that&amp;rsquo;s right - methods can no longer execute programs.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I just uploaded APT 1.6 alpha 1, introducing a very scary thing: Seccomp sandboxing for methods, the programs downloading files from the internet and decompressing or compressing stuff. With seccomp I reduced the number of system calls these methods can use to 149 from 430. Specifically we excluded most ways of IPC, xattrs, and most importantly, the ability for methods to <code>clone(2)</code>, <code>fork(2)</code>, <code>execve(2)</code>, and <code>execveat(2)</code>. Yes, that&rsquo;s right - methods can no longer execute programs.</p>
<p>This was a real problem, because the http method did in fact execute programs - there is this small option called <code>ProxyAutoDetect</code> or <code>Proxy-Auto-Detect</code> where you can specify a script to run for an URL and the script outputs a (list of) proxies. In order to be able to seccomp the http method, I moved the invocation of the script to the parent process. The parent process now executes the script within the sandbox user, but without seccomp (obviously).</p>
<p>I tested the code on amd64, ppc64el, s390x, arm64, mipsel, i386, and armhf. I hope it works on all other architectures libseccomp is currently built for in Debian, but I did not check that, so your apt might be broken now if you use powerpc, powerpcspe, armel, mips, mips64el, hhpa, or x32 (I don&rsquo;t think you can even really use x32).</p>
<p>Also, apt-transport-https is gone for good now. When installing the new apt release, any installed apt-transport-https package is removed (apt breaks apt-transport-https now, but it also provides it versioned, so any dependencies should still be satisfiable).</p>
<p>David also did a few cool bug fixes again, finally teaching apt-key to ignore unsupported GPG key files instead of causing weird errors :)</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>APT 1.5 is out</title>
      <link>https://blog.jak-linux.org/2017/09/24/apt-1-5-is-out/</link>
      <pubDate>Sun, 24 Sep 2017 19:32:10 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2017/09/24/apt-1-5-is-out/</guid>
      <description>&lt;p&gt;APT 1.5 is out, after almost 3 months the release of 1.5 alpha 1, and almost six months since the release of 1.4 on April 1st. This release cycle was unusually short, as 1.4 was the stretch release series and the zesty release series, and we waited for the latter of these releases before we started 1.5. In related news, 1.4.8 hit stretch-proposed-updates today, and is waiting in the unapproved queue for zesty.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>APT 1.5 is out, after almost 3 months the release of 1.5 alpha 1, and almost six months since the release of 1.4 on April 1st. This release cycle was unusually short, as 1.4 was the stretch release series and the zesty release series, and we waited for the latter of these releases before we started 1.5. In related news, 1.4.8 hit stretch-proposed-updates today, and is waiting in the unapproved queue for zesty.</p>
<p>This release series moves https support from apt-transport-https into apt proper, bringing with it support for https:// proxies, and support for autodetectproxy scripts that return http, https, and socks5h proxies for both http and https.</p>
<p>Unattended updates and upgrades now work better: The dependency on network-online was removed and we introduced a meta wait-online helper with support for NetworkManager, systemd-networkd, and connman that allows us to wait for network even if we want to run updates directly after a resume (which might or might not have worked before, depending on whether update ran before or after network was back up again). This also improves a boot performance regression for systems with rc.local files:</p>
<p>The rc.local.service unit specified <code>After=network-online.target</code>, and login stuff was <code>After=rc.local.service</code>, and apt-daily.timer was <code>Wants=network-online.target</code>, causing network-online.target to be pulled into the boot and the rc.local.service ordering dependency to take effect, significantly slowing down the boot.</p>
<p>An earlier less intrusive variant of that fix is in 1.4.8: It just moves the network-online.target Want/After from apt-daily.timer to apt-daily.service so most boots are uncoupled now. I hope we get the full solution into stretch in a later point release, but we should gather some experience first before discussing this with the release time.</p>
<p>Balint Reczey also provided a patch to increase the time out before killing the daily upgrade service to 15 minutes, to actually give unattended-upgrades some time to finish an in-progress update. Honestly, I&rsquo;d have though the machine hung up and force rebooted it after 5 seconds already. (this patch is also in 1.4.8)</p>
<p>We also made sure that unreadable config files no longer cause an error, but only a warning, as that was sort of a regression from previous releases; and we added documentation for /etc/apt/auth.conf, so people actually know the preferred way to place sensitive data like passwords (and can make their sources.list files world-readable again).</p>
<p>We also fixed apt-cdrom to support discs without MD5 hashes for Sources (the Files field), and re-enabled support for udev-based detection of cdrom devices which was accidentally broken for 4 years, as it was trying to load libudev.so.0 at runtime, but that library had an SONAME change to libudev.so.1 - we now link against it normally.</p>
<p>Furthermore, if certain information in Release files change, like the codename, apt will now request confirmation from the user, avoiding a scenario where a user has stable in their sources.list and accidentally upgrades to the next release when it becomes stable.</p>
<p>Paul Wise contributed patches to allow configuring the apt-daily intervals more easily - apt-daily is invoked twice a day by systemd but has more fine-grained internal timestamp files. You can now specify the intervals in seconds, minutes, hours, and day units, or specify &ldquo;always&rdquo; to always run (that is, up to twice a day on systemd, once per day on non-systemd platforms).</p>
<p>Development for the 1.6 series has started, and I intent to upload a first alpha to unstable in about a week, removing the apt-transport-https package and enabling compressed index files by default (save space, a lot of space, at not much performance cost thanks to lz4). There will also be some small clean ups in there, but I don&rsquo;t expect any life-changing changes for now.</p>
<p>I think our new approach of uploading development releases directly to unstable instead of parking them in experimental is working out well. Some people are confused why alpha releases appear in unstable, but let me just say one thing: These labels basically just indicate feature-completeness, and not stability. An alpha is just very likely to get a lot more features, a beta is less likely (all the big stuff is in), and the release candidates just fix bugs.</p>
<p>Also, we now have 3 active stable series: The 1.2 LTS series, 1.4 medium LTS, and 1.5. 1.2 receives updates as part of Ubuntu 16.04 (xenial), 1.4 as part of Debian 9.0 (stretch) and Ubuntu 17.04 (zesty); whereas 1.5 will only be supported for 9 months (as part of Ubuntu 17.10). I think the stable release series are working well, although 1.4 is a bit tricky being shared by stretch and zesty right now (but zesty is history soon, so &hellip;).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Why TUF does not shine (for APT repositories)</title>
      <link>https://blog.jak-linux.org/2017/08/17/why-tuf-does-not-shine-for-apt-repositories/</link>
      <pubDate>Thu, 17 Aug 2017 19:47:49 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2017/08/17/why-tuf-does-not-shine-for-apt-repositories/</guid>
      <description>&lt;p&gt;In DebConf17 there was a talk about The Update Framework, short TUF. TUF claims to be a plug-in solution to software updates, but while it has the same practical level of security as apt, it also has the same shortcomings, including no way to effectively revoke keys.&lt;/p&gt;
&lt;p&gt;TUF divides signing responsibilities into roles: A root role, a targets rule (signing stuff to download), a snapshots rule (signing meta data), and a time stamp rule (signing a time stamp file). There also is a mirror role for signing a list of mirrors, but we can ignore that for now. It strongly recommends that all keys except for timestamp and mirrors are kept offline, which is not applicable for APT repositories - Ubuntu updates the repository every 30 minutes, imagine doing that with offline keys. An insane proposal.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>In DebConf17 there was a talk about The Update Framework, short TUF. TUF claims to be a plug-in solution to software updates, but while it has the same practical level of security as apt, it also has the same shortcomings, including no way to effectively revoke keys.</p>
<p>TUF divides signing responsibilities into roles: A root role, a targets rule (signing stuff to download), a snapshots rule (signing meta data), and a time stamp rule (signing a time stamp file). There also is a mirror role for signing a list of mirrors, but we can ignore that for now. It strongly recommends that all keys except for timestamp and mirrors are kept offline, which is not applicable for APT repositories - Ubuntu updates the repository every 30 minutes, imagine doing that with offline keys. An insane proposal.</p>
<p>In APT repositories, we effectively only have a snapshots rule - the only thing we sign are Release files, and trust is then chained down by hashes (Release files hashes Packages index files, and they have hashes of individual packages). The keys used to sign repositories are online keys, after all, all the metadata files change every 30 minutes (Ubuntu) or 6 hours (Debian) - it&rsquo;s impossible to sign them by hand. The timestamp role is replaced by a field in the Release file specifying until when the Release file is considered valid.</p>
<p>Let&rsquo;s check the <a href="https://github.com/theupdateframework/tuf/blob/develop/docs/tuf-spec.md#1-introduction">attacks TUF protects again</a>:</p>
<ul>
<li>Arbitrary installation attacks. - We protect against that with the outer signature and hashes</li>
<li>Endless data attacks. - Yes, we impose a limit on Release files (the sizes of other files are specified in there and this file is signed)</li>
<li>Extraneous dependencies attacks - That&rsquo;s verified by the signed hashes of Packages files</li>
<li>Fast-forward attacks - same</li>
<li>Indefinite freeze attacks - APT has a Valid-Until field that can be used to specify a maximum life time of a release file</li>
<li>Malicious mirrors preventing updates. - Well, the user configures the mirror, so usually not applicable. if the user has multiple mirrors, APT deals with that fine</li>
<li>Mix-and-match attacks - Again, signed Release file and hashes of other files</li>
<li>Rollback attacks - We do not allow Date fields in Release files to go backwards</li>
<li>Slow retrieval attacks - TUF cannot protect against that either. APT has very high timeouts, and there is no reasonable answer to that.</li>
<li>Vulnerability to key compromises - For our purposes where we need all repository signing keys to be online, as we need to sign new releases and metadata fairly often, it does not make it less vulnerable to require a threshold of keys (APT allows repositories to specify concrete key ids they may be signed with though, that has the same effect)</li>
<li>Wrong software installation. - Does not happen, the .deb files are hashed in the Packages files which are signed by the release file</li>
</ul>
<p>As we can see, APT addresses all attacks TUF addresses.</p>
<p>But both do not handle key revocation. So, if a key &amp; mirror gets compromised (or just key and the mirror is MITMed), we cannot inform the user that the key has been compromised and block updates from the compromised repository.</p>
<p>I just wrote up a <a href="https://lists.debian.org/deity/2017/08/msg00067.html">proposal to allow APT to query for revoked keys from a different host</a> with a key revocation list (KRL) file that is signed by different keys than the repository. This would solve the problem of key revocation easily - even if the repository host is MITMed or compromised, we can still revoke the keys signing the repository from a different location.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>jak-linux.org moved / backing up</title>
      <link>https://blog.jak-linux.org/2017/02/15/jak-linux-org-moved-backing-up-to/</link>
      <pubDate>Tue, 14 Feb 2017 23:51:38 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2017/02/15/jak-linux-org-moved-backing-up-to/</guid>
      <description>&lt;p&gt;In the past two days, I moved my main web site jak-linux.org (and jak-software.de) from a very old contract at STRATO over to something else: The domains are registered with &lt;a href=&#34;https://www.inwx.de/&#34;&gt;INWX&lt;/a&gt; and the hosting is handled by &lt;a href=&#34;https://uberspace.de/&#34;&gt;uberspace.de&lt;/a&gt;. Encryption is provided by &lt;a href=&#34;https://letsencrypt.org/&#34;&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I requested the domain transfer from STRATO on Monday at 16:23, received the auth codes at 20:10 and the .de domain was transferred completely on 20:36 (about 20 minutes if you count my overhead). The .org domain I had to ACK, which I did at 20:46 and at 03:00 I received the notification that the transfer was successful (I think there was some registrar ACKing involved there). So the whole transfer took about 10 1/2 hours, or 7 hours since I retrieved the auth code. I think that&amp;rsquo;s quite a good time :)&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>In the past two days, I moved my main web site jak-linux.org (and jak-software.de) from a very old contract at STRATO over to something else: The domains are registered with <a href="https://www.inwx.de/">INWX</a> and the hosting is handled by <a href="https://uberspace.de/">uberspace.de</a>. Encryption is provided by <a href="https://letsencrypt.org/">Let&rsquo;s Encrypt</a>.</p>
<p>I requested the domain transfer from STRATO on Monday at 16:23, received the auth codes at 20:10 and the .de domain was transferred completely on 20:36 (about 20 minutes if you count my overhead). The .org domain I had to ACK, which I did at 20:46 and at 03:00 I received the notification that the transfer was successful (I think there was some registrar ACKing involved there). So the whole transfer took about 10 1/2 hours, or 7 hours since I retrieved the auth code. I think that&rsquo;s quite a good time :)</p>
<p>And, for those of you who don&rsquo;t know: uberspace is a shared hoster that basically just gives you an SSH shell account, directories for you to drop files in for the http server, and various tools to add subdomains, certificates, virtual users to the mailserver. You can also run your own custom build software and open ports in their firewall. That&rsquo;s quite cool.</p>
<p>I&rsquo;m considering migrating the blog away from wordpress at some point in the future - having a more integrated experience is a bit nicer than having my web presence split over two sites. I&rsquo;m unsure if I shouldn&rsquo;t add something like cloudflare there - I don&rsquo;t want to overload the servers (but I only serve static pages, so how much load is this really going to get?).</p>
<h2 id="in-other-news-off-site-backups">in other news: off-site backups</h2>
<p>I also recently started doing offsite backups via borg to a server operated by the wonderful <a href="http://rsync.net/">rsync.net</a>. For those of you who do not know rsync.net: You basically get SSH to a server where you can upload your backups via common tools like rsync, scp, or you can go crazy and use git-annex, borg, attic; or you could even just plain <code>zfs send</code> your stuff there.</p>
<p>The normal price is $0.08 per GB per month, but there is a <a href="http://rsync.net/products/attic.html">special borg price of $0.03</a> (that price does not include snapshotting or support, really). You can also get a discounted normal account for $0.04 if you find the correct code on Hacker News, or other discounts for open source developers, students, etc. - you just have to send them an email.</p>
<p>Finally, I must say that uberspace and rsync.net feel similar in spirit. Both heavily emphasise the command line, and don&rsquo;t really have any fancy click stuff. I like that.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Starting the faster, more secure APT 1.4 series</title>
      <link>https://blog.jak-linux.org/2016/11/26/starting-the-faster-more-secure-apt-1-4-series/</link>
      <pubDate>Fri, 25 Nov 2016 23:42:20 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2016/11/26/starting-the-faster-more-secure-apt-1-4-series/</guid>
      <description>&lt;p&gt;We just released the first beta of APT 1.4 to Debian unstable (beta here means that we don&amp;rsquo;t know any other big stuff to add to it, but are still open to further extensions). This is the release series that will be released with Debian stretch, Ubuntu zesty, and possibly Ubuntu zesty+1 (if the Debian freeze takes a very long time, even zesty+2 is possible). It should reach the master archive in a few hours, and your mirrors shortly after that.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>We just released the first beta of APT 1.4 to Debian unstable (beta here means that we don&rsquo;t know any other big stuff to add to it, but are still open to further extensions). This is the release series that will be released with Debian stretch, Ubuntu zesty, and possibly Ubuntu zesty+1 (if the Debian freeze takes a very long time, even zesty+2 is possible). It should reach the master archive in a few hours, and your mirrors shortly after that.</p>
<h2 id="security-changes">Security changes</h2>
<p>APT 1.4 by default disables support for repositories signed with SHA1 keys. I announced back in January that it was my intention to do this during the summer for development releases, but I only remembered the Jan 1st deadline for stable releases supporting that (APT 1.2 and 1.3), so better late than never.</p>
<p>Around January 1st, the same or a similar change will occur in the APT 1.2 and 1.3 series in Ubuntu 16.04 and 16.10 (subject to approval by Ubuntu&rsquo;s release team). This should mean that repository provides had about one year to fix their repositories, and more than 8 months since the release of 16.04. I believe that 8 months is a reasonable time frame to upgrade a repository signing key, and hope that providers who have not updated their repositories yet will do so as soon as possible.</p>
<h2 id="performance-work">Performance work</h2>
<p>APT 1.4 provides a 10-20% performance increase in cache generation (and according to callgrind, we went from approx 6.8 billion to 5.3 billion instructions for my laptop&rsquo;s configuration, a reduction of more than 21%). The major improvements are:</p>
<p>We switched the parsing of Deb822 files (such as Packages files) to my perfect hash function <a href="https://github.com/julian-klode/triehash">TrieHash</a>. TrieHash - which generates C code from a set of words - is about equal or twice as fast as the previously used hash function (and <em>two to three times faster</em> than gperf), and we save an additional 50% of that time as we only have to hash once during parsing now, instead of during look up as well. APT 1.4 marks the first time TrieHash is used in any software. I hope that it will spread to dpkg and other software at a later point in time.vendors.</p>
<p>Another important change was to drop normalization of Description-MD5 values, the fields mapping a description in a Packages files to a translated description. We used to parse the hex digits into a native binary stream, and then compared it back to hex digits for comparisons, which cost us about 5% of the run time performance.</p>
<p>We also optimized one of our hash functions - the VersionHash that hashes the important fields of a package to recognize packages with the same version, but different content - to not normalize data to a temporary buffer anymore. This buffer has been the subject of some bugs (overflow, incompleteness) in the recent past, and also caused some slowdown due to the additional writes to the stack. Instead, we now pass the bytes we are interested in directly to our CRC code, one byte at a time.</p>
<p>There were also some other micro-optimisations: For example, the hash tables in the cache used to be ordered by standard compare (alphabetical followed by shortest). It is now ordered by size first, meaning we can avoid data comparisons for strings of different lengths. We also got rid of a std::string that cannot use short string optimisation in a hot path of the code. Finally, we also converted our case-insensitive djb hashes to not use a normal tolower_ascii(), but introduced tolower_ascii_unsafe() which just sets the &ldquo;lowercase bit&rdquo; (| 0x20) in the character.</p>
<h2 id="others">Others</h2>
<ul>
<li>Sandboxing now removes some environment variables like TMP from the environment.</li>
<li>Several improvements to installation ordering.</li>
<li>Support for armored GPG keys in trusted.gpg.d.</li>
<li>Various other fixes</li>
</ul>
<p>For a more complete overview of all changes, consult the changelog.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Introducing DNS66, a host blocker for Android</title>
      <link>https://blog.jak-linux.org/2016/10/25/introducing-dns66-a-host-blocker-for-android/</link>
      <pubDate>Tue, 25 Oct 2016 16:19:50 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2016/10/25/introducing-dns66-a-host-blocker-for-android/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;https://juliank.files.wordpress.com/2016/10/ic_launcher.png&#34; alt=&#34;ic_launcher&#34;&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m proud (yes, really) to announce &lt;strong&gt;DNS66&lt;/strong&gt;, my host/ad blocker for Android 5.0 and newer. It&amp;rsquo;s been around since last Thursday on F-Droid, but it never really got a formal announcement.&lt;/p&gt;
&lt;p&gt;DNS66 creates a local VPN service on your Android device, and diverts all DNS traffic to it, possibly adding new DNS servers you can configure in its UI. It can use hosts files for blocking whole sets of hosts or you can just give it a domain name to block (or multiple hosts files/hosts). You can also whitelist individual hosts or entire files by adding them to the end of the list. When a host name is looked up, the query goes to the VPN which looks at the packet and responds with NXDOMAIN (non-existing domain) for hosts that are blocked.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p><img src="https://juliank.files.wordpress.com/2016/10/ic_launcher.png" alt="ic_launcher"></p>
<p>I&rsquo;m proud (yes, really) to announce <strong>DNS66</strong>, my host/ad blocker for Android 5.0 and newer. It&rsquo;s been around since last Thursday on F-Droid, but it never really got a formal announcement.</p>
<p>DNS66 creates a local VPN service on your Android device, and diverts all DNS traffic to it, possibly adding new DNS servers you can configure in its UI. It can use hosts files for blocking whole sets of hosts or you can just give it a domain name to block (or multiple hosts files/hosts). You can also whitelist individual hosts or entire files by adding them to the end of the list. When a host name is looked up, the query goes to the VPN which looks at the packet and responds with NXDOMAIN (non-existing domain) for hosts that are blocked.</p>
<p>You can find DNS66 here:</p>
<ul>
<li>on GitHub: <a href="https://github.com/julian-klode/dns66">https://github.com/julian-klode/dns66</a></li>
<li>on F-Droid: <a href="https://f-droid.org/app/org.jak_linux.dns66">https://f-droid.org/app/org.jak_linux.dns66</a></li>
</ul>
<p>F-Droid is the recommended source to install from. DNS66 is licensed under the GNU GPL 3, or (mostly) any later version.</p>
<h2 id="implementation-notes">Implementation Notes</h2>
<p>DNS66&rsquo;s core logic is based on another project, <a href="https://github.com/dbrodie/AdBuster">dbrodie/AdBuster</a>, which arguably has the cooler name. I translated that from Kotlin to Java, and cleaned up the implementation a bit:</p>
<p>All work is done in a single thread by using poll() to detect when to read/write stuff. Each DNS request is sent via a new UDP socket, and poll() polls over all UDP sockets, a Device Socket (for the VPN&rsquo;s tun device) and a pipe (so we can interrupt the poll at any time by closing the pipe).</p>
<p>We literally redirect your DNS servers. Meaning if your DNS server is 1.2.3.4, all traffic to 1.2.3.4 is routed to the VPN. The VPN only understands DNS traffic, though, so you might have trouble if your DNS server also happens to serve something else. I plan to change that at some point to emulate multiple DNS servers with fake IPs, but this was a first step to get it working with fallback: Android can now transparently fallback to other DNS servers without having to be aware that they are routed via the VPN.</p>
<p>We also need to deal with timing out queries that we received no answer for: DNS66 stores the query into a LinkedHashMap and overrides the removeEldestEntry() method to remove the eldest entry if it is older than 10 seconds or there are more than 1024 pending queries. This means that it only times out up to one request per new request, but it eventually cleans up fine.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Introducing TrieHash, a order-preserving minimal perfect hash function generator for C(&#43;&#43;)</title>
      <link>https://blog.jak-linux.org/2016/09/25/introducing-triehash-a-order-preserving-minimal-perfect-hash-function-generator-for-c/</link>
      <pubDate>Sun, 25 Sep 2016 18:22:43 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2016/09/25/introducing-triehash-a-order-preserving-minimal-perfect-hash-function-generator-for-c/</guid>
      <description>&lt;h2 id=&#34;abstract&#34;&gt;Abstract&lt;/h2&gt;
&lt;p&gt;I introduce TrieHash an algorithm for constructing perfect hash functions from tries. The generated hash functions are pure C code, minimal, order-preserving and outperform existing alternatives. Together with the generated header files,they can also be used as a generic string to enumeration mapper (enums are created by the tool).&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;APT (and dpkg) spend a lot of time in parsing various files, especially Packages files. APT currently uses a function called AlphaHash which hashes the last 8 bytes of a word in a case-insensitive manner to hash fields in those files (dpkg just compares strings in an array of structs).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <h2 id="abstract">Abstract</h2>
<p>I introduce TrieHash an algorithm for constructing perfect hash functions from tries. The generated hash functions are pure C code, minimal, order-preserving and outperform existing alternatives. Together with the generated header files,they can also be used as a generic string to enumeration mapper (enums are created by the tool).</p>
<h2 id="introduction">Introduction</h2>
<p>APT (and dpkg) spend a lot of time in parsing various files, especially Packages files. APT currently uses a function called AlphaHash which hashes the last 8 bytes of a word in a case-insensitive manner to hash fields in those files (dpkg just compares strings in an array of structs).</p>
<p>There is one obvious drawback to using a normal hash function: When we want to access the data in the hash table, we have to hash the key again, causing us to hash every accessed key at least twice. It turned out that this affects something like 5 to 10% of the cache generation performance.</p>
<p>Enter perfect hash functions: A perfect hash function matches a set of words to constant values without collisions. You can thus just use the index to index into your hash table directly, and do not have to hash again (if you generate the function at compile time and store key constants) or handle collision resolution.</p>
<p>As #debian-apt people know, I happened to play a bit around with tries this week before guillem suggested perfect hashing. Let me tell you one thing: My trie implementation was very naive, that did not really improve things a lot&hellip;</p>
<h2 id="enter-triehash">Enter TrieHash</h2>
<p>Now, how is this related to hashing? The answer is simple: I wrote a perfect hash function generator that is based on tries. You give it a list of words, it puts them in a trie, and generates C code out of it, using recursive switch statements (see code generation below). The function achieves competitive performance with other hash functions, it even usually outperforms them.</p>
<p>Given a dictionary, it generates an enumeration (a C <code>enum</code> or C++ <code>enum class</code>) of all words in the dictionary, with the values corresponding to the order in the dictionary (the order-preserving property), and a function mapping strings to members of that enumeration.</p>
<p>By default, the first word is considered to be 0 and each word increases a counter by one (that is, it generates a minimal hash function). You can tweak that however:</p>
<pre><code>= 0
WordLabel ~ Word
OtherWord = 9
</code></pre>
<p>will return 0 for an unknown value, map &ldquo;Word&rdquo; to the enum member <code>WordLabel</code> and map OtherWord to 9. That is, the input list functions like the body of a C enumeration. If no label is specified for a word, it will be generated from the word. For more details see the documentation</p>
<h3 id="c-code-generation">C code generation</h3>
<pre><code>switch(string[0] | 32) {
case 't':
    switch(string[1] | 32) {
    case 'a':
        switch(string[2] | 32) {
        case 'g':
            return Tag;
        }
    }
}
return Unknown;
</code></pre>
<p>Yes, really recursive switches - they directly represent the trie. Now, we did not really do a straightforward translation, there are some optimisations to make the whole thing faster and easier to look at:</p>
<p>First of all, the <code>32</code> you see is used to make the check case insensitive in case all cases of the switch body are alphabetical characters. If there are non-alphabetical characters, it will generate two cases per character, one upper case and one lowercase (with one break in it). I did not know that lowercase and uppercase characters differed by only one bit before, thanks to the clang compiler for pointing that out in its generated assembler code!</p>
<p>Secondly, we only insert breaks only between cases. Initially, each case ended with a return Unknown, but guillem (the dpkg developer) suggested it might be faster to let them fallthrough where possible. Turns out it was not faster on a good compiler, but it&rsquo;s still more readable anywhere.</p>
<p>Finally, we build one trie per word length, and switch by the word length first. Like the 32 trick, his gives a huge improvement in performance.</p>
<h2 id="digging-into-the-assembler-code">Digging into the assembler code</h2>
<p>The whole code translates to roughly 4 instructions per byte:</p>
<ol>
<li>A memory load,</li>
<li>an or with 32</li>
<li>a comparison, and</li>
<li>a conditional jump.</li>
</ol>
<p>(On x86, the case sensitive version actually only has a cmp-with-memory and a conditional jump).</p>
<p>Due to <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77729">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77729</a> this may be one instruction more: On some architectures an unneeded zero-extend-byte instruction is inserted - this causes a 20% performance loss.</p>
<h2 id="performance-evaluation">Performance evaluation</h2>
<p>I run the hash against all 82 words understood by APT in Packages and Sources files, 1,000,000 times for each word, and summed up the average run-time:</p>
<!-- raw HTML omitted -->
<p>Suffice to say, GPerf does not really come close.</p>
<p>All hosts except the x230 are Debian porterboxes. The x230 is my laptop with a a Core i5-3320M, barriere has an Opteron 23xx. I included the DJB hash function for another reference.</p>
<h2 id="source-code">Source code</h2>
<p>The generator is written in Perl, licensed under the MIT license and available from <a href="https://github.com/julian-klode/triehash">https://github.com/julian-klode/triehash</a> - I initially prototyped it in Python, but guillem complained that this would add new build dependencies to dpkg, so I rewrote it in Perl.</p>
<p>Benchmark is available from <a href="https://github.com/julian-klode/hashbench">https://github.com/julian-klode/hashbench</a></p>
<h2 id="usage">Usage</h2>
<p>See the script for POD documentation.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>New software: sicherboot</title>
      <link>https://blog.jak-linux.org/2016/09/07/new-software-sicherboot/</link>
      <pubDate>Tue, 06 Sep 2016 22:12:12 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2016/09/07/new-software-sicherboot/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://github.com/julian-klode/sicherboot&#34;&gt;&lt;img src=&#34;https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67&#34; alt=&#34;Fork me on GitHub&#34;&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Today, I wrote &lt;em&gt;&lt;a href=&#34;https://github.com/julian-klode/sicherboot&#34;&gt;sicherboot&lt;/a&gt;&lt;/em&gt;, a tool to integrate systemd-boot into a Linux distribution in an entirely new way: With secure boot support. To be precise: The use case here is to only run trusted code which then unmounts an otherwise fully encrypted disk, as in my setup:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://juliank.files.wordpress.com/2016/09/screenshot-from-2016-09-06-04-09-52.png&#34; alt=&#34;screenshot-from-2016-09-06-04-09-52&#34;&gt;&lt;/p&gt;
&lt;p&gt;If you want, sicherboot automatically creates db, KEK, and PK keys, and puts the public keys on your EFI System Partition (ESP) together with the KeyTool tool, so you can enroll the keys in UEFI. You can of course also use other keys, you just need to drop a db.crt and a db.key file into &lt;code&gt;/etc/sicherboot/keys&lt;/code&gt;. It would be nice if sicherboot could enroll the keys directly in Linux, but there seems to be a &lt;a href=&#34;https://bugs.debian.org/836770&#34;&gt;bug in efitools&lt;/a&gt; preventing that at the moment. For some background: The Platform Key (PK) signs the Key Exchange Key (KEK) which signs the database key (db). The db key is the one signing binaries.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p><a href="https://github.com/julian-klode/sicherboot"><img src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub">
</a></p>
<p>Today, I wrote <em><a href="https://github.com/julian-klode/sicherboot">sicherboot</a></em>, a tool to integrate systemd-boot into a Linux distribution in an entirely new way: With secure boot support. To be precise: The use case here is to only run trusted code which then unmounts an otherwise fully encrypted disk, as in my setup:</p>
<p><img src="https://juliank.files.wordpress.com/2016/09/screenshot-from-2016-09-06-04-09-52.png" alt="screenshot-from-2016-09-06-04-09-52"></p>
<p>If you want, sicherboot automatically creates db, KEK, and PK keys, and puts the public keys on your EFI System Partition (ESP) together with the KeyTool tool, so you can enroll the keys in UEFI. You can of course also use other keys, you just need to drop a db.crt and a db.key file into <code>/etc/sicherboot/keys</code>. It would be nice if sicherboot could enroll the keys directly in Linux, but there seems to be a <a href="https://bugs.debian.org/836770">bug in efitools</a> preventing that at the moment. For some background: The Platform Key (PK) signs the Key Exchange Key (KEK) which signs the database key (db). The db key is the one signing binaries.</p>
<p>sicherboot also handles installing new kernels to your ESP. For this, it combines the kernel with its initramfs into one executable UEFI image, and then signs that. Combined with a fully encrypted disk setup, this assures that only you can run UEFI binaries on the system, and attackers cannot boot any other operating system or modify parts of your operating system (except for, well, any block of your encrypted data, as XTS does not authenticate the data; but then you do have to know which blocks are which which is somewhat hard).</p>
<p>sicherboot integrates with various parts of Debian: It can work together by dracut via an evil hack (diverting dracut&rsquo;s <code>kernel/postinst.d</code> config file, so we can run sicherboot after running dracut), it should support initramfs-tools (untested), and it also integrates with systemd upgrades via triggers on the <code>/usr/lib/systemd/boot/efi</code> directory.</p>
<p>Currently sicherboot only supports Debian-style setups with <code>/boot/vmlinuz-&lt;version&gt;</code> and <code>/boot/initrd.img-&lt;version</code>&gt; files, it cannot automatically create combined boot images from or install boot loader entries for other naming schemes yet. Fixing that should be trivial though, with a configuration setting and some eval magic (or string substitution).</p>
<p>Future planned features include: (1) support for multiple ESP partitions, so you can have a fallback partition on a different drive (think RAID type situation, keep one ESP on each drive, so you can remove a failing one); and (2) a tool to create a self-contained rescue disk image from a directory (which will act as initramfs) and a kernel (falling back to a <code>vmlinuz</code> file )</p>
<p>It might also be interesting to add support for other bootloaders and setups, so you could automatically sign a grub cryptodisk image for example. Not sure how much sense that makes.</p>
<p>I published the source at <a href="https://github.com/julian-klode/sicherboot">https://github.com/julian-klode/sicherboot</a> (MIT licensed) and uploaded the package to Debian, it should enter the NEW queue soon (or be in NEW by the time you read this). Give it a try, and let me know what you think.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>apt 1.3 RC4 - Tweaking apt update</title>
      <link>https://blog.jak-linux.org/2016/09/02/tweaking-apt-update/</link>
      <pubDate>Fri, 02 Sep 2016 19:43:25 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2016/09/02/tweaking-apt-update/</guid>
      <description>&lt;p&gt;Did that ever happen to you: You run apt update, it fetches a Release file, then starts fetching DEP-11 metadata, then any pdiff index stuff, and then applies them; all after another? Or this: You don&amp;rsquo;t see any update progress until very near the end? Worry no more: I tweaked things a bit in 1.3~rc4 (&lt;a href=&#34;https://anonscm.debian.org/cgit/apt/apt.git/commit/?id=2a440328ea19e9646a93f847dd9eff21e03ad16d&#34;&gt;git commit&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Prior to 1.3~rc4, acquiring the files for an update worked like this: We create some object for the Release file, once a release file is done we queue any next object (DEP-11 icons, .diff/Index files, etc). There is no prioritizing, so usually we fetch the 5MB+ DEP-11 icons and components files first, and only then start working on other indices which might use Pdiff.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Did that ever happen to you: You run apt update, it fetches a Release file, then starts fetching DEP-11 metadata, then any pdiff index stuff, and then applies them; all after another? Or this: You don&rsquo;t see any update progress until very near the end? Worry no more: I tweaked things a bit in 1.3~rc4 (<a href="https://anonscm.debian.org/cgit/apt/apt.git/commit/?id=2a440328ea19e9646a93f847dd9eff21e03ad16d">git commit</a>).</p>
<p>Prior to 1.3~rc4, acquiring the files for an update worked like this: We create some object for the Release file, once a release file is done we queue any next object (DEP-11 icons, .diff/Index files, etc). There is no prioritizing, so usually we fetch the 5MB+ DEP-11 icons and components files first, and only then start working on other indices which might use Pdiff.</p>
<p>In 1.3~rc4 I changed the queues to be priority queues: Release files and .diff/Index files have the highest priority (once we have them all, we know how much to fetch). The second level of priority goes to the .pdiff files which are later on passed to the rred process to patch an existing Packages, Sources, or Contents file. The third priority level is taken by all other index targets.</p>
<p>Actually, I implemented the priority queues back in Jun. There was just one tiny problem: Pipelining. We might be inserting elements into our fetching queues in order of priority, but with pipelining enabled, stuff of lower priority might already have their HTTP request sent before we even get to queue the higher priority stuff.</p>
<p>Today I had an epiphany: We fill the pipeline up to a number of items (the depth, currently 10). So, let&rsquo;s just fill the pipeline with items that have the same (or higher) priority than the maximum priority of the already-queued ones; and pretend it is full when we only have lower priority items.</p>
<p>And that works fine: First the Release and .diff/Index stuff is fetched, which means we can start showing <em>accurate progress info</em> from there one. Next, the pdiff files are fetched, meaning that we can <em>apply them in parallel</em> to any targets downloading later in parallel (think DEP-11 icon tarballs).</p>
<p>This has a great effect on performance: For the 01 Sep 2016 03:35:23 UTC -&gt; 02 Sep 2016 09:25:37 update of Debian unstable and testing with Contents and appstream for amd64 and i386, update time reduced from 37 seconds to 24-28 seconds.</p>
<h2 id="in-other-news">In other news</h2>
<p>I recently cleaned up the apt packaging which renamed /usr/share/bug/apt/script to /usr/share/bug/apt. That broke on overlayfs, because dpkg could not rename the old apt directory to a backup name during unpack (only directories purely on the upper layer can be renamed). I reverted that now, so all future updates should be fine.</p>
<p>David re-added the Breaks against apt-utils I recently removed by accident during the cleanup, so no more errors about overriding dump solvers. He also added support for fingerprints in gpgv&rsquo;s GOODSIG output, which apparently might come at some point.</p>
<p>I Also fixed a few CMake issues, fixed the test suite for gpgv 2.1.15, allow building with a system-wide gtest library (we really ought to add back a pre-built one in Debian), and modified debian/rules to pass -O to make. I wish debhelper would do the latter automatically (there&rsquo;s a bug for that).</p>
<p>Finally, we fixed some uninitialized variables in the base256 code, out-of-bound reads in the Sources file parser, off-by-one errors in the tagfile comment stripping code[1], and some memcpy() with length 0. Most of these will be cherry-picked into the 1.2 (xenial) and 1.0.9.8 (jessie) branches (releases 1.2.15 and 1.0.9.8.4). If you forked off your version of apt at another point, you might want to do the same.</p>
<p>[1] those were actually causing the failures and segfaults in the unit tests on hurd-i386 buildds. I always thought it was a hurd-specific issue&hellip;</p>
<p>PS. Building for Fedora on OBS has a weird socket fd #3 that does not get closed during the test suite despite us setting CLOEXEC on it. Join us in #debian-apt on oftc if you have ideas.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Porting APT to CMake</title>
      <link>https://blog.jak-linux.org/2016/08/10/porting-apt-to-cmake/</link>
      <pubDate>Wed, 10 Aug 2016 15:52:12 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2016/08/10/porting-apt-to-cmake/</guid>
      <description>&lt;p&gt;Ever since it&amp;rsquo;s creation back in the dark ages, APT shipped with it&amp;rsquo;s own build system consisting of autoconf and a bunch of makefiles. In 2009, I felt like replacing that with something more standard, and because nobody really liked autotools, decided to go with CMake. Well, the bazaar branch was never really merged back in 2009.&lt;/p&gt;
&lt;p&gt;Fast forward 7 years to 2016. A few months ago, we noticed that our build system had trouble with correct dependencies in parallel building. So, in search for a way out, I picked up my CMake branch from 2009 last Thursday and spent the whole weekend working on it, and today I am happy to announce that I merged it into master:&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Ever since it&rsquo;s creation back in the dark ages, APT shipped with it&rsquo;s own build system consisting of autoconf and a bunch of makefiles. In 2009, I felt like replacing that with something more standard, and because nobody really liked autotools, decided to go with CMake. Well, the bazaar branch was never really merged back in 2009.</p>
<p>Fast forward 7 years to 2016. A few months ago, we noticed that our build system had trouble with correct dependencies in parallel building. So, in search for a way out, I picked up my CMake branch from 2009 last Thursday and spent the whole weekend working on it, and today I am happy to announce that I merged it into master:</p>
<pre><code>123 files changed, 1674 insertions(+), 3205 deletions(-)
</code></pre>
<p>More than 1500 lines less build system code. Quite impressive, eh? This also includes about 200 lines of less code in debian/, as that switched from prehistoric debhelper stuff to modern dh (compat level 9, almost ready for 10).</p>
<h2 id="the-annoying-tale-of-targets-vs-files">The annoying Tale of Targets vs Files</h2>
<p>Talking about CMake: I don&rsquo;t really love it. As you might know, CMake differentiates between targets and files. Targets can in some cases depend on files (generated by a command in the same directory), but overall files are not really targets. You also cannot have a target with the same name as a file you are generating in a custom command, you have to rename your target (make is OK with the generated stuff, but ninja complains about cycles because your custom target and your custom command have the same name).</p>
<h2 id="byproducts-for-the-time-win"><strong>Byproducts for the (time) win</strong></h2>
<p>One interesting thing about CMake and Ninja are byproducts. In our tree, we are building C++ files. We also have .pot templates depending on them, and .mo files depending on the templates (we have multiple domains, and merge the per-domain .pot with the all-domain .po file during the build to get a per-domain .mo). Now, if we just let them depend naively, changing a C++ file causes the .pot file to be regenerated which in turns causes us to build .mo files for every freaking language in the package. Even if nothing changed.</p>
<p>Byproducts solve this problem. Instead of just building the .pot file, we also create a stamp file (AKA the witness) and write the .pot file (without a header) into a temporary name and only copy it to its final name if the content changed. The .pot file is declared as a byproduct of the command.</p>
<p>The command doing the .pot-&gt;.mo step still depends on the .pot file (the byproduct), but as that only changes now if strings change, the .mo files only get rebuild if I change a translatable string. We still need to ensure that that the .pot file is actually built before we try to use it - the solution here is to specify a custom target depending on the witness and then have the target containing the .mo build commands depend on that target.</p>
<p>Now if you use  make, you might now this trick already. In make, the byproducts remain undeclared, though, while in CMake we can now actually express them, and they are used by the Ninja generator and the Ninja build tool if you chose that over make (try it out, it&rsquo;s fast).</p>
<h2 id="further-work">Further Work</h2>
<p>Some command names are hardcoded, I should find_program() them. Also cross-building the package does not yet work successfully, but it only requires a tiny amount of patches in debhelper and/or cmake.</p>
<p>I also tried building the package on a Fedora docker image (with dpkg installed, it&rsquo;s available in the Fedora sources). While I could eventually get the programs build and most of the integration test suite to pass, there are some minor issues to fix, mostly in the documentation building and GTest department: Fedora ships its docbook stylesheets in a different location, and ships GTest as a pre-compiled library, and not a source tree.</p>
<p>I have not yet tested building on exotic platforms like macOS, or even a BSD. Please do and report back. In Debian, CMake is not up-to.date enough on the non-Linux platforms to build APT due to test suite failures, I hope those can be fixed/disabled soon (it appears to be a timing issue AFAICT).</p>
<p>I hope that we eventually get some non-Debian backends for APT. I&rsquo;d love that.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Backing up with borg and git-annex</title>
      <link>https://blog.jak-linux.org/2016/05/11/backing-up-with-borg-and-git-annex/</link>
      <pubDate>Wed, 11 May 2016 09:47:42 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2016/05/11/backing-up-with-borg-and-git-annex/</guid>
      <description>&lt;p&gt;I recently found out that I have access to a 1 TB cloud storage drive by 1&amp;amp;1, so I decided to start taking off-site backups of my $HOME (well, backups at all, previously I only mirrored the latest version from my SSD to an HDD).&lt;/p&gt;
&lt;p&gt;I initially tried obnam. Obnam seems like a good tool, but is insanely slow. Unencrypted it can write about 3 MB/s, which is somewhat OK, but even then it can spend hours forgetting generations (1 generation takes probably 2 minutes, and there might be 22 of them). In encrypted mode, the speed reduces a lot, to about 500 KB/s if I recall correctly, which is just unusable.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I recently found out that I have access to a 1 TB cloud storage drive by 1&amp;1, so I decided to start taking off-site backups of my $HOME (well, backups at all, previously I only mirrored the latest version from my SSD to an HDD).</p>
<p>I initially tried obnam. Obnam seems like a good tool, but is insanely slow. Unencrypted it can write about 3 MB/s, which is somewhat OK, but even then it can spend hours forgetting generations (1 generation takes probably 2 minutes, and there might be 22 of them). In encrypted mode, the speed reduces a lot, to about 500 KB/s if I recall correctly, which is just unusable.</p>
<p>I found borg backup, a fork of attic. Borg backup achieves speeds of up to 15 MB/s which is really nice. It&rsquo;s also faster with scanning: I can now run my bihourly backups in about 1 min 30s (usually backs up about 30 to 80 MB - mostly thanks to Chrome I suppose!). And all those speeds are with encryption turned on.</p>
<p>Both borg and obnam use some form of chunks from which they compose files. Obnam stores each chunk in its own file, borg stores multiple chunks (even from different files) in a single pack file which is probably the main reason it is faster.</p>
<p>So how am I backing up: My laptop has an internal SSD and an HDD.  I backup every 2 hours (at 09,11,13,15,17,19,21,23,01:00 hours) using a systemd timer event, from the SSD to the HDD. The backup includes all of $HOME except for Downloads, .cache, the trash, Android SDK, and the eclipse and IntelliJ IDEA IDEs.</p>
<p>Now the magic comes in: The backup repository on the HDD is monitored by git-annex assistant, which automatically encrypts and uploads any new files in there to my 1&amp;1 WebDAV drive and registers them in a git repository hosted on bitbucket. All files are encrypted and checksummed using SHA256, reducing the chance of the backup being corrupted.</p>
<p>I&rsquo;m not sure how the WebDAV thing will work once I want to prune things, I suspect it will then delete some pack files and repack things into new files which means it will spend more bandwidth than obnam would. I&rsquo;d also have to convince git-annex to actually drop anything from the WebDAV remote, but that is not really that much of a concern with 1TB storage space in the next 2 years at least&hellip;</p>
<p>I also have an external encrypted HDD which I can take backups on, it currently houses a fuller backup of $HOME that also includes Downloads, the Android SDK, and the IDEs for quicker recovery. Downloads changes a lot, and all of them can be fairly easily re-retrieved from the internet as needed, so there&rsquo;s not much point in painfully uploading them to a WebDAV backup site.</p>
<p><em>Update</em>: I can&rsquo;t recommend this. Get a service that has native borg support such as <a href="https://www.rsync.net/products/attic.html">rsync.net</a> or a storage box at <a href="https://wiki.hetzner.de/index.php/BorgBackup/en">hetzner</a>.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Clarifications and updates on APT &#43; SHA1</title>
      <link>https://blog.jak-linux.org/2016/03/15/clarifications-and-updates-on-apt-sha1/</link>
      <pubDate>Tue, 15 Mar 2016 19:25:00 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2016/03/15/clarifications-and-updates-on-apt-sha1/</guid>
      <description>&lt;p&gt;The APT 1.2.7 release is out now.&lt;/p&gt;
&lt;p&gt;Despite of what I wrote earlier, we now print warnings for Release files signed with signatures using SHA1 as the digest algorithm. This involved extending the protocol APT uses to communicate with the methods a bit, by adding a new 104 Warning message type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;W: gpgv:/var/lib/apt/lists/apt.example.com_debian_dists_sid_InRelease: The repository is insufficiently signed by key
1234567890ABCDEF0123456789ABCDEF01234567 (weak digest)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also note that SHA1 support is not dropped, we merely do not consider it trustworthy. This means that it feels like SHA1 support is dropped, because sources without SHA2 won&amp;rsquo;t work; but the SHA1 signatures will still be used in addition to the SHA2 ones, so there&amp;rsquo;s no point removing them (same for MD5Sum fields).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>The APT 1.2.7 release is out now.</p>
<p>Despite of what I wrote earlier, we now print warnings for Release files signed with signatures using SHA1 as the digest algorithm. This involved extending the protocol APT uses to communicate with the methods a bit, by adding a new 104 Warning message type.</p>
<pre><code>W: gpgv:/var/lib/apt/lists/apt.example.com_debian_dists_sid_InRelease: The repository is insufficiently signed by key
1234567890ABCDEF0123456789ABCDEF01234567 (weak digest)
</code></pre>
<p>Also note that SHA1 support is not dropped, we merely do not consider it trustworthy. This means that it feels like SHA1 support is dropped, because sources without SHA2 won&rsquo;t work; but the SHA1 signatures will still be used in addition to the SHA2 ones, so there&rsquo;s no point removing them (same for MD5Sum fields).</p>
<p>We also fixed some small bugs!</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Dropping SHA-1 support in APT</title>
      <link>https://blog.jak-linux.org/2016/03/14/dropping-sha-1-support-in-apt/</link>
      <pubDate>Mon, 14 Mar 2016 20:03:35 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2016/03/14/dropping-sha-1-support-in-apt/</guid>
      <description>&lt;p&gt;Tomorrow &lt;!-- raw HTML omitted --&gt;is the anniversary of Caesar&amp;rsquo;s assassination&lt;!-- raw HTML omitted --&gt; APT will see a new release, turning of support for SHA-1 checksums in Debian unstable and in Ubuntu xenial, the upcoming LTS release.  While I have no knowledge of an imminent attack on our use of SHA1, Xenial (Ubuntu 16.04 LTS) will be supported for 5 years, and the landscape may change a lot in the next 5 years. As disabling the SHA1 support requires a bit of patching in our test suite, it&amp;rsquo;s best to do that now rather than later when we&amp;rsquo;re forced to do it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Tomorrow <!-- raw HTML omitted -->is the anniversary of Caesar&rsquo;s assassination<!-- raw HTML omitted --> APT will see a new release, turning of support for SHA-1 checksums in Debian unstable and in Ubuntu xenial, the upcoming LTS release.  While I have no knowledge of an imminent attack on our use of SHA1, Xenial (Ubuntu 16.04 LTS) will be supported for 5 years, and the landscape may change a lot in the next 5 years. As disabling the SHA1 support requires a bit of patching in our test suite, it&rsquo;s best to do that now rather than later when we&rsquo;re forced to do it.</p>
<p>This will mean that starting tomorrow, some third party repositories may stop working, such as the one for the web browser I am writing this with. Debian Derivatives should be mostly safe for that change, if they are registered in the Consensus, as that has checks for that. This is a bit unfortunate, but we have no real choice: Technical restrictions prevent us from just showing a warning in a sensible way.</p>
<p>There is one caveat, however: GPG signatures may still use SHA1. While I have prepared the needed code to reject SHA1-based signatures in APT, a lot of third party repositories still ship Release files signed with signatures using SHA-1 as the digest algorithms. Some repositories even still use 1024-bit DSA keys.</p>
<p>I plan to enforce SHA2 for GPG signatures some time after the release of xenial, and definitely for Ubuntu 16.10, so around June-August (possibly during DebConf). For xenial, I plan to have a SRU (stable release update) in January to do the same (it&rsquo;s just adding one member to an array). This should give 3rd party providers a reasonable time frame to migrate to a new digest algorithm for their GPG config and possibly a new repository key.</p>
<p>Summary</p>
<ul>
<li>Tomorrow: Disabling SHA1 support for Release, Packages, Sources files</li>
<li>June/July/August: Disabling SHA1 support for GPG signatures (InRelease/Release.gpg) in development releases</li>
<li>January 2017: Disabling SHA1 support for GPG signatures in Ubuntu 16.04 LTS via a stable-release-update.</li>
</ul>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>APT 1.1.8 to 1.1.10 - going &#34;faster&#34;</title>
      <link>https://blog.jak-linux.org/2015/12/30/apt-1-1-8-to-1-1-10-going-faster/</link>
      <pubDate>Wed, 30 Dec 2015 01:01:05 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2015/12/30/apt-1-1-8-to-1-1-10-going-faster/</guid>
      <description>&lt;p&gt;Not only do I keep incrementing version numbers faster than ever before, APT also keeps getting faster. But not only that, it also has some bugs fixed and the cache is now checked with a hash when opening.&lt;/p&gt;
&lt;h2 id=&#34;important-fix-for-116-regression&#34;&gt;Important fix for 1.1.6 regression&lt;/h2&gt;
&lt;p&gt;Since APT 1.1.6, APT uses the configured xz compression level. Unfortunately, the default was set to 9, which requires 674 MiB of RAM, compared to the 94 MiB required at level 6.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Not only do I keep incrementing version numbers faster than ever before, APT also keeps getting faster. But not only that, it also has some bugs fixed and the cache is now checked with a hash when opening.</p>
<h2 id="important-fix-for-116-regression">Important fix for 1.1.6 regression</h2>
<p>Since APT 1.1.6, APT uses the configured xz compression level. Unfortunately, the default was set to 9, which requires 674 MiB of RAM, compared to the 94 MiB required at level 6.</p>
<p>This caused the test suite to fail on the Ubuntu autopkgtest servers, but I thought it was just some temporary hickup on their part, and so did not look into it for the 1.1.7, 1.1.8, and 1.1.9 releases.  When the Ubuntu servers finally failed with 1.1.9 again (they only started building again on Monday it seems), I noticed something was wrong.</p>
<p>Enter git bisect. I created a script that compiles the APT source code and runs a test with ulimit for virtual and resident memory set to 512 (that worked in 1.1.5), and let it ran, and thus found out the reason mentioned above.</p>
<p>The solution: APT now defaults to level 6.</p>
<h2 id="new-features">New Features</h2>
<p>APT 1.1.8 introduces <code>/usr/lib/apt/apt-helper cat-file</code> which can be used to read files compressed by any compressor understood by APT. It is used in the recent apt-file experimental release, and serves to prepare us for a future in which files on the disk might be compressed with a different compressor (such as LZ4 for Contents files, this will improve rred speed on them by factor 7).</p>
<p>David added a feature that enables servers to advertise that they do not want APT to download and use some Architecture: all contents when they include all in their list of architectures. This is to allow archives to drop Architecture: all packages from the architecture-specific content files, to avoid redundant data and (thus) improve the performance of apt-file.</p>
<h2 id="buffered-writes">Buffered writes</h2>
<p>APT 1.1.9 introduces buffered writing for rred, reducing the runtime by about 50% on a slowish SSD, and maybe more on HDDs. The 1.1.9 release is a bit buggy and might mess up things when a write syscall is interrupted, this is fixed in 1.1.10.</p>
<h2 id="cache-generation-improvements">Cache generation improvements</h2>
<p>APT 1.1.9 and APT 1.1.10 improve the cache generation algorithms in several ways: Switching a lookup table from <code>std::map</code> to <code>std::unordered_map</code>, providing an inline <code>isspace_ascii()</code> function, and inlining the <code>tolower_ascii()</code> function which are tiny functions that are called a lot.</p>
<p>APT 1.1.10 also switches the cache&rsquo;s hash function to the DJB hash function and increases the default hash table sizes to the smallest prime larger than 15000, namely 15013. This reduces the average bucket size from 6.5 to 4.5. We might increase this further in the future.</p>
<h2 id="checksum-for-the-cache-but-no-more-syncs">Checksum for the cache, but no more syncs</h2>
<p>Prior to APT 1.1.10 writing the cache was a multi-part process:</p>
<pre><code>  1. Write the the cache to a temporary file with the dirty bit set to true
  2. Call `fsync()` to sync the cache
  3. Write a new header with the dirty bit set to false
  4. Call `fsync()` to sync the new header
  5. (Rename the temporary file to the target name)
</code></pre>
<p>The last step was obviously not needed, as we could easily live with an intact cache that has its dirty field set to false, as we can just rebuild it.</p>
<p>But what matters more is step 2. Synchronizing the entire 40 or 50 MB takes some time. On my HDD system, it consumed 56% of the entire cache generation time, and on my SSD system, it consumed 25% of the time.</p>
<p>APT 1.1.10 does not sync the cache at all. It now embeds a hashsum (adler32 for performance reasons) in the cache. This helps ensure that no matter what parts of the cache are written in case of some failure somewhere, we can still detect a failure with reasonable confidence (and even more errors than before).</p>
<p>This means that cache generation is now much faster for a lot of people. On the bad side, commands like apt-cache show that previously took maybe 10 ms to execute can now take about 80 ms.</p>
<p>Please report back on your performance experience with 1.1.10 release, I&rsquo;m very interested to see if that works reasonably for other people. And if you have any other idea how to solve the issue, I&rsquo;d be interested to hear them (all data needs to be written before the header with dirty=0 is written, but we don&rsquo;t want to sync the data).</p>
<h2 id="future-work">Future work</h2>
<p>We seem to have a lot of temporary (?) <code>std::string</code> objects during the cache generation, accounting for about 10% of the run time. I&rsquo;m thinking of introducing a <code>string_view</code> class similar to the one proposed for C++17 and make use of that.</p>
<p>I also thought about calling <code>posix_fadvise()</code> before starting to parse files, but the cache generation process does not seem to spend a lot of its time in system calls (even with all caches dropped before the run), so I don&rsquo;t think this will improve things.</p>
<p>If anyone has some other suggestions or patches for performance stuff, let me know.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Much faster incremental apt updates</title>
      <link>https://blog.jak-linux.org/2015/12/26/much-faster-incremental-apt-updates/</link>
      <pubDate>Sat, 26 Dec 2015 19:01:37 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2015/12/26/much-faster-incremental-apt-updates/</guid>
      <description>&lt;p&gt;APT&amp;rsquo;s performance in applying the Pdiffs files, which are the diff format used for Packages, Sources, and other files in the archive has been slow.&lt;/p&gt;
&lt;h2 id=&#34;improving-performance-for-uncompressed-files&#34;&gt;Improving performance for uncompressed files&lt;/h2&gt;
&lt;p&gt;The reason for this is that our I/O is unbuffered, and we were reading one byte at a time in order to read lines. This changed on December 24, by adding read buffering for reading lines, vastly improving the performance of rred.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>APT&rsquo;s performance in applying the Pdiffs files, which are the diff format used for Packages, Sources, and other files in the archive has been slow.</p>
<h2 id="improving-performance-for-uncompressed-files">Improving performance for uncompressed files</h2>
<p>The reason for this is that our I/O is unbuffered, and we were reading one byte at a time in order to read lines. This changed on December 24, by adding read buffering for reading lines, vastly improving the performance of rred.</p>
<p>But it was still slow, so today I profiled - using gperftools - the rred method running on a 430MB uncompressed Contents file with a 75 KB large patch. I noticed that our ReadLine() method was calling some method which took a long time (google-pprof told me it was some _nss method, but that was wrong [thank you, addr2line]).</p>
<p>After some further look into the code, I noticed that we set the length of the buffer using the length of the line. And whenever we moved some data out of the buffer, we called <code>memmove()</code> to move the remaining data to the front of the buffer.</p>
<p>So, I tried to use a fixed buffer size of 4096 (<a href="http://anonscm.debian.org/cgit/apt/apt.git/commit/?id=0b29c72bdfc1466d47567cc3191b9661f81d3d3f">commit</a>). Now <code>memmove() </code> would spend less time moving memory around inside the buffer. This helped a lot, bringing the run time on my example file down from 46 seconds to about 2 seconds.</p>
<p>Later on, I rewrote the code to not use <code>memmove()</code> at all - opting for start and end variables instead; and increasing the start variable when reading from the buffer (<a href="http://anonscm.debian.org/cgit/apt/apt.git/commit/?id=83e22e26f9f10472aed97f889967c86ee218d28d">commit</a>).</p>
<p>This in turn further improved things, bringing it down to about 1.6 seconds. We could now increase the buffer size again, without any negative effect.</p>
<h3 id="effects-on-apt-get-update">Effects on apt-get update</h3>
<p>I measured the run-time of apt-get update, excluding appstream and apt-file files, for the update from todays 07:52 to the 13:52 dinstall run. Configured sources are unstable and experimental with amd64 and i386 architectures. appstream and apt-file indexes are disabled for testing, so only Packages and Sources indexes are fetched.</p>
<p>The results are impressive:</p>
<pre><code>  * For APT 1.1.6, updating with PDiffs enabled took 41 seconds.
  * For APT 1.1.7, updating with PDiffs enabled took 4 seconds.
</code></pre>
<p>That&rsquo;s a tenfold increase in performance. By the way, running without PDiffs took 20 seconds, so there&rsquo;s no reason not to use them.</p>
<h3 id="future-work">Future work</h3>
<p>Writes are still unbuffered, and account for about 75% to 80% of our runtime. That&rsquo;s an obvious area for improvements.</p>
<p><img src="https://juliank.files.wordpress.com/2015/12/rred-profile.png" alt="rred-profile"></p>
<h2 id="performance-for-patching-compressed-files">Performance for patching compressed files</h2>
<p>Contents files are usually compressed with gzip, and kept compressed locally because they are about 500 MB uncompressed and only 30MB compressed. I profiled this, and it turns out there is not much we can do about it: The majority of the time is spent inside zlib, mostly combining CRC checksums:</p>
<p><img src="https://juliank.files.wordpress.com/2015/12/rred-gz-profile.png" alt="rred-gz-profile"></p>
<p>Going forward, I think a reasonable option might be to recompress Contents files using lzo - they will be a bit bigger (50MB instead of 30MB), but lzo is about 6 times as fast (compressing a 430MB Contents file took 1 second instead of 6).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Key transition</title>
      <link>https://blog.jak-linux.org/2014/10/14/key-transition/</link>
      <pubDate>Tue, 14 Oct 2014 21:46:03 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2014/10/14/key-transition/</guid>
      <description>&lt;p&gt;I started transitioning from 1024D to 4096R.  The new key is available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://people.debian.org/~jak/pubkey.gpg&#34;&gt;https://people.debian.org/~jak/pubkey.gpg&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;and the keys.gnupg.net key server. A very short transition statement is available at:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://people.debian.org/~jak/transition-statement.txt&#34;&gt;https://people.debian.org/~jak/transition-statement.txt&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;and included below (the http version might get extended over time if needed).&lt;/p&gt;
&lt;p&gt;The key consists of one master key and 3 sub keys (signing, encryption, authentication). The sub keys are stored on an OpenPGP v2 Smartcard. That&amp;rsquo;s really cool, isn&amp;rsquo;t it?&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I started transitioning from 1024D to 4096R.  The new key is available at:</p>
<p><a href="https://people.debian.org/~jak/pubkey.gpg">https://people.debian.org/~jak/pubkey.gpg</a></p>
<p>and the keys.gnupg.net key server. A very short transition statement is available at:</p>
<p><a href="https://people.debian.org/~jak/transition-statement.txt">https://people.debian.org/~jak/transition-statement.txt</a></p>
<p>and included below (the http version might get extended over time if needed).</p>
<p>The key consists of one master key and 3 sub keys (signing, encryption, authentication). The sub keys are stored on an OpenPGP v2 Smartcard. That&rsquo;s really cool, isn&rsquo;t it?</p>
<p>Somehow it seems that GnuPG 1.4.18 also works with 4096R keys on this smartcard (I accidentally used it instead of gpg2 and it worked fine), although only GPG 2.0.13 and newer is supposed to work.</p>
<pre><code>-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1,SHA512

Because 1024D keys are not deemed secure enough anymore, I switched to
a 4096R one.

The old key will continue to be valid for some time, but i prefer all
future correspondence to come to the new one.  I would also like this
new key to be re-integrated into the web of trust.  This message is
signed by both keys to certify the transition.

the old key was:

pub   1024D/00823EC2 2007-04-12
      Key fingerprint = D9D9 754A 4BBA 2E7D 0A0A  C024 AC2A 5FFE 0082 3EC2

And the new key is:

pub   4096R/6B031B00 2014-10-14 [expires: 2017-10-13]
      Key fingerprint = AEE1 C8AA AAF0 B768 4019  C546 021B 361B 6B03 1B00

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iEYEARECAAYFAlQ9j+oACgkQrCpf/gCCPsKskgCgiRn7DoP5RASkaZZjpop9P8aG
zhgAnjHeE8BXvTSkr7hccNb2tZsnqlTaiQIcBAEBCgAGBQJUPY/qAAoJENc8OeVl
gLOGZiMP/1MHubKmA8aGDj8Ow5Uo4lkzp+A89vJqgbm9bjVrfjDHZQIdebYfWrjr
RQzXdbIHnILYnUfYaOHUzMxpBHya3rFu6xbfKesR+jzQf8gxFXoBY7OQVL4Ycyss
4Y++g9m4Lqm+IDyIhhDNY6mtFU9e3CkljI52p/CIqM7eUyBfyRJDRfeh6c40Pfx2
AlNyFe+9JzYG1i3YG96Z8bKiVK5GpvyKWiggo08r3oqGvWyROYY9E4nLM9OJu8EL
GuSNDCRJOhfnegWqKq+BRZUXA2wbTG0f8AxAuetdo6MKmVmHGcHxpIGFHqxO1QhV
VM7VpMj+bxcevJ50BO5kylRrptlUugTaJ6il/o5sfgy1FdXGlgWCsIwmja2Z/fQr
ycnqrtMVVYfln9IwDODItHx3hSwRoHnUxLWq8yY8gyx+//geZ0BROonXVy1YEo9a
PDplOF1HKlaFAHv+Zq8wDWT8Lt1H2EecRFN+hov3+lU74ylnogZLS+bA7tqrjig0
bZfCo7i9Z7ag4GvLWY5PvN4fbws/5Yz9L8I4CnrqCUtzJg4vyA44Kpo8iuQsIrhz
CKDnsoehxS95YjiJcbL0Y63Ed4mkSaibUKfoYObv/k61XmBCNkmNAAuRwzV7d5q2
/w3bSTB0O7FHcCxFDnn+tiLwgiTEQDYAP9nN97uibSUCbf98wl3/
=VRZJ
-----END PGP SIGNATURE-----
</code></pre>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>A weekend with the Acer Chromebook 13 FHD (AKA nyan-big)</title>
      <link>https://blog.jak-linux.org/2014/10/06/a-weekend-with-the-acer-chromebook-13-fhd-aka-nyan-big/</link>
      <pubDate>Mon, 06 Oct 2014 16:19:03 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2014/10/06/a-weekend-with-the-acer-chromebook-13-fhd-aka-nyan-big/</guid>
      <description>&lt;p&gt;I spent the weekend using almost exclusively my Chromebook 13, on a single charge Saturday and Sunday.&lt;/p&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;p&gt;I think I like the keyboard better now than I used to when I first tried it. It gets nowhere near the ThinkPad X230 one, though; appart from the coating, which my (backlit) X230 unfortunately does not have.&lt;/p&gt;
&lt;h3 id=&#34;screen&#34;&gt;Screen&lt;/h3&gt;
&lt;p&gt;While the screen appeared very grainy to me on first sight, having only used IPS screens in the past year, I got used to it over the weekend. I now do not notice much graininess anymore. The contrast still seems extremely poor, the colors are not vivid, and the vertical viewing angles are still a disaster, though.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I spent the weekend using almost exclusively my Chromebook 13, on a single charge Saturday and Sunday.</p>
<h3 id="keyboard">Keyboard</h3>
<p>I think I like the keyboard better now than I used to when I first tried it. It gets nowhere near the ThinkPad X230 one, though; appart from the coating, which my (backlit) X230 unfortunately does not have.</p>
<h3 id="screen">Screen</h3>
<p>While the screen appeared very grainy to me on first sight, having only used IPS screens in the past year, I got used to it over the weekend. I now do not notice much graininess anymore. The contrast still seems extremely poor, the colors are not vivid, and the vertical viewing angles are still a disaster, though.</p>
<h3 id="battery-life">Battery life</h3>
<p>I think the battery life is awesome. I have 30% remaining now while I am writing this blog post and Chrome OS tells me I still have 3 hours and 19 minutes remaining. It could probably still be improved though, I notice that Chrome OS uses 7-14% CPU in idle normally (and up to 20% in exceptional cases).</p>
<p>The maximum power usage I measured using the battery&rsquo;s internal sensor was about 9.2W, that was with 5 Big Buck Bunny 1080p videos played in parallel. Average power consumption is around 3-5W (up to 6.5 with single video playing), depending on brightness, and use.</p>
<h3 id="performance">Performance</h3>
<p>While I do notice a performance difference to my much more high-end Ivy Bridge Core i5 laptop, it turns out to be usable enough to not make me want to throw it at a wall. Things take a bit longer than I am used to, but it is still acceptable.</p>
<h3 id="input-software-part">Input: Software Part</h3>
<p>The user interface is great. There are a lot of gestures available for navigating between windows, tabs, and in the history. For example, horizontally swiping with two finger moves in history, three fingers moves between tabs; and swiping down (or up for Australian scrolling) gives an overview of all windows (like expose on Mac, GNOME&rsquo;s activities, or the multi-tasking thing Maemo used to have).</p>
<p>What I miss is a keyboard shortcut like Meta + Left/Right on GNOME which moves the active window to the left/right side of the screen. That would be very useful for mult-tasking situations.</p>
<h3 id="issues">Issues</h3>
<p>I noticed some performance issues. For example, I can easily get the Chromebook to use 85% of a CPU by scrolling on a page with the touchpad or 70% for scrolling by keeping a key pressed (<a href="http://crbug.com/420452">crbug.com/420452</a>).</p>
<p>While watching Big Buck Bunny on YouTube, I noticed some (micro) stuttering in the beginning of the film, as well as each time I move in or out of the video area when not in full-screen mode (<a href="http://crbug.com/420582">crbug.com/420582</a>). It also increases CPU usage to about 70%.</p>
<h3 id="running-a-proper-linux">Running a &ldquo;proper&rdquo; Linux?</h3>
<p>Today, I tried to play around a bit with Debian wheezy and Ubuntu trusty systems, in a chroot for now. I was trying to find out if I can get an accelerated X server with the standard ChromeOS kernel. The short answer is: No. I tried two things:</p>
<pre><code>  1. Debian wheezy with the binaries from ChromeOS (they have the same xserver version)
  2. Ubuntu trusty with the Nvidia drivers
</code></pre>
<p>Unfortunately, they did not work. Option 1 failed because ChromeOS uses glibc 2.15 whereas wheezy uses 1.13. Option 2 failed because the sysfs interface is different between the ChromeOS and Linux4Tegra kernels.</p>
<p>I guess I&rsquo;ll have to wait.</p>
<p>I also tried booting a custom kernel from USB, but given that the u-boot always sets console= and there is no non-verified u-boot available yet, I could not see any output on the screen :(  - Maybe I should build a u-boot myself?</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Acer Chromebook 13 (FHD): Initial impressions</title>
      <link>https://blog.jak-linux.org/2014/10/02/acer-chromebook-13-fhd-initial-impressions/</link>
      <pubDate>Thu, 02 Oct 2014 16:08:03 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2014/10/02/acer-chromebook-13-fhd-initial-impressions/</guid>
      <description>&lt;p&gt;Today, I received my Acer Chromebook 13, in the glorious FullHD variant with 4GB RAM. For those of you who don&amp;rsquo;t know it, the Acer Chromebook 13 is a 13.3 inch chromebook powered by a Tegra K1 cpu.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.jak-linux.org/images/2014-10-02-acer-chromebook-13-fhd-initial-impressions/chromebook.jpg&#34;&gt;&lt;img src=&#34;https://blog.jak-linux.org/images/2014-10-02-acer-chromebook-13-fhd-initial-impressions/chromebook.jpg?w=284&#34; alt=&#34;Chromebook&#34;&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This version cannot be ordered currently, only pre-orders were shipped yesterday (at least here in Germany). I cannot even review it on Amazon (despite having it bought there), as they have not enabled reviews for it yet.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today, I received my Acer Chromebook 13, in the glorious FullHD variant with 4GB RAM. For those of you who don&rsquo;t know it, the Acer Chromebook 13 is a 13.3 inch chromebook powered by a Tegra K1 cpu.</p>
<p><a href="/images/2014-10-02-acer-chromebook-13-fhd-initial-impressions/chromebook.jpg"><img src="/images/2014-10-02-acer-chromebook-13-fhd-initial-impressions/chromebook.jpg?w=284" alt="Chromebook">
</a></p>
<p>This version cannot be ordered currently, only pre-orders were shipped yesterday (at least here in Germany). I cannot even review it on Amazon (despite having it bought there), as they have not enabled reviews for it yet.</p>
<p>The device feels solidly built, and looks good. It comes in all-white matte plastic and is slightly reminiscent of the old white MacBooks. The keyboard is horrible, there&rsquo;s no well defined pressure point. It feels like your typing on a pillow. The display is OK, an IPS would be a lot nicer to work with, though. Oh, and it could be brighter. I do not think that using it outside on a sunny day would be a good idea. The speakers are loud and clear compared to my ThinkPad X230.</p>
<p>The performance of the device is about acceptable (unfortunately, I do not have any comparison in this device class). Even when typing this blog post in the visual wordpress editor, I notice some sluggishness. Opening the app launcher or loading the new tab page while music is playing makes the music stop for or skip a few ms (20-50ms if I had to guess). Running a benchmark in parallel or browsing does not usually cause this stuttering, though.</p>
<p>There are still some bugs in Chrome OS:  Loading the Play Books library the first time resulted in some rendering issues. The &ldquo;Browser&rdquo; process always consumes at least 10% CPU, even when idling, with no page open; this might cause some of the sluggishness I mentioned above. Also watching Flash videos used more CPU than I expected given that it is hardware accelerated.</p>
<p>Finally, Netflix did not work out of the box, despite the Chromebook shipping with a special Netflix plugin. I always get some unexpected issue-type page. Setting the user agent to Chrome 38 from Windows, thus forcing the use of the EME video player instead of the Netflix plugin, makes it work.</p>
<p>I reported these software issues to Google via Alt+Shift+I. The issues appeared on the current version of the stable channel, 37.0.2062.120.</p>
<p>What&rsquo;s next? I don&rsquo;t know.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>hardlink 0.3.0 released; xattr support</title>
      <link>https://blog.jak-linux.org/2014/09/25/hardlink-0-3-0-released-xattr-support/</link>
      <pubDate>Thu, 25 Sep 2014 12:41:47 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2014/09/25/hardlink-0-3-0-released-xattr-support/</guid>
      <description>&lt;p&gt;Today I not only submitted my bachelor thesis to the printing company, I also released a new version of hardlink, my file deduplication tool.&lt;/p&gt;
&lt;p&gt;hardlink 0.3 now features support for xattr support, contributed by Tom Keel at Intel. If this does not work correctly, please blame him.&lt;/p&gt;
&lt;p&gt;I also added support for a &amp;ndash;minimum-size option.&lt;/p&gt;
&lt;p&gt;Most of the other code has been tested since the upload of RC1 to experimental in September 2012.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today I not only submitted my bachelor thesis to the printing company, I also released a new version of hardlink, my file deduplication tool.</p>
<p>hardlink 0.3 now features support for xattr support, contributed by Tom Keel at Intel. If this does not work correctly, please blame him.</p>
<p>I also added support for a &ndash;minimum-size option.</p>
<p>Most of the other code has been tested since the upload of RC1 to experimental in September 2012.</p>
<p>The next major version will split up the code into multiple files and clean it up a bit. It&rsquo;s getting a bit long now in a single file.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>APT 1.1~exp3 released to experimental: First step to sandboxed fetcher methods</title>
      <link>https://blog.jak-linux.org/2014/09/24/apt-1-1exp3-released-to-experimental-first-step-to-sandboxed-fetcher-methods/</link>
      <pubDate>Wed, 24 Sep 2014 21:05:56 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2014/09/24/apt-1-1exp3-released-to-experimental-first-step-to-sandboxed-fetcher-methods/</guid>
      <description>&lt;p&gt;Today, we worked, with the help of ioerror on IRC, on reducing the attack surface in our fetcher methods.&lt;/p&gt;
&lt;p&gt;There are three things that we looked at:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  1. Reducing privileges by setting a new user and group
  2. chroot()
  3. seccomp-bpf sandbox
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Today, we implemented the first of them. Starting with 1.1~exp3, the APT directories /var/cache/apt/archives and /var/lib/apt/lists are owned by the &amp;ldquo;_apt&amp;rdquo; user (username suggested by pabs). The methods switch to that user shortly after the start. The only methods doing this right now are: copy, ftp, gpgv, gzip, http, https.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today, we worked, with the help of ioerror on IRC, on reducing the attack surface in our fetcher methods.</p>
<p>There are three things that we looked at:</p>
<pre><code>  1. Reducing privileges by setting a new user and group
  2. chroot()
  3. seccomp-bpf sandbox
</code></pre>
<p>Today, we implemented the first of them. Starting with 1.1~exp3, the APT directories /var/cache/apt/archives and /var/lib/apt/lists are owned by the &ldquo;_apt&rdquo; user (username suggested by pabs). The methods switch to that user shortly after the start. The only methods doing this right now are: copy, ftp, gpgv, gzip, http, https.</p>
<p>If privileges cannot be dropped, the methods will fail to start. No fetching will be possible at all.</p>
<p>Known issues:</p>
<ul>
<li>We drop all groups except the primary gid of the user</li>
<li>copy breaks if that group has no read access to the files</li>
</ul>
<p>We plan to also add chroot() and seccomp sandboxing later on; to reduce the attack surface on untrusted files and protocol parsing.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Configuring an OpenWRT Router as a repeater for a FRITZ!Box with working Multicast</title>
      <link>https://blog.jak-linux.org/2014/08/07/configuring-an-openwrt-router-as-a-repeater-for-a-fritzbox-with-working-multicast/</link>
      <pubDate>Wed, 06 Aug 2014 23:01:15 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2014/08/07/configuring-an-openwrt-router-as-a-repeater-for-a-fritzbox-with-working-multicast/</guid>
      <description>&lt;p&gt;Since some time, those crappy Fritz!Box devices do not support WDS anymore, but rather a proprietary solution created by AVM. Now what happens if you have devices in another room that need/want wired access (like TVs, Playstations) or if you want to extend the range of your network? Buying another Fritz!Box is not very cost efficient - What I did was to buy a cheap TP-Link TL-WR841N (can be bought for 18 euros) and installed OpenWRT on it. Here&amp;rsquo;s how I configured it to act as a WiFi bridge.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Since some time, those crappy Fritz!Box devices do not support WDS anymore, but rather a proprietary solution created by AVM. Now what happens if you have devices in another room that need/want wired access (like TVs, Playstations) or if you want to extend the range of your network? Buying another Fritz!Box is not very cost efficient - What I did was to buy a cheap TP-Link TL-WR841N (can be bought for 18 euros) and installed OpenWRT on it. Here&rsquo;s how I configured it to act as a WiFi bridge.</p>
<p>Basic overview: You configure OpenWRT into station mode (that is, as a WiFi client) and use relayd to relay between the WiFi network and your local network. You also need igmpproxy to proxy multicast packages between those networks, other UPnP stuff won&rsquo;t work.</p>
<p>I did this on the recent Barrier Braker RC2. It should work on older versions as well, but I cannot promise it (I did not get igmpproxy to work in Attitude Adjustment, but that was probably my fault).</p>
<p>Note: I don&rsquo;t know if it works with IPv6, I only use IPv4.</p>
<p>You might want to re-start (or start) services after the steps, or reboot the router afterwards.</p>
<h2 id="configuring-wifi-connection-to-the-fritzbox">Configuring WiFi connection to the FRITZ!Box</h2>
<p><strong>Add to: /etc/config/network</strong></p>
<pre><code>config interface 'wwan'
	option proto 'dhcp'
</code></pre>
<p>(you can use any other name you want instead of wwan, and a static IP. This will be your uplink to the Fritz!Box)</p>
<p><strong>Replace wifi-iface in: /etc/config/wireless:</strong></p>
<pre><code>config wifi-iface
	option device 'radio0'
	option mode 'sta'
	option ssid 'FRITZ!Box 7270'
	option encryption 'psk2'
	option key 'PASSWORD'
	option network 'wwan'
</code></pre>
<p>(adjust values as needed for your network)</p>
<h2 id="setting-up-the-pseudo-bridge">Setting up the pseudo-bridge</h2>
<p>First, add <code>wwan</code> to the list of networks in the <code>lan</code> zone in the firewall. Then add a forward rule for the lan network (not sure if needed). Afterwards, configure a new <code>stabridge</code> network and disable the built-in DHCP server.</p>
<p><strong>Diff for /etc/config/firewall</strong></p>
<pre><code>@@ -10,2 +10,3 @@ config zone
 	list network 'lan'
+	list network 'wwan'
 	option input 'ACCEPT'
@@ -28,2 +29,7 @@ config forwarding
 
+# Not sure if actually needed
+config forwarding
+	option src 'lan'
+	option dest 'lan'
+
 config rule
</code></pre>
<p><strong>Add to /etc/config/network</strong></p>
<pre><code>config interface 'stabridge'
	option proto 'relay'
	option network 'lan wwan'
	option ipaddr '192.168.178.26'
</code></pre>
<p>(Replace 192.168.178.26 with the IP address your OpenWRT router was given by the Fritz!Box on wlan0)</p>
<p>Also make sure to ignore dhcp on the lan interface, as the DHCP server of the FRITZ!Box will be used:</p>
<p><strong>Diff for /etc/config/dhcp</strong></p>
<pre><code>@@ -24,2 +24,3 @@ config dhcp 'lan'
        option ra 'server'
+       option ignore '1'
</code></pre>
<h2 id="proxying-multicast-packages">Proxying multicast packages</h2>
<p>For proxying multicast packages, we need to install igmpproxy and configure it:</p>
<p><strong>Add to: /etc/config/firewall</strong></p>
<pre><code># Configuration for igmpproxy
config rule
	option src      lan
	option proto    igmp
	option target   ACCEPT

config rule
	option src      lan
	option proto    udp
	option dest     lan
	option target   ACCEPT
</code></pre>
<p>(OpenWRT wiki gives a different 2nd rule now, but this is the one I currently use)</p>
<p><strong>Replace /etc/config/igmpproxy with:</strong></p>
<pre><code>config igmpproxy
	option quickleave 1

config phyint
	option network wwan
	option direction upstream
	list altnet 192.168.178.0/24

config phyint
	option network lan
	option direction downstream
	list altnet 192.168.178.0/24
</code></pre>
<p>(Assuming Fritz!Box uses the <code>192.168.178.0/24</code> network)</p>
<p>Don&rsquo;t forget to enable the igmpproxy script:</p>
<pre><code># /etc/init.d/igmpproxy enable
</code></pre>
<h2 id="optional-repeat-the-wifi-signal">Optional: Repeat the WiFi signal</h2>
<p>If you want to repeat your WiFi signal, all you need to do is add a second <code>wifi-iface</code> to your <code>/etc/config/wireless</code>.</p>
<pre><code>config wifi-iface
	option device 'radio0'
	option mode 'ap'
	option network 'lan'
	option encryption 'psk2+tkip+ccmp'
	option key 'PASSWORD'
	option ssid 'YourForwardingSSID'
</code></pre>
<h2 id="known-issues">Known Issues</h2>
<p>If I was connected via WiFi to the OpenWRT AP and switch to the FRITZ!Box AP, I cannot connect to the OpenWRT router for some time.</p>
<p>The igmpproxy tool writes to the log about changing routes.</p>
<h2 id="future-work">Future Work</h2>
<p>I&rsquo;ll try to get the FRITZ!Box replaced by something that runs OpenWRT as well, and then use OpenWRT&rsquo;s WDS support for repeating; because the FRITZ!Box 7270v2 is largely crap - loading a page in its web frontend takes 5 (idle) - 20 seconds (1 download), and it&rsquo;s WiFi speed is limited to about 20 Mbit/s in WiFi-n mode (2.4 GHz (or 5 GHz, does not matter), 40 MHz channel). It seems the 7270 has a really slow CPU.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>ThinkPad X230 UEFI broken by setting a setting</title>
      <link>https://blog.jak-linux.org/2014/04/09/thinkpad-x230-uefi-broken-by-setting-a-setting/</link>
      <pubDate>Wed, 09 Apr 2014 12:57:59 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2014/04/09/thinkpad-x230-uefi-broken-by-setting-a-setting/</guid>
      <description>&lt;p&gt;Today, I decided to set my X230 back to UEFI-only boot, after having changed that for a bios upgrade recently (to fix a resume bug). I then choose to save the settings and received several error messages telling me that the system ran out of resources (probably storage space for UEFI variables).&lt;/p&gt;
&lt;p&gt;I rebooted my machine, and saw no logo appearing. Just something like an underscore on a text console. The system appears to boot normally otherwise, and once the i915 module is loaded (and we&amp;rsquo;re switching away from UEFI&amp;rsquo;s Graphical Output Protocol [GOP]) the screen works correctly.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today, I decided to set my X230 back to UEFI-only boot, after having changed that for a bios upgrade recently (to fix a resume bug). I then choose to save the settings and received several error messages telling me that the system ran out of resources (probably storage space for UEFI variables).</p>
<p>I rebooted my machine, and saw no logo appearing. Just something like an underscore on a text console. The system appears to boot normally otherwise, and once the i915 module is loaded (and we&rsquo;re switching away from UEFI&rsquo;s Graphical Output Protocol [GOP]) the screen works correctly.</p>
<p>So it seems the GOP broke.</p>
<p>What should I do next?</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>python-apt now native Python 3 code</title>
      <link>https://blog.jak-linux.org/2014/01/06/python-apt-now-native-python-3-code/</link>
      <pubDate>Mon, 06 Jan 2014 16:46:41 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2014/01/06/python-apt-now-native-python-3-code/</guid>
      <description>&lt;p&gt;Today I made an important change to the python-apt code: It is now native Python 3 code (but also works under Python 2). The previous versions all run 2to3 during the build process to create a Python 3 version. This is no longer needed, as the code is now identical.&lt;/p&gt;
&lt;p&gt;As part of that change, python-apt now only supports Python 2.7, Python 3.3, and newer. I&amp;rsquo;m using some features only present in 3.3 like Python2 unicode literal syntax in order to keep the code simple.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today I made an important change to the python-apt code: It is now native Python 3 code (but also works under Python 2). The previous versions all run 2to3 during the build process to create a Python 3 version. This is no longer needed, as the code is now identical.</p>
<p>As part of that change, python-apt now only supports Python 2.7, Python 3.3, and newer. I&rsquo;m using some features only present in 3.3 like Python2 unicode literal syntax in order to keep the code simple.</p>
<p>Here&rsquo;s how I did it:</p>
<p>I took the Python 2 code and ran 2to3 -f print -x future on it. This turned every print statement in a call to the print function. I then went ahead and added a &ldquo;from <strong>future</strong> import print_function&rdquo; to the top of each module. This was the first commit.</p>
<p>For the second commit, I ran 2to3 -p -x future to convert the remaining stuff to Python 3, and then undid some changes (like unicode literals) and fixed the rest of the changes to work under both Python 2 and 3. Sometimes I added a top-level code like:</p>
<pre><code>if sys.version_info_major &gt;= 3:
    unicode = str
</code></pre>
<p>So I could use unicode in the code for the Python 2 cases.</p>
<p>I used various backported modules like io and stuff only available in Python 2.7, so dropped support for Python 2.6.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>python-apt 0.9 released</title>
      <link>https://blog.jak-linux.org/2013/10/22/python-apt-0-9-released/</link>
      <pubDate>Mon, 21 Oct 2013 22:03:58 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2013/10/22/python-apt-0-9-released/</guid>
      <description>&lt;p&gt;I released python-apt 0.9. This completely removes support for the old API from the code base (it was disabled for the entirety of 0.8 in Debian, and in Ubuntu since saucy). Highlights:  * Cleanup: Complete removal of old-api support code  * Bug fix: Various coverty bug fixes by Michael Vogt  * Bug fix: Correctly handles multi-arch dependencies in apt.debfile, so packagekit and gdebi can now install local multi-arch packages correctly  * Bug fix: A segmentation fault has been fixed. When releasing the value of the policy attribute of an apt_pkg.Cache object, its destructor deleted the pkgPolicy, but that was managed by a CacheFile from APT, causing it to be deleted twice.  * Bug fix: Tests do not depend on the contents of /tmp anymore  * Bug fix: All examples and old tests have been updated to the current python-apt API  * Feature: Paths can now be specified using &amp;lsquo;bytes&amp;rsquo; objects instead of &amp;lsquo;str&amp;rsquo; in Python 3.  * Ubuntu-specific: Meta-data for Ubuntu 14.04 &amp;ndash; although with a typo (&amp;rsquo;thar&amp;rsquo; instead of &amp;rsquo;tahr&amp;rsquo;), but that is fixed in git&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I released python-apt 0.9. This completely removes support for the old API from the code base (it was disabled for the entirety of 0.8 in Debian, and in Ubuntu since saucy). Highlights:  * Cleanup: Complete removal of old-api support code  * Bug fix: Various coverty bug fixes by Michael Vogt  * Bug fix: Correctly handles multi-arch dependencies in apt.debfile, so packagekit and gdebi can now install local multi-arch packages correctly  * Bug fix: A segmentation fault has been fixed. When releasing the value of the policy attribute of an apt_pkg.Cache object, its destructor deleted the pkgPolicy, but that was managed by a CacheFile from APT, causing it to be deleted twice.  * Bug fix: Tests do not depend on the contents of /tmp anymore  * Bug fix: All examples and old tests have been updated to the current python-apt API  * Feature: Paths can now be specified using &lsquo;bytes&rsquo; objects instead of &lsquo;str&rsquo; in Python 3.  * Ubuntu-specific: Meta-data for Ubuntu 14.04 &ndash; although with a typo (&rsquo;thar&rsquo; instead of &rsquo;tahr&rsquo;), but that is fixed in git</p>
<p> </p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Review: ThinkPad X230</title>
      <link>https://blog.jak-linux.org/2013/09/07/thinkpad-x230/</link>
      <pubDate>Sat, 07 Sep 2013 16:43:20 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2013/09/07/thinkpad-x230/</guid>
      <description>&lt;p&gt;This week, a few hours after Lenovo announced the X240, I bought an X230. Normally, the X230 model I bought comes with a Core i5-3320M CPU, 4GB RAM, 500GB HDD. My model was a special set including a second 4GB RAM stick and a 128 GB mSATA Plextor SSD. It came without Windows; and the ThinkVantage button is black instead of blue and has no label.&lt;/p&gt;
&lt;p&gt;I put a fresh installation of unstable on it and tweaked it to save more power when on battery (enabled RC6++, and enabled autosuspend and other powertop suggestions with a script in /etc/pm/power.d); and configured hdparm.conf to put my hard disk into standby after 5 seconds (it&amp;rsquo;s only used for big data anyway, so most of the time it is unused). It now consumes 5W in idle with minimum brightness, and 8-10W with brightness 13 of 15. Consumption when surfing is 10 - 15 watts. Booting from grub to gdm is fast, I did not measure it, but it probably took about 5 seconds.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>This week, a few hours after Lenovo announced the X240, I bought an X230. Normally, the X230 model I bought comes with a Core i5-3320M CPU, 4GB RAM, 500GB HDD. My model was a special set including a second 4GB RAM stick and a 128 GB mSATA Plextor SSD. It came without Windows; and the ThinkVantage button is black instead of blue and has no label.</p>
<p>I put a fresh installation of unstable on it and tweaked it to save more power when on battery (enabled RC6++, and enabled autosuspend and other powertop suggestions with a script in /etc/pm/power.d); and configured hdparm.conf to put my hard disk into standby after 5 seconds (it&rsquo;s only used for big data anyway, so most of the time it is unused). It now consumes 5W in idle with minimum brightness, and 8-10W with brightness 13 of 15. Consumption when surfing is 10 - 15 watts. Booting from grub to gdm is fast, I did not measure it, but it probably took about 5 seconds.</p>
<p>The IPS screen looks really good. Much much much better than the screen in my 2010 Edge 15 (I <a href="http://juliank.wordpress.com/2010/07/05/review-lenovo-thinkpad-edge-15/">reviewed</a> that one in 2010). It seems a bit more glossy than that one, but still matte. Keyboard is good as well. The touch pad is crap however. All hardware seems to work.</p>
<p>Comparison to the X240 for others who think about buying one of them: The X240 is lighter and thinner (it&rsquo;s an Ultrabook) and has an optional FullHD 12.5 inch screen. It also offers a much larger touchpad and palm rest. But compared to the X230, the X240 lacks many things: No dedicated buttons for the trackpoint (you need to use the click-pad), it&rsquo;s limited at 8GB RAM, uses a slower low-voltage Haswell CPU, and it uses the new M.2 connector (probably supporting only the shortest cards) instead of mini-PCIe, so it&rsquo;s not really possible to add an additional SSD currently; as M.2 SSDs do not seem to be available yet. I also do not know whether the X240 offers ThinkLight or LEDs for hard drive activity and similar.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>apt-show-versions rewrite in C&#43;&#43; (more than 10 times faster)</title>
      <link>https://blog.jak-linux.org/2013/04/09/apt-show-versions-rewrite-in-c-more-than-100-times-faster/</link>
      <pubDate>Tue, 09 Apr 2013 18:40:16 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2013/04/09/apt-show-versions-rewrite-in-c-more-than-100-times-faster/</guid>
      <description>&lt;p&gt;The script apt-show-versions is developed by another Debian Developer called Christoph Martin in Perl. Recently, it turned out that apt-show-versions is too slow for some users; so I decided to rewrite his program using APT&amp;rsquo;s C++ API. I expect this to be part of a future APT release, rendering the original apt-show-versions obsolete.&lt;/p&gt;
&lt;p&gt;The rewrite is sadly not 100% backwards compatible to the original version; as some option names had to be renamed due to our command-line parser not supporting option names like -nh, and some other options were dropped because they are hard to support (like &amp;ndash;status-file and &amp;ndash;lists-dir) with our command-line parsing. I also decided not to keep the the -p and -r options, but use the standard APT command-line conventions insteads.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>The script apt-show-versions is developed by another Debian Developer called Christoph Martin in Perl. Recently, it turned out that apt-show-versions is too slow for some users; so I decided to rewrite his program using APT&rsquo;s C++ API. I expect this to be part of a future APT release, rendering the original apt-show-versions obsolete.</p>
<p>The rewrite is sadly not 100% backwards compatible to the original version; as some option names had to be renamed due to our command-line parser not supporting option names like -nh, and some other options were dropped because they are hard to support (like &ndash;status-file and &ndash;lists-dir) with our command-line parsing. I also decided not to keep the the -p and -r options, but use the standard APT command-line conventions insteads.</p>
<p>For now, it also cannot show you the distribution names you have specified in your sources.list file, but will always display codenames instead; if available. I hope to fix this in Jessie by extending APT&rsquo;s cache format a bit.</p>
<p>On the performance side, this program now takes about 0.09s compared to the 1.40 seconds needed by apt-show-versions. The times are taken with all data in caches.</p>
<p>The current version can be found in a git repository, a link to gitweb is:</p>
<p><a href="http://anonscm.debian.org/gitweb/?p=users/jak/apt-show-versions.git">http://anonscm.debian.org/gitweb/?p=users/jak/apt-show-versions.git
</a></p>
<p>Please also note that support for &ndash;allversions is not 100% implemented yet, but it should work for most uses.</p>
<p>Now, go testing and report back!</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Recursive-descent in Python, using generators</title>
      <link>https://blog.jak-linux.org/2013/01/11/recursive-descent-in-python-using-generators/</link>
      <pubDate>Fri, 11 Jan 2013 11:30:48 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2013/01/11/recursive-descent-in-python-using-generators/</guid>
      <description>&lt;p&gt;Writing recursive descent parsers is easy, especially in Python (just like everything is easy in Python). But Python defines a low limit on the number of recursive calls that can be made, and recursive descent parsers are prone to exceed this limit.&lt;/p&gt;
&lt;p&gt;We should thus write our parser without real recursion. Fortunately, Python offers us a way out: Coroutines,  introduced in Python 2.5 as per PEP 342. Using coroutines and a simple trampoline function, we can convert every mutually recursive set of functions into a set of coroutines that require constant stack space.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Writing recursive descent parsers is easy, especially in Python (just like everything is easy in Python). But Python defines a low limit on the number of recursive calls that can be made, and recursive descent parsers are prone to exceed this limit.</p>
<p>We should thus write our parser without real recursion. Fortunately, Python offers us a way out: Coroutines,  introduced in Python 2.5 as per PEP 342. Using coroutines and a simple trampoline function, we can convert every mutually recursive set of functions into a set of coroutines that require constant stack space.</p>
<p>Let&rsquo;s say our parser looks like this (tokens being an iterator over characters):</p>
<pre><code>def parse(tokens):
    token = next(tokens)
    if token.isalnum():
        return token
    elif token == '(':
         result = parse(tokens)
         if next(tokens) != ')': raise ...
         return result
    else:
         raise ...
</code></pre>
<p>We now apply the following transformations:
return X =&gt; yield (X)
parse()  =&gt; (yield parse())</p>
<p>That is, we yield the value we want to return, and we yield a generator whenever we want to call (using a yield expression). Our rewritten parser reads:</p>
<pre><code>def parse(tokens):
    token = next(tokens)
    if token.isalnum():
        yield token
    elif token == '(':
         result = yield parse(tokens)
         if next(tokens) != ')': raise ...
         return result
    else:
         raise ...
</code></pre>
<p>We obviously cannot call that generator like the previous function. What we need to introduce is a trampoline. A trampoline is a function that manages that yielded generators, calls them, and passes their result upwards. It looks like this:</p>
<pre><code>def trampoline(generator):
    &quot;&quot;&quot;Execute the generator using trampolining. &quot;&quot;&quot;
    queue = collections.deque()

    def schedule(coroutine, stack=(), value=None):
        def resume():
            if 0:
                global prev
                now = stack_len(stack)
                if now &lt; prev:
                    print(&quot;Length&quot;, now)
                    prev = -1
                elif prev != -1:
                    prev = now
            result = coroutine.send(value)
            if isinstance(result, types.GeneratorType):     # Normal call
                schedule(result, (coroutine, stack))
            elif isinstance(result, Tail):                  # Tail call (if you want to)
                schedule(result.value, stack)
            elif stack:                                     # Return to parent
                schedule(stack[0], stack[1], result)
            else:                                           # Final Return
                return result

        queue.append(resume)

    schedule(generator)

    result = None
    while queue:
        func = queue.popleft()
        result = func()

    return result
</code></pre>
<p>This function is based on the code in PEP 342, the difference being that</p>
<ul>
<li>we do not correctly propagate exceptions through the stack, but directly unwind to the caller of the parser (we don&rsquo;t handle exceptions inside our parser generators anyway)</li>
<li>the code actually compiles (code in PEP used &lsquo;value = coroutine.send(value)&rsquo; which does not work)</li>
<li>the code returns a value (code in PEP was missing a return in schedule)</li>
<li>we don&rsquo;t use a class, and allow only one function to be scheduled at once (yes, we could get rid of the queue)</li>
<li>we allow tail calls [where Tail = namedtuple(&ldquo;Tail&rdquo;, [&ldquo;result&rdquo;])] to save some more memory.</li>
</ul>
<p>For a more generic version of that, you might want to re-add exception passing, but the exceptions will then have long tracebacks, so I&rsquo;m not sure how well they will work if you have deep recursion.</p>
<p>Now, the advantage of that is that our parser now requires constant stack space, because the actual real stack is stored in the heap using tuples which are used like singly-linked lists in scheme here. So, the only recursion limit is  available memory.</p>
<p>A disadvantage of that transformation is that the code will run slightly slower for small inputs that could be handled using a normally recursive parser.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Cleaning up the system with pseudo-boolean optimization</title>
      <link>https://blog.jak-linux.org/2012/08/16/cleaning-up-the-system-with-pseudo-boolean-optimization/</link>
      <pubDate>Thu, 16 Aug 2012 18:45:08 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2012/08/16/cleaning-up-the-system-with-pseudo-boolean-optimization/</guid>
      <description>&lt;p&gt;You can use a PBO solver to clean up your system from unneeded automatically installed packages. First of all, you convert the system state to PB, and add an optimization function telling it to remove as many automatically installed packages as possible. Then you run this thing through a solver (such as clasp, which seems the fastest solver for PBO instances in the Debian archive) and convert its output to human-readable package names.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>You can use a PBO solver to clean up your system from unneeded automatically installed packages. First of all, you convert the system state to PB, and add an optimization function telling it to remove as many automatically installed packages as possible. Then you run this thing through a solver (such as clasp, which seems the fastest solver for PBO instances in the Debian archive) and convert its output to human-readable package names.</p>
<p>Code is provided at <a href="http://anonscm.debian.org/gitweb/?p=users/jak/cleanup.git">http://anonscm.debian.org/gitweb/?p=users/jak/cleanup.git</a>, under the MPL 2.0. You need to have python-apt and clasp installed to use it. There is potential minisat+ support, but it&rsquo;s currently a bit broken.</p>
<p>To use, run python program_builder.py, and it will tell you which packages are no longer needed on your system. It ignores Suggests, if you want those in, you have to hack the code and replace {&ldquo;Recommends&rdquo;} by {&ldquo;Recommends&rdquo;, &ldquo;Suggests&rdquo;}. You can also turn of such dependencies by setting Program.hard_softdeps to False.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Implicit preferences in OR dependencies</title>
      <link>https://blog.jak-linux.org/2012/08/11/implicit-preferences-in-or-dependencies/</link>
      <pubDate>Sat, 11 Aug 2012 14:27:18 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2012/08/11/implicit-preferences-in-or-dependencies/</guid>
      <description>&lt;p&gt;Debian packages commonly use or dependencies of the form &amp;ldquo;a | b&amp;rdquo; to mean that a or b should be installed, while preferring option a over b. In general, for resolving an or dependency, we will try all options from the left to the right, preferring the left-most option. We also prefer real packages over virtual ones. If one of the alternatives is already installed we use that.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def solve_or(or):
  best_real = None
  best_virtual = None
  for dep in or:
     for target in dep:
        if target.name == dep.name and best_real is None:
           best_real = target
        if target.name != dep.name and best_virtual is None:
           best_virtual = target        
        if target.is_installed():
          return target

  return best_real if best_real is not None else best_virtual
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, this way of solving dependencies is slightly problematic. Let us consider a package that depends on: a | b, b. APT will likely choose to install &amp;lsquo;a&amp;rsquo; to satisfy the first dependency and &amp;lsquo;b&amp;rsquo; to satisfy the second. I currently have draft  code around for a future version of APT that will cause it to later on revert unneeded changes, which means that APT will then only install &amp;lsquo;b&amp;rsquo;. This result closely matches the CUDF solvers and cupt&amp;rsquo;s solver.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Debian packages commonly use or dependencies of the form &ldquo;a | b&rdquo; to mean that a or b should be installed, while preferring option a over b. In general, for resolving an or dependency, we will try all options from the left to the right, preferring the left-most option. We also prefer real packages over virtual ones. If one of the alternatives is already installed we use that.</p>
<pre><code>def solve_or(or):
  best_real = None
  best_virtual = None
  for dep in or:
     for target in dep:
        if target.name == dep.name and best_real is None:
           best_real = target
        if target.name != dep.name and best_virtual is None:
           best_virtual = target        
        if target.is_installed():
          return target

  return best_real if best_real is not None else best_virtual
</code></pre>
<p>Now, this way of solving dependencies is slightly problematic. Let us consider a package that depends on: a | b, b. APT will likely choose to install &lsquo;a&rsquo; to satisfy the first dependency and &lsquo;b&rsquo; to satisfy the second. I currently have draft  code around for a future version of APT that will cause it to later on revert unneeded changes, which means that APT will then only install &lsquo;b&rsquo;. This result closely matches the CUDF solvers and cupt&rsquo;s solver.</p>
<p>On the topic of solving algorithms, we also have the problem that optimizing solvers like the ones used with apt-cudf do not respect the order of dependencies, rather choosing to minimise the number of packages installed. This causes such a solver to often do stuff like selecting an sqlite database as backend for some service rather then a larger SQL server, as that installs fewer packages.</p>
<p>To make such solvers aware of the implicit preferences, we can introduce a new type of dependency category: Weak conflicts, also known as Recommends-Not. If a package P defines a Recommends-Not dependency against a package Q, then this means that Q should not be installed if P is installed. Now, if we have a dependency like:</p>
<p><code>Depends: a | b | c</code></p>
<p>we can encode this as:</p>
<p><code>Recommends-Not: c, c, b</code></p>
<p>Causing the solver to prefer a, then b, and then c. This should be representable as a pseudo-boolean optimization problem, as is common for the dependency problem, although I have not looked at that yet &ndash; it should work by taking the standard representation of conflicts, adding a relaxation variable and then minimising [or maximising] the number of relaxation variables.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Memory allocators</title>
      <link>https://blog.jak-linux.org/2012/05/31/memory-allocators/</link>
      <pubDate>Thu, 31 May 2012 09:43:00 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2012/05/31/memory-allocators/</guid>
      <description>&lt;p&gt;In the past days, I looked at various memory allocators in a quest to improve performance in my multi-threaded test cases of a reference counting language runtime / object allocator (a fun project).&lt;/p&gt;
&lt;p&gt;It turns out the glibc&amp;rsquo;s memory allocator is relatively slow, especially if you do loops that create one element and destroy one element at the same time (for example, map() on a list you no longer use after you passed it to map). To fix this problem, I considered various options.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>In the past days, I looked at various memory allocators in a quest to improve performance in my multi-threaded test cases of a reference counting language runtime / object allocator (a fun project).</p>
<p>It turns out the glibc&rsquo;s memory allocator is relatively slow, especially if you do loops that create one element and destroy one element at the same time (for example, map() on a list you no longer use after you passed it to map). To fix this problem, I considered various options.</p>
<p>The first option was to add a thread-local cache around malloc(). So whenever we want to free() an object, we place it on  a thread-local list instead, and if a malloc() request for an object of that size comes in, we reuse the old object.</p>
<p>This fixes the problem with the lists, but experiments shown another problem with the glibc allocator: Allocating many objects without releasing others (let&rsquo;s say appending an element to a functional list). I started testing with tcmalloc instead, and noticed that it was several times faster (reducing run time from 6.75 seconds to 1.33 seconds (5 times faster)). As I do not want to depend on a C++ code base, I decided to write a simple allocator that allocates blocks of memory via mmap(), splits those into objects, and puts the objects on a local free list. That allocator performed faster than tcmalloc(), but was also just a simple test case, and not really useable, due to potential fragmentation problems (and because the code was statically linked in, causing thread-local storage to be considerably faster, as it does not need to call a function on every TLS access, but can rather go through a segment register).</p>
<p>I then discovered jemalloc, and tried testing with this. It turned out that jemalloc was even faster than tcmalloc in all test cases, and also required about the same amount of memory as tcmalloc (and slightly more than the custom test code, as that combined reference counting with memory allocator metadata and thus had less meta data overhead). Using jemalloc, the list building test performs in 0.9X seconds now (instead of tcmalloc&rsquo;s 1.33 or glibc&rsquo;s 6.75 seconds), requires 0 major page faults (tcmalloc has 2), and uses 5361472 kb memory (tcmalloc uses 5290240, glibc requires 7866608).</p>
<p>Given that jemalloc is written in C, I can only recommend it to everyone in need of a scalable memory allocator. Depending on your workload, it might require less memory than tcmalloc (at least that&rsquo;s the case at Facebook) and is most likely faster than tcmalloc. It also provides tcmalloc-compatible profiling facilities (as Facebook needed them). Furthermore, jemalloc is also the memory allocator used by FreeBSD, and is used by Mozilla projects, and on several Facebook projects, and should thus be relatively stable and useable.</p>
<p>All tests were run with 4 threads, on a dual-core laptop with hyper-threading, using (e)glibc 2.13, tcmalloc 2.0, and jemalloc 3.0. The tests may not be representative of real world performance, and do not account for fragmentation.</p>
<p>Should I try replacing Python&rsquo;s custom caching of malloc() calls with simply calling jemalloc, and run a few Python benchmarks? Anyone interested in that?</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Reference Counting and Tail Calls</title>
      <link>https://blog.jak-linux.org/2012/04/22/reference-counting-and-tail-calls/</link>
      <pubDate>Sun, 22 Apr 2012 17:05:40 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2012/04/22/reference-counting-and-tail-calls/</guid>
      <description>&lt;p&gt;One thing I thought about today is reference counting in combination with tail calls. Imagine a function like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function f(x) { return g(x+1); }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now consider that &lt;code&gt;x&lt;/code&gt; is a reference counted object and that &lt;code&gt;x + 1&lt;/code&gt; creates a new object. The call to &lt;code&gt;g(x + 1)&lt;/code&gt; shall be in tail call position.&lt;/p&gt;
&lt;p&gt;In most reference counted languages, the reference to an argument is owned by the caller. That is, &lt;code&gt;f()&lt;/code&gt; owns the reference to &lt;code&gt;x + 1&lt;/code&gt;. In that case, the call to &lt;code&gt;g()&lt;/code&gt; would no longer be in a tail call position, as we still have to decrease the reference count after &lt;code&gt;g()&lt;/code&gt; exits.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>One thing I thought about today is reference counting in combination with tail calls. Imagine a function like this:</p>
<pre><code>function f(x) { return g(x+1); }
</code></pre>
<p>Now consider that <code>x</code> is a reference counted object and that <code>x + 1</code> creates a new object. The call to <code>g(x + 1)</code> shall be in tail call position.</p>
<p>In most reference counted languages, the reference to an argument is owned by the caller. That is, <code>f()</code> owns the reference to <code>x + 1</code>. In that case, the call to <code>g()</code> would no longer be in a tail call position, as we still have to decrease the reference count after <code>g()</code> exits.</p>
<p>An alternative would be that the callee owns the reference. This however, will most likely create far more reference count changes than a caller-owns language (increase reference count in caller, decrease reference count in callee). For example, the following function requires an increment before the call to <code>g()</code>.</p>
<pre><code>function f1(x) { return g(x); }
</code></pre>
<p>Does anyone have any ideas on how to solve the problem of tail calls while avoiding the callee-owns scenario? Something that does not require a (non-reference-counting) garbage collector would be preferably.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Currying in the presence of mutable parameters</title>
      <link>https://blog.jak-linux.org/2012/04/02/currying-in-the-presence-of-mutable-parameters/</link>
      <pubDate>Mon, 02 Apr 2012 11:43:17 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2012/04/02/currying-in-the-presence-of-mutable-parameters/</guid>
      <description>&lt;p&gt;In the language introduced yesterday, mutable parameters play the important role of representing the side effects of actions in the type system and thus ensure referential transparency.&lt;/p&gt;
&lt;p&gt;One of the questions currently unaddressed is how to handle currying in the presence of mutable parameters. In order to visualise this problem, consider a function&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    printLn(mutable IO, String line)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we bind the the first parameter, what should be the type of the function, and especially important how do we get back the mutable parameter? Consider the partially applied form printLn1:&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>In the language introduced yesterday, mutable parameters play the important role of representing the side effects of actions in the type system and thus ensure referential transparency.</p>
<p>One of the questions currently unaddressed is how to handle currying in the presence of mutable parameters. In order to visualise this problem, consider a function</p>
<pre><code>    printLn(mutable IO, String line)
</code></pre>
<p>If we bind the the first parameter, what should be the type of the function, and especially important how do we get back the mutable parameter? Consider the partially applied form printLn1:</p>
<pre><code>    printLn1(String line)
</code></pre>
<p>The mutability parameter would be lost and we could not do any further I/O (and the curried form would appear as a pure function, so a good compiler would not even emit a call to it) An answer might be to put the thing into the result when currying:</p>
<pre><code>    printLn2(String line) -&gt; mutable IO
</code></pre>
<p>But how can we explain this? In the end result, do we maybe have to use a signature like:</p>
<pre><code>    printLn(String, mutable in IO io1, mutable out IO io2)
</code></pre>
<p>We could then introduce syntax to call that as</p>
<pre><code>    printLn(string, mutable io)
</code></pre>
<p>Where as the &ldquo;mutable io&rdquo; argument basically expands to &ldquo;io&rdquo; and &ldquo;io1&rdquo; for the first call, and for later calls to &ldquo;io1, io2&rdquo;, and so on. It can also be easily curried by allowing currying to take place on variables not declared as output parameters. We can then curry the function as:</p>
<pre><code>    printLn3(mutable in IO io1, mutable out IO io2)
    printLn4(mutable out IO io2)
</code></pre>
<p>If so, we can rename <strong>mutable</strong> back to <strong>unique</strong> and make that easier by introducing the unary operator <code>&amp;</code> for two locations, just like Mercury uses <code>!</code> for it. We could then write calls looking like this:</p>
<pre><code>    printLn(&quot;Hello&quot;, &amp;io);
    printLn(&quot;Hello&quot;, io, io1);
</code></pre>
<p>How <strong>out</strong> parameters are explained is a different topic; we could probably say that an <strong>out</strong> parameter defines a new variable.</p>
<p>Another option is to forbid currying of mutable parameters entirely. This would have the advantage of maintaining the somewhat simple one parameter style.</p>
<p>The programming language <em>Clean</em> does not provide any special syntactic sugar for having mutable variables. In Clean, the function gets a unique object and returns a unique object (noted by <code>*</code>). For example, the main entry point in a Clean program (with state) looks like this:</p>
<pre><code>    Start:: *World -&gt; *World
</code></pre>
<p>In short, the function Start gets a abstract world passed that is unique and at the end returns a new unique world. In Clean syntax, our example function would most likely have the signature:</p>
<pre><code>    printLn :: String *IO -&gt; *IO
</code></pre>
<p>You know have to either maintain one additional variable for the new unique object, which gets a bit complicated with time. On the other hand, you can do function composition on this (if you have a function composition operator that preserves uniqueness when available, as should be possible in Clean):</p>
<pre><code>    printTwoLines :: *IO -&gt; *IO 
    printTwoLines = (printLn &quot;World&quot;) o (printLn &quot;Hello&quot;)
</code></pre>
<p>Function composition on mutable things however, does not seem like it is needed often enough in a functional programming language with a C syntax.</p>
<p>People might also ask why monads are not used instead. Simon L Peyton Jones and Philip Wadler described monadic I/O in their paper &ldquo;Imperative Functional Programming&rdquo; (<a href="http://research.microsoft.com/en-us/um/people/simonpj/papers/imperative.ps.Z">http://research.microsoft.com/en-us/um/people/simonpj/papers/imperative.ps.Z</a>) in 1993, and it is used in Haskell (the paper was about the implementation in Haskell anyway), one of the world&rsquo;s most popular and successful functional programming languages.</p>
<p>While monadic I/O works for the Haskell crowd, and surely some other people, the use of Monads also limits the expressiveness of code, at least as far as I can tell. At least as soon as you want to combine multiple monads, you will have to start lifting stuff from one monad to another (<code>liftIO</code> and friends), or perform all operations in the IO monad, which prevents obvious optimizations (such as parallelizing the creation of two arrays) &ndash; in short dependencies between actions are more strict than they have to be. For a functional language targeting imperative programmers, the lifting part seems a bit too complicated.</p>
<p>One of the big advantages of monads is that they are much easier to implement, as they do not require extensions to the type system and the Hindley-Milner type inference algorithm used by the cool functional programming languages. If you want uniqueness typing however, you need to modify the algorithm or infer the basic types first and then infer uniqueness in a second pass (as Clean seems to do it).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Functional programming language for Python programmers and friends</title>
      <link>https://blog.jak-linux.org/2012/04/01/functional-programming-language-for-python-programmers-and-friends/</link>
      <pubDate>Sun, 01 Apr 2012 16:33:17 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2012/04/01/functional-programming-language-for-python-programmers-and-friends/</guid>
      <description>&lt;p&gt;Just for you, and this time in the Pythonesque rendering.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;module main:
    import std (range)
    import std.io (printf, IO)

    # print the Fahrenheit-Celcius table for fahr = 0, 20, ..., 300
    function main(mutable IO io):
        Int lower = 0    # lower bound
        Int upper = 300  # upper bound
        Int step = 20    # step
        for Int fahr in range(lower, upper, step):
            Double celcius = 5 * (fahr - 32) / 9
            std.io.printf(io, &amp;quot;%3d\t%6.1f\n&amp;quot;, fahr, celcius)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It does not really look like it, but this language is purely functional. It represents side effects using unique types. If you declare a mutable parameter, you basically declare a unique input parameter and a unique output parameter.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Just for you, and this time in the Pythonesque rendering.</p>
<pre><code>module main:
    import std (range)
    import std.io (printf, IO)

    # print the Fahrenheit-Celcius table for fahr = 0, 20, ..., 300
    function main(mutable IO io):
        Int lower = 0    # lower bound
        Int upper = 300  # upper bound
        Int step = 20    # step
        for Int fahr in range(lower, upper, step):
            Double celcius = 5 * (fahr - 32) / 9
            std.io.printf(io, &quot;%3d\t%6.1f\n&quot;, fahr, celcius)
</code></pre>
<p>It does not really look like it, but this language is purely functional. It represents side effects using unique types. If you declare a mutable parameter, you basically declare a unique input parameter and a unique output parameter.</p>
<p>I’m also giving you a list implementation</p>
<pre><code>module std.container.list:

    ## The standard singly-linked list type
    type List[E]:
        Nil                     ## empty list
        Node:
            E value             ## current value
            List[E] next        ## remaining list
</code></pre>
<p>_
_And yes, both languages should be able to be represented using the same abstract syntax tree. The only change is the replacement of the opening curly brace by a colon, the removal of the closing curly bracket and semicolons, the replacement of C-style comments with Python-style comments and the requirement of indentation; oh and the for statement gets a bit lighter as well.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>[updated] Functional programming language for C programmers and friends</title>
      <link>https://blog.jak-linux.org/2012/04/01/mutable-types-and-functional-programming/</link>
      <pubDate>Sun, 01 Apr 2012 15:41:17 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2012/04/01/mutable-types-and-functional-programming/</guid>
      <description>&lt;p&gt;Just for you:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;module main {
    import std (range);
    import std.io (printf, IO);
 
    /* print the Fahrenheit-Celcius table
        for fahr = 0, 20, ..., 300 */
    function main(mutable IO io) {
        Int lower = 0;   // lower bound
        Int upper = 300; // upper bound
        Int step = 20;   // step
        for (Int fahr in range(lower, upper, step)) {
            Double celcius = 5 * (fahr - 32) / 9;
            std.io.printf(io, &amp;quot;%3d\t%6.1f\n&amp;quot;, fahr, celcius);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It does not really look like it, but this language is purely functional. It represents side effects using unique types. If you declare a mutable parameter, you basically declare a unique input parameter and a unique output parameter.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Just for you:</p>
<pre><code>module main {
    import std (range);
    import std.io (printf, IO);
 
    /* print the Fahrenheit-Celcius table
        for fahr = 0, 20, ..., 300 */
    function main(mutable IO io) {
        Int lower = 0;   // lower bound
        Int upper = 300; // upper bound
        Int step = 20;   // step
        for (Int fahr in range(lower, upper, step)) {
            Double celcius = 5 * (fahr - 32) / 9;
            std.io.printf(io, &quot;%3d\t%6.1f\n&quot;, fahr, celcius);
        }
    }
}
</code></pre>
<p>It does not really look like it, but this language is purely functional. It represents side effects using unique types. If you declare a mutable parameter, you basically declare a unique input parameter and a unique output parameter.</p>
<p>I&rsquo;m also giving you a list implementation</p>
<pre><code>module std.container.list {

    /** The standard singly-linked list type */
    type List[E] {
        Nil;                    /** empty list */
        Node {
            E value;            /** current value */
            List[E] next;       /** remaining list */
        }
    }
}
</code></pre>
<p>Thus are only excerpts from a document with tens of pages and the reference implementation of the standard library. The incomplete working draft for the language is attached: <a href="https://juliank.files.wordpress.com/2012/04/jlang1.pdf">JAK Programming Language Early Working Draft (28 pages)</a>.</p>
<p><strong>Update:</strong> Fixed the link.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>hardlink 0.2 RC1 released</title>
      <link>https://blog.jak-linux.org/2012/03/03/hardlink-0-2-rc1-released/</link>
      <pubDate>Sat, 03 Mar 2012 18:39:55 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2012/03/03/hardlink-0-2-rc1-released/</guid>
      <description>&lt;p&gt;I have just released version 0.2 RC1 of my hardlink program. Compared to the 0.1.X series, the program has been rewritten in C, as Python was to memory-hungry for people with millions of files. The new program uses almost the same algorithm and has almost completely the same bugs as the old version.&lt;/p&gt;
&lt;p&gt;The code should be portable to all UNIX-like platforms supporting nftw(). I have tested the code on Debian, FreeBSD 9, and Minix 3.2. For storing path names, it uses a flexible array member on C99 compilers, a zero-length-array on GNU compilers, and a array of length 1 on all other compilers (which should work everywhere as far as I heard).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I have just released version 0.2 RC1 of my hardlink program. Compared to the 0.1.X series, the program has been rewritten in C, as Python was to memory-hungry for people with millions of files. The new program uses almost the same algorithm and has almost completely the same bugs as the old version.</p>
<p>The code should be portable to all UNIX-like platforms supporting nftw(). I have tested the code on Debian, FreeBSD 9, and Minix 3.2. For storing path names, it uses a flexible array member on C99 compilers, a zero-length-array on GNU compilers, and a array of length 1 on all other compilers (which should work everywhere as far as I heard).</p>
<p>The new version may have slightly different behaviour compared to 0.1.2 when regular expressions are specified on the command-line, as a result of the switch from Python&rsquo;s regular expression engine to PCRE (if compiled with PCRE support, you can also use POSIX extended regular expressions if you like).</p>
<p>The code is significantly faster than the old code (in situations where it&rsquo;s not I/O bound), and uses much less memory than the old one. Per file, we now store a <!-- raw HTML omitted -->struct stat<!-- raw HTML omitted -->, a pointer, an int, a char, and the filename; as well as three pointers for a binary search tree (which uses tsearch()).</p>
<p>It should also be compatible to Red Hat&rsquo;s original hardlink tool now command-line-wise, there is at least a -c option now. The history and the name conflict are interesting, but probably nothing for this post. We&rsquo;re even less resistant against changing trees than Fedora&rsquo;s tool (and derived) currently, but should otherwise be better (and far more complicated and feature-packed). And we don&rsquo;t require mmap(), but use fread() instead. There was no real performance difference in testing. And we are not GPL-licensed, but use the MIT/Expat license.</p>
<p>The package is currently entering Debian experimental for testing purposes. If you have used hardlink previously, or are just curious, give it try.</p>
<p>And the makefile is now compatible with the various BSD makes out there, if that&rsquo;s interesting for you.</p>
<p>Link to website: <a href="http://jak-linux.org/projects/hardlink/">http://jak-linux.org/projects/hardlink/</a></p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Managing system package selections using custom meta packages</title>
      <link>https://blog.jak-linux.org/2012/01/24/managing-system-package-selections-using-custom-meta-packages/</link>
      <pubDate>Tue, 24 Jan 2012 09:43:05 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2012/01/24/managing-system-package-selections-using-custom-meta-packages/</guid>
      <description>&lt;p&gt;Over the last years, I have developed a variety of metapackages for managing the package selections of the systems I administrate. The meta packages are organized like this:&lt;/p&gt;
&lt;p&gt;jak-standard&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Standard packages for all systems
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;jak-desktop&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Standard packages for all desktop systems (GNOME 3 if possible, otherwise GNOME 2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;jak-printing&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Print support
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;jak-devel&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Development packages
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;jak-machine-&amp;lt;X&amp;gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;The meta package defining the computer X
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each computer has a jak-machine-X package installed. This package is marked as manually installed, all other packages are marked as automatically installed.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Over the last years, I have developed a variety of metapackages for managing the package selections of the systems I administrate. The meta packages are organized like this:</p>
<p>jak-standard</p>
<pre><code>Standard packages for all systems
</code></pre>
<p>jak-desktop</p>
<pre><code>Standard packages for all desktop systems (GNOME 3 if possible, otherwise GNOME 2)
</code></pre>
<p>jak-printing</p>
<pre><code>Print support
</code></pre>
<p>jak-devel</p>
<pre><code>Development packages
</code></pre>
<p>jak-machine-&lt;X&gt;</p>
<pre><code>The meta package defining the computer X
</code></pre>
<p>Each computer has a jak-machine-X package installed. This package is marked as manually installed, all other packages are marked as automatically installed.</p>
<p>The machine packages have the attribute <code>XB-Important: yes</code> set in debian/control. This creates an <code>Important: yes</code> field. This field is not official, but APT recognizes it and does not remove those packages (the same field is set for the APT package by APT when building the cache, as APT should not be removed either by APT). It seems to work a bit like <code>Essential</code>, with the exception that non-installed packages are not installed automatically on <code>dist-upgrade</code>.</p>
<p>The meta packages are created using seed files similar to Ubuntu. In contrast to Ubuntu, I&rsquo;m not using <code>germinate</code> to create the packages from the seeds, but a custom <code>dh_germinate_lite</code> that simply takes a seed file and creates the correct substvars. It&rsquo;s faster than germinate and really simplistic. It also does not handle Recommends currently.</p>
<p>The whole result can be seen on <a href="http://anonscm.debian.org/gitweb/?p=users/jak/jak-meta.git">http://anonscm.debian.org/gitweb/?p=users/jak/jak-meta.git</a>. Maybe that&rsquo;s useful for some people. And if you happen to find some packages in the seeds that are deprecated, please let me know. Oh, and yes, some packages (such as the letterman one) are internal software not publically available yet [letterman is a simple GUI for creating letters using LaTeX].</p>
<p>While I&rsquo;m at it, I also built Ubuntu&rsquo;s version of wine1.2 for i386 squeeze. It can be found in
<code>deb [http://people.debian.org/~jak/debian/](http://people.debian.org/~jak/debian/) squeeze main</code> (it still needs a few changes to be correct though, I&rsquo;ll upload a jak2 build soon). I also built updated sun-java6 packages for my parents (mostly needed due to the plugin, some websites do not work with the IcedTea one), but can&rsquo;t share the binaries due to licensing requirements. I may push out a source repository, though, so others can build those packages themselves. I&rsquo;ll let you know once that&rsquo;s done.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Combining ikiwiki and Twitter&#39;s bootstrap</title>
      <link>https://blog.jak-linux.org/2011/12/09/combining-ikiwiki-and-twitters-bootstrap/</link>
      <pubDate>Fri, 09 Dec 2011 21:07:43 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2011/12/09/combining-ikiwiki-and-twitters-bootstrap/</guid>
      <description>&lt;p&gt;Just because Julien did it, I moved my website to almost the same design now. Still using ikiwiki, of course. I&amp;rsquo;m still missing a few things, such as marking the currently active page in the menu, but I hope to get that done as well soon. Go  to &lt;a href=&#34;http://jak-linux.org/&#34;&gt;http://jak-linux.org/&lt;/a&gt; to see it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Just because Julien did it, I moved my website to almost the same design now. Still using ikiwiki, of course. I&rsquo;m still missing a few things, such as marking the currently active page in the menu, but I hope to get that done as well soon. Go  to <a href="http://jak-linux.org/">http://jak-linux.org/</a> to see it.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Looking for HP Touchpad, Intel tablets, and other devices</title>
      <link>https://blog.jak-linux.org/2011/08/23/looking-for-hp-touchpad-intel-tablets-and-other-devices/</link>
      <pubDate>Tue, 23 Aug 2011 11:19:13 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2011/08/23/looking-for-hp-touchpad-intel-tablets-and-other-devices/</guid>
      <description>&lt;p&gt;If someone in Germany (or want to send it to Germany [at low costs]) still has (new) Touchpads to sell, I&amp;rsquo;d buy one or two of them at the reduced price (16GB: 99€, 32GB: 129€), or take them for free.&lt;/p&gt;
&lt;p&gt;I promise that I will not sell them to others. I&amp;rsquo;m interested in WebOS, in running Debian and/or Ubuntu on those devices (for the extra fun  factor), and lend it to family members for surfing, etc.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>If someone in Germany (or want to send it to Germany [at low costs]) still has (new) Touchpads to sell, I&rsquo;d buy one or two of them at the reduced price (16GB: 99€, 32GB: 129€), or take them for free.</p>
<p>I promise that I will not sell them to others. I&rsquo;m interested in WebOS, in running Debian and/or Ubuntu on those devices (for the extra fun  factor), and lend it to family members for surfing, etc.</p>
<p>I also take other tablets and smart phones and various kinds of ARM and PowerPC hardware (I guess that&rsquo;s all that&rsquo;s interesting for me) for free, just send me an email if you have some and want to give them to me. This applies to Intel stuff as well, I&rsquo;d really like to get some kind of WeTab/ExoPC, but can&rsquo;t buy one currently (and they&rsquo;re probably to outdated hardware-wise for buying to make sense).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>World, Space, and Licenses</title>
      <link>https://blog.jak-linux.org/2011/08/11/world-space-and-licenses/</link>
      <pubDate>Thu, 11 Aug 2011 09:15:36 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2011/08/11/world-space-and-licenses/</guid>
      <description>&lt;p&gt;Common licenses for software include the term &amp;ldquo;worldwide&amp;rdquo;. Now, what does worldwide mean? The problem with the term worldwide is that it is ambigous and depending on it&amp;rsquo;s interpretation, violates against DFSG 6 which states: &amp;ldquo;No Discrimination Against Fields of Endeavor&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The reason: Space travel. If we take the term worldwide to mean &amp;ldquo;everywhere on earth&amp;rdquo;, the license becomes non-free, as it prohibits the use outside of this planet. Affected by this problem are the patent section of GPL-3, the Apache 2.0 license, the CC licenses, the GFDL, and probably also others.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Common licenses for software include the term &ldquo;worldwide&rdquo;. Now, what does worldwide mean? The problem with the term worldwide is that it is ambigous and depending on it&rsquo;s interpretation, violates against DFSG 6 which states: &ldquo;No Discrimination Against Fields of Endeavor&rdquo;.</p>
<p>The reason: Space travel. If we take the term worldwide to mean &ldquo;everywhere on earth&rdquo;, the license becomes non-free, as it prohibits the use outside of this planet. Affected by this problem are the patent section of GPL-3, the Apache 2.0 license, the CC licenses, the GFDL, and probably also others.</p>
<p>Now what should be used instead? Universal? No, that wouldn&rsquo;t work in case there are multiple ones (while travelling between them (if they exist) could be impossible, it would still be a restriction). The correct team would probably be &ldquo;omniversal&rdquo; meaning &ldquo;everywhere in the omniverse&rdquo;. But really, avoiding locations is probably the best way.</p>
<p>In any case, if you have received software from me under a license that uses the term &ldquo;worldwide&rdquo;, you can treat worldwide as everywhere, and are thus free to use it outside of earth (and other planets).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>dh-autoreconf v4 released, patching ltmain.sh for as-needed support</title>
      <link>https://blog.jak-linux.org/2011/06/15/dh-autoreconf-v4-released-patching-ltmain-sh-for-as-needed-support/</link>
      <pubDate>Wed, 15 Jun 2011 18:28:20 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2011/06/15/dh-autoreconf-v4-released-patching-ltmain-sh-for-as-needed-support/</guid>
      <description>&lt;p&gt;Yesterday I released version 4 of dh-autoreconf, fixing two bugs, and introducing a new feature: Patching ltmain.sh to make -Wl,&amp;ndash;as-needed work.&lt;/p&gt;
&lt;p&gt;For this new feature, run dh_autoreconf with the &amp;ndash;as-needed option. dh_autoreconf will then patch all ltmain.sh equal to the system one (which should be all ltmain.sh files if libtoolize ran before or via dh_autoreconf). On clean, dh_autoreconf_clean reverses the patch again.&lt;/p&gt;
&lt;p&gt;So, if your package runs autoreconf, and patches ltmain.sh via a patch you can now do this automatically via dh-autoreconf and be future-proof.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Yesterday I released version 4 of dh-autoreconf, fixing two bugs, and introducing a new feature: Patching ltmain.sh to make -Wl,&ndash;as-needed work.</p>
<p>For this new feature, run dh_autoreconf with the &ndash;as-needed option. dh_autoreconf will then patch all ltmain.sh equal to the system one (which should be all ltmain.sh files if libtoolize ran before or via dh_autoreconf). On clean, dh_autoreconf_clean reverses the patch again.</p>
<p>So, if your package runs autoreconf, and patches ltmain.sh via a patch you can now do this automatically via dh-autoreconf and be future-proof.</p>
<p>The only problem is that this might break once the patch no longer applies to libtool, at which point I need to update the package to include an updated patch. A solution for this problem would be to include the patch in libtool itself, as I proposed in <a href="http://bugs.debian.org/347650">Bug#347650</a>.</p>
<p>In case this works well, the option could also become the default which would make things even easier.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>0x15 &#43; 1/365</title>
      <link>https://blog.jak-linux.org/2011/05/30/015-1365/</link>
      <pubDate>Mon, 30 May 2011 17:36:43 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2011/05/30/015-1365/</guid>
      <description>&lt;p&gt;Yesterday was my 21st birthday, and I received all &amp;ldquo;Hitchhiker&amp;rsquo;s Guide to the Galaxy&amp;rdquo; novels, the five ones in one book, and the sixth one written by Eoin Colfer in another book. Needless to say, the first book weights more than an N900. I did not read them yet, so now is the perfect chance to do so. Yes, I did not know that 25th is towel day, sorry for that.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Yesterday was my 21st birthday, and I received all &ldquo;Hitchhiker&rsquo;s Guide to the Galaxy&rdquo; novels, the five ones in one book, and the sixth one written by Eoin Colfer in another book. Needless to say, the first book weights more than an N900. I did not read them yet, so now is the perfect chance to do so. Yes, I did not know that 25th is towel day, sorry for that.</p>
<p><a href="/images/2011-05-30-015-1365/20110529_001.jpg"><img src="/images/2011-05-30-015-1365/20110529_001.jpg?w=300" alt="">
</a></p>
<p>I also bought a Toshiba AC100 before my birthday, a Tegra 2 based notebook/netbook/&ldquo;web companion&rdquo; with 1 GHz dual core ARM Cortex A9 chip and 512 MB RAM. It runs Android by default, and had a price of 160€ which is low compared to anything else with Cortex A9. It currently runs Ubuntu 11.04 with a specialised kernel 2.6.37 from time to time, without sound and accelerated video (and not functioning HDMI). Mostly waiting for Nvidia to release a new binary blob for the video part (And yes, if you just want to build packages, you can probably get happy without those things).</p>
<p>Another thing happening last week is the upload of python-apt 0.8.0 to unstable, marking the beginning (or end) of the API transition I started more than a year ago. Almost all packages not supporting it have proper Breaks in python-apt [most of them already fixed, only 2 packages remaining, one of which is &ldquo;maintained&rdquo; (well, not really maintained right now) by me], but there may be some which do not work correctly despite being fixed (or at least thought to be fixed).</p>
<p>If you know any other interesting thing I did last week, leave a comment, I wrote enough now. And yes, Wordpress wants to write a multiplication sign instead of an x, so I had to use &amp;#120 instead.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Project APT2: new cache format and small things</title>
      <link>https://blog.jak-linux.org/2011/05/11/project-apt2-new-cache-format-and-small-things/</link>
      <pubDate>Wed, 11 May 2011 16:52:57 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2011/05/11/project-apt2-new-cache-format-and-small-things/</guid>
      <description>&lt;p&gt;I did not write much code or merge much of my prototype code, but some things happened since the last blog post about APT2 specific things in August and I forgot to write about them.&lt;/p&gt;
&lt;p&gt;First of all, I dropped the GVariant-based cache. The format strings were simply getting ugly long and were not very understandable, performance was just much too slow (needing more than a few nanoseconds for a package lookup is obviously too slow for solving dependency problems); furthermore, building the cache was also slow and complicated because we needed all attributes of an object at once to pass them to GVariant, leading to ugly API.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I did not write much code or merge much of my prototype code, but some things happened since the last blog post about APT2 specific things in August and I forgot to write about them.</p>
<p>First of all, I dropped the GVariant-based cache. The format strings were simply getting ugly long and were not very understandable, performance was just much too slow (needing more than a few nanoseconds for a package lookup is obviously too slow for solving dependency problems); furthermore, building the cache was also slow and complicated because we needed all attributes of an object at once to pass them to GVariant, leading to ugly API.</p>
<p>I replaced the GVariant cache with one that can be easily mmap()ed and is described completely in C. It&rsquo;s derived from APT&rsquo;s cache design (but more robust, as it includes the size of the cache and we can thus detect to small files, although that&rsquo;s scheduled for the next ABI break in APT as well), but has fewer duplicate data, and uses arrays where APT uses linked lists. The reason for arrays is simple: They take up less space and can be represented naturally in Python and other languages using array-based lists. The cache also contains a coalesced hash table which does use a linked list, but that one is a bit different, as it is for searching only and not exposed. Everything non-stringy is 64-bit aligned in order to keep things as simple as possible. All integers are fixed size, thus the format is architecture-independent if you fix byte orders. The format is described at <a href="http://people.debian.org/~jak/apt2-doc/apt-Cache-Format.html">http://people.debian.org/~jak/apt2-doc/apt-Cache-Format.html</a>.</p>
<p>I stole one more idea from cupt and changed the configuration system to verify types of variables. APT2&rsquo;s configuration system knows more types than cupt&rsquo;s, though, including regular expressions, directory and filenames (i.e. it does not let you store a value /d/ in a file variable), strings (which store everything), unsigned and signed integers, and boolean options; all of which are checked when parsing files (producing warnings) or command-line options (producing errors).</p>
<p>I have also simplified the type world by removing all iterator types except for one, replacing them with <code>get_thing()</code> and <code>n_things()</code> functions in the objects holding the arrays. Makes cool bindings slightly harder, but makes the C API much easier to use from C.</p>
<p>Most things expected from a package manager are still missing, but what is there looks good in most cases (especially <code>AptConfiguration</code> has a nice API, and no complaints from valgrind anywhere). Currently I am working on Python bindings so I can interact with the functions easily and check things in an interactive fashion; and I am also writing a document explaining the concepts behind APT2, drafts at <a href="http://people.debian.org/~jak/midlevel.pdf">http://people.debian.org/~jak/midlevel.pdf</a>. I also have some more code pending further thoughts (including complete index parsing), but it might still take some time before I have something usable in the wild.</p>
<p>On other package managers: From time to time I also use Cupt, look at Cupt code, hack Cupt code, and report bugs against Cupt. I still do not really understand the (extreme) nesting of directory structures in the source code, why there are so (extremely) many source files split all over them, or the general concepts of Cupt, but I can hack together what I need for my personal testing. I also play with yum whenever I end up on a Fedora system (which happens from time to time).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>underscores and undefined behavior</title>
      <link>https://blog.jak-linux.org/2011/05/11/underscores-and-undefined-behavior/</link>
      <pubDate>Wed, 11 May 2011 16:05:28 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2011/05/11/underscores-and-undefined-behavior/</guid>
      <description>&lt;p&gt;As everyone should know, underscores in C are not cool, as they cause undefined behavior per 7.1.3:&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;Yet, they are widely used everywhere. Here are some examples:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  * inclusion guards in GLib: ` __G_VARIANT_H__`
      * internal Python functions: `_PyUnicode_AsString`
      * various macros in APT: `__deprecated`, `__hot`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All of this triggers undefined behavior and is thus uncool. Of course in APT, it&amp;rsquo;s most stupid, as we do not have any namespace and could thus
end up redefining things we should not much more likely then the other two.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>As everyone should know, underscores in C are not cool, as they cause undefined behavior per 7.1.3:</p>
<!-- raw HTML omitted -->
<p>Yet, they are widely used everywhere. Here are some examples:</p>
<pre><code>  * inclusion guards in GLib: ` __G_VARIANT_H__`
      * internal Python functions: `_PyUnicode_AsString`
      * various macros in APT: `__deprecated`, `__hot`
</code></pre>
<p>All of this triggers undefined behavior and is thus uncool. Of course in APT, it&rsquo;s most stupid, as we do not have any namespace and could thus
end up redefining things we should not much more likely then the other two.</p>
<p>But why were those solutions chosen in the first place, and what is the alternative? I cannot answer the first question, but for the second one, the obvious alternative is to use trailing underscores:</p>
<pre><code>  * inclusion guards, defined behavior: ` G_VARIANT_H__`
      * internal functions, defined behavior: `PyUnicode_AsString_`
      * various macros, defined behavior: `deprecated__`, `hot__`
</code></pre>
<p>Then there is another class of reserved identifiers with underscores:</p>
<!-- raw HTML omitted -->
<p>Meaning that everything except for parameters, local variables and members of structs/unions that starts with an underscore is reserved. So, if you happen to create a variable <code>_mylibrary_debug_flag</code>, you trigger undefined behavior as well. And while we&rsquo;re at it, do not think you can create a type ending in <code>_t</code>: POSIX reserves all identifiers ending in <code>_t</code> for its own use.</p>
<p>In summary, whenever you write C and want to be 100% safe of undefined-behavior-because-of-naming, do not start any identifier with an underscore and do not end any identifier with <code>_t</code>.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>last two weeks</title>
      <link>https://blog.jak-linux.org/2011/04/30/last-two-weeks/</link>
      <pubDate>Sat, 30 Apr 2011 15:41:02 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2011/04/30/last-two-weeks/</guid>
      <description>&lt;p&gt;The last two weeks, two new python-apt releases were made. 0.8.0&lt;del&gt;exp3 did not add much, but 0.8.0&lt;/del&gt;exp4 added some new bindings for our friends at the &lt;a href=&#34;http://www.mancoosi.org/&#34;&gt;mancoosi&lt;/a&gt; project. I also committed several fixes to the APT repository, but did not upload them yet.&lt;/p&gt;
&lt;p&gt;In #debian-devel, some people (including me and others on the Debian side; and sladen, sabdfl for the Ubuntu side) discussed the Ubuntu font license which is considered non-free by Debian, due to extreme naming restrictions in section 2 (unmodified versions must keep the name, slightly modified versions must keep the name and add something). Some consider those restrictions equivalent to invariant sections. After we discusses the font license, we quickly got to discuss Doctor Who and time travel, as those two are obviously connected.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>The last two weeks, two new python-apt releases were made. 0.8.0<del>exp3 did not add much, but 0.8.0</del>exp4 added some new bindings for our friends at the <a href="http://www.mancoosi.org/">mancoosi</a> project. I also committed several fixes to the APT repository, but did not upload them yet.</p>
<p>In #debian-devel, some people (including me and others on the Debian side; and sladen, sabdfl for the Ubuntu side) discussed the Ubuntu font license which is considered non-free by Debian, due to extreme naming restrictions in section 2 (unmodified versions must keep the name, slightly modified versions must keep the name and add something). Some consider those restrictions equivalent to invariant sections. After we discusses the font license, we quickly got to discuss Doctor Who and time travel, as those two are obviously connected.</p>
<p>Some other things happened as well, like closing more bugs, but all in all, the last two weeks where a bit less intensive than the two weeks before them.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>this week: apt 0.8.14 (regex pinning), stable updates, and bug triaging</title>
      <link>https://blog.jak-linux.org/2011/04/15/this-week-apt-0-8-14-regex-pinning-stable-updates-and-bug-triaging/</link>
      <pubDate>Fri, 15 Apr 2011 13:15:02 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2011/04/15/this-week-apt-0-8-14-regex-pinning-stable-updates-and-bug-triaging/</guid>
      <description>&lt;h3 id=&#34;python-apt-080exp2-bug-fix-release&#34;&gt;python-apt 0.8.0~exp2 bug fix release&lt;/h3&gt;
&lt;p&gt;On Tuesday, I uploaded python-apt 0.8.0~exp2 to experimental, fixing about 10 bugs reported in Ubuntu and Debian bug trackers. It should know even convert integers correctly on all architectures, previously we could have passed long via varargs where int was expected.&lt;/p&gt;
&lt;h3 id=&#34;bugs&#34;&gt;Bugs&lt;/h3&gt;
&lt;p&gt;Until Thursday, I went through the bug list in Launchpad and closed/fixed/reassigned/merged about 100 bugs in APT and python-apt.&lt;/p&gt;
&lt;h3 id=&#34;apt--python-apt-updates-for-squeeze&#34;&gt;APT &amp;amp; python-apt updates for squeeze&lt;/h3&gt;
&lt;p&gt;Today, I uploaded updates of apt and python-apt to stable. They include support for xz and parsing multi-arch dependencies, as wanted by ftpmasters.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <h3 id="python-apt-080exp2-bug-fix-release">python-apt 0.8.0~exp2 bug fix release</h3>
<p>On Tuesday, I uploaded python-apt 0.8.0~exp2 to experimental, fixing about 10 bugs reported in Ubuntu and Debian bug trackers. It should know even convert integers correctly on all architectures, previously we could have passed long via varargs where int was expected.</p>
<h3 id="bugs">Bugs</h3>
<p>Until Thursday, I went through the bug list in Launchpad and closed/fixed/reassigned/merged about 100 bugs in APT and python-apt.</p>
<h3 id="apt--python-apt-updates-for-squeeze">APT &amp; python-apt updates for squeeze</h3>
<p>Today, I uploaded updates of apt and python-apt to stable. They include support for xz and parsing multi-arch dependencies, as wanted by ftpmasters.</p>
<h3 id="apt-0814-and-wildcardsregular-expression-pinning">APT 0.8.14 and wildcards/regular expression pinning</h3>
<p>Today, I uploaded apt 0.8.14 to Debian unstable, introducing support for pinning using glob() like Syntax and POSIX extended regular expressions. Let&rsquo;s say we want to pin all packages starting with gnome or kde to 990. The following example does this, using glob-like patterns for gnome, and a regular expression enclosed in / for kde:
<code>Package: gnome* /^kde/ Pin: release a=experimental Pin-Priority: 990</code></p>
<p>This closes 10-year-old <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=121132">Bug#121132</a> in Debian. Have fun with this feature, but please note that it may not be the fastest thing on earth, as it checks every package in the cache on initialization of such queries, which may take a few 10 ms.</p>
<p>Since some time already, it&rsquo;s also possible to use such expressions for the Pin field. Thus users of Ubuntu releases could use the following piece of preferences to pin all packages in archives starting with lucid (e.g. lucid, lucid-updates) to 990:
<code>Package: * Pin: release a=lucid* Pin-Priority: 990</code></p>
<p>Those types of pins do not have the negative performance impact of complex expressions in the Package header, as they are only checked against a smaller set of packages, or if &ldquo;Package: *&rdquo;, simply checked against the package files in the cache.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>this week: dh-autoreconf 3, and APT-related things</title>
      <link>https://blog.jak-linux.org/2011/04/08/this-week-dh-autoreconf-3-and-apt-related-things/</link>
      <pubDate>Fri, 08 Apr 2011 18:15:57 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2011/04/08/this-week-dh-autoreconf-3-and-apt-related-things/</guid>
      <description>&lt;h3 id=&#34;internship--apt-stuff&#34;&gt;Internship / APT stuff&lt;/h3&gt;
&lt;p&gt;This week was a rather busy week. I&amp;rsquo;m currently doing a (unpaid) 1 month internship as part of my education. Thanks to Michael Vogt and his boss at Canonical Ltd, this internship takes place in IRC and is dedicated to Debian and Ubuntu stuff, primarily APT-related things.&lt;/p&gt;
&lt;p&gt;The first two days were spent on multi-arch support in python-apt: On Monday, I released python-apt 0.7.100.3, introducing initial minimal multi-arch support (just enough to not break anymore, but no really new multi-arch-specific API). This release is also the base for the version going to be shipped in Ubuntu natty, which is one of the reasons to keep the changes such minimal. I also fixed an RC bug related to Python 3.2 modules in python-apt, and implemented nocheck build option and disabled test errors on hurd.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <h3 id="internship--apt-stuff">Internship / APT stuff</h3>
<p>This week was a rather busy week. I&rsquo;m currently doing a (unpaid) 1 month internship as part of my education. Thanks to Michael Vogt and his boss at Canonical Ltd, this internship takes place in IRC and is dedicated to Debian and Ubuntu stuff, primarily APT-related things.</p>
<p>The first two days were spent on multi-arch support in python-apt: On Monday, I released python-apt 0.7.100.3, introducing initial minimal multi-arch support (just enough to not break anymore, but no really new multi-arch-specific API). This release is also the base for the version going to be shipped in Ubuntu natty, which is one of the reasons to keep the changes such minimal. I also fixed an RC bug related to Python 3.2 modules in python-apt, and implemented nocheck build option and disabled test errors on hurd.</p>
<p>On Tuesday, I released python-apt 0.8.0~exp1 to experimental. This release now has the old-style non-PEP8 API disabled and also introduces improved multi-arch support, by introducing bindings for APT&rsquo;s GrpIterator class, and supporting indexing the cache by (name, architecture) tuples.</p>
<p>On Wednesday, I noticed a strange bug in APT (via python-apt&rsquo;s test suite) where what the cache considered the native architecture was not the configured one. David Kalnischkies and I debugged the problem, and he found the source of the problem and implemented a fix in his branch of APT. I also introduced multi-arch support for the aptsources module, fixed all Python 3.2 ResourceWarnings in python-apt, and prepared an NMU for python-debian, to adjust it to python-apt&rsquo;s new API. I also took over maintenance  of  software-properties in Debian, and did two uploads there (rebased on the Ubuntu package), both with python-apt 0.8 API support.</p>
<p>On Thursday, I shifted a bit more to the Ubuntu side and fixed several bugs in APT and aptdaemon, resulting in the aptdaemon 0.41+bzr614-0ubuntu2 upload and apt 0.8.13.3ubuntu2. I also fixed software-properties KDE version in Debian, as I broke it the previous day.</p>
<p>Today, on Friday, I fixed one more bug in APT. APT now treats Release files that cannot be verified identical to Release files without signature, that is, they are actually parsed now (no more missing Origin fields) - see <a href="https://bugs.launchpad.net/ubuntu/+source/apt/+bug/704595">LP: #704595</a>.</p>
<h3 id="dh-autoreconf-3">dh-autoreconf 3</h3>
<p>I uploaded dh-autoreconf 3, fixing all bugs in the BTS except for one (if someone knows why autopoint depends on git, please tell me, and I may fix this bug as well). For those who don&rsquo;t know dh-autoreconf, it is a tool to run autoreconf automatically during the package build, so no need for manual cleanup or autoreconf patches.</p>
<p>I now thought about adding the option to automatically patch ltmain.sh to dh-autoreconf. As many know, ltmain.sh does not work correctly with -Wl,&ndash;as-needed. Now, if the libtool maintainer cooperates and provides a patch file in the libtool binary package, dh-autoreconf could automatically apply it during build-time, thus fixing this problem as well.</p>
<h3 id="gnome-3">GNOME 3</h3>
<p>I&rsquo;m now running GNOME 3, or the parts of it we have in Debian.</p>
<h3 id="next-week">Next week</h3>
<p>We&rsquo;ll probably see python-apt 0.8.0~exp2 next week with more improved multi-arch support and other fixes.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>sbuild on a tmpfs</title>
      <link>https://blog.jak-linux.org/2010/12/10/sbuild-on-a-tmpfs/</link>
      <pubDate>Fri, 10 Dec 2010 15:56:59 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/12/10/sbuild-on-a-tmpfs/</guid>
      <description>&lt;p&gt;As some already know, is that I use sbuild to build all my packages in clean chroot environments. For this, I use the &amp;lsquo;aufs&amp;rsquo; &amp;ldquo;mode&amp;rdquo; of schroot, that allows you to setup a chroot with one read-only base directory and one writeable overlay where changes are written to.&lt;/p&gt;
&lt;p&gt;One thing I had problems with was the time required to install build dependencies due to disk I/O. Given that I have 4G RAM in my computer, I decided to use a tmpfs as the writable overlay. For those of you who want to do the same, putting the following in /etc/fstab makes it work:&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>As some already know, is that I use sbuild to build all my packages in clean chroot environments. For this, I use the &lsquo;aufs&rsquo; &ldquo;mode&rdquo; of schroot, that allows you to setup a chroot with one read-only base directory and one writeable overlay where changes are written to.</p>
<p>One thing I had problems with was the time required to install build dependencies due to disk I/O. Given that I have 4G RAM in my computer, I decided to use a tmpfs as the writable overlay. For those of you who want to do the same, putting the following in /etc/fstab makes it work:</p>
<pre><code>overlay                     /var/lib/schroot/union/overlay tmpfs         defaults                    0       0
</code></pre>
<p>Build times are much faster this way because all write I/O is directed to the RAM</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Vettel world champion</title>
      <link>https://blog.jak-linux.org/2010/11/14/vettel-world-champion/</link>
      <pubDate>Sun, 14 Nov 2010 15:53:32 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/11/14/vettel-world-champion/</guid>
      <description>&lt;p&gt;Vettel made it - F1 World Champion 2010.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Vettel made it - F1 World Champion 2010.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>simple code - clang creates 1600x faster executable than gcc</title>
      <link>https://blog.jak-linux.org/2010/10/26/simple-code-clang-creates-1600x-faster-executable-than-gcc/</link>
      <pubDate>Tue, 26 Oct 2010 13:58:38 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/10/26/simple-code-clang-creates-1600x-faster-executable-than-gcc/</guid>
      <description>&lt;p&gt;The following program, compiled with clang 1.1, runs 500 times faster than the gcc4.5-compiled code (in both cases with -O2):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;span style=&amp;quot;color:#008200;&amp;quot;&amp;gt;#include &amp;lt;stdio.h&amp;gt;&amp;lt;/span&amp;gt;

&amp;lt;span style=&amp;quot;color:#008200;&amp;quot;&amp;gt;#define len 1000000000L&amp;lt;/span&amp;gt;

&amp;lt;span style=&amp;quot;color:#830000;&amp;quot;&amp;gt;unsigned long&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:#010181;&amp;quot;&amp;gt;f&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#830000;&amp;quot;&amp;gt;unsigned long&amp;lt;/span&amp;gt; a&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:#830000;&amp;quot;&amp;gt;unsigned long&amp;lt;/span&amp;gt; b&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:#010181;&amp;quot;&amp;gt;__attribute__&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;((&amp;lt;/span&amp;gt;noinline&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;));&amp;lt;/span&amp;gt;

&amp;lt;span style=&amp;quot;color:#830000;&amp;quot;&amp;gt;int&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:#010181;&amp;quot;&amp;gt;main&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;()&amp;lt;/span&amp;gt;
&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;    
    &amp;lt;span style=&amp;quot;color:#010181;&amp;quot;&amp;gt;printf&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#ff0000;&amp;quot;&amp;gt;&amp;quot;%lu&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#ff00ff;&amp;quot;&amp;gt;\n&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#ff0000;&amp;quot;&amp;gt;&amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:#010181;&amp;quot;&amp;gt;f&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#2928ff;&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:#2928ff;&amp;quot;&amp;gt;2&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;*&amp;lt;/span&amp;gt;len&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;));&amp;lt;/span&amp;gt;
    &amp;lt;span style=&amp;quot;color:#000000;font-weight:bold;&amp;quot;&amp;gt;return&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:#2928ff;&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;

&amp;lt;span style=&amp;quot;color:#830000;&amp;quot;&amp;gt;unsigned long&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:#010181;&amp;quot;&amp;gt;f&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#830000;&amp;quot;&amp;gt;unsigned long&amp;lt;/span&amp;gt; a&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:#830000;&amp;quot;&amp;gt;unsigned long&amp;lt;/span&amp;gt; b&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;
&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;{&amp;lt;/span&amp;gt;
    &amp;lt;span style=&amp;quot;color:#830000;&amp;quot;&amp;gt;unsigned long&amp;lt;/span&amp;gt; sum &amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:#2928ff;&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
    &amp;lt;span style=&amp;quot;color:#000000;font-weight:bold;&amp;quot;&amp;gt;for&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;(;&amp;lt;/span&amp;gt; a &amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;&amp;lt;&amp;lt;/span&amp;gt; b&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt; a&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;++)&amp;lt;/span&amp;gt;
        sum &amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;+=&amp;lt;/span&amp;gt; a&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
    &amp;lt;span style=&amp;quot;color:#000000;font-weight:bold;&amp;quot;&amp;gt;return&amp;lt;/span&amp;gt; sum&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;
&amp;lt;span style=&amp;quot;color:#000000;&amp;quot;&amp;gt;}&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, I would be interested to see what&amp;rsquo;s happening here. I took a look at the assembler code both compilers create, but the only thing I found out so far is that gcc&amp;rsquo;s assembly is easier to understand - 50 lines (gcc) vs 134 lines (clang). If someone knows the answer, please tell me.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>The following program, compiled with clang 1.1, runs 500 times faster than the gcc4.5-compiled code (in both cases with -O2):</p>
<pre><code>&lt;span style=&quot;color:#008200;&quot;&gt;#include &lt;stdio.h&gt;&lt;/span&gt;

&lt;span style=&quot;color:#008200;&quot;&gt;#define len 1000000000L&lt;/span&gt;

&lt;span style=&quot;color:#830000;&quot;&gt;unsigned long&lt;/span&gt; &lt;span style=&quot;color:#010181;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#830000;&quot;&gt;unsigned long&lt;/span&gt; a&lt;span style=&quot;color:#000000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color:#830000;&quot;&gt;unsigned long&lt;/span&gt; b&lt;span style=&quot;color:#000000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color:#010181;&quot;&gt;__attribute__&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;((&lt;/span&gt;noinline&lt;span style=&quot;color:#000000;&quot;&gt;));&lt;/span&gt;

&lt;span style=&quot;color:#830000;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color:#010181;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;()&lt;/span&gt;
&lt;span style=&quot;color:#000000;&quot;&gt;{&lt;/span&gt;    
    &lt;span style=&quot;color:#010181;&quot;&gt;printf&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&quot;%lu&lt;/span&gt;&lt;span style=&quot;color:#ff00ff;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color:#010181;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#2928ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color:#2928ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;*&lt;/span&gt;len&lt;span style=&quot;color:#000000;&quot;&gt;));&lt;/span&gt;
    &lt;span style=&quot;color:#000000;font-weight:bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#2928ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color:#000000;&quot;&gt;}&lt;/span&gt;

&lt;span style=&quot;color:#830000;&quot;&gt;unsigned long&lt;/span&gt; &lt;span style=&quot;color:#010181;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#830000;&quot;&gt;unsigned long&lt;/span&gt; a&lt;span style=&quot;color:#000000;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color:#830000;&quot;&gt;unsigned long&lt;/span&gt; b&lt;span style=&quot;color:#000000;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color:#000000;&quot;&gt;{&lt;/span&gt;
    &lt;span style=&quot;color:#830000;&quot;&gt;unsigned long&lt;/span&gt; sum &lt;span style=&quot;color:#000000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#2928ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color:#000000;font-weight:bold;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color:#000000;&quot;&gt;(;&lt;/span&gt; a &lt;span style=&quot;color:#000000;&quot;&gt;&lt;&lt;/span&gt; b&lt;span style=&quot;color:#000000;&quot;&gt;;&lt;/span&gt; a&lt;span style=&quot;color:#000000;&quot;&gt;++)&lt;/span&gt;
        sum &lt;span style=&quot;color:#000000;&quot;&gt;+=&lt;/span&gt; a&lt;span style=&quot;color:#000000;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color:#000000;font-weight:bold;&quot;&gt;return&lt;/span&gt; sum&lt;span style=&quot;color:#000000;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color:#000000;&quot;&gt;}&lt;/span&gt;
</code></pre>
<p>Now, I would be interested to see what&rsquo;s happening here. I took a look at the assembler code both compilers create, but the only thing I found out so far is that gcc&rsquo;s assembly is easier to understand - 50 lines (gcc) vs 134 lines (clang). If someone knows the answer, please tell me.</p>
<p>Also see <a href="http://lwn.net/Articles/411776/">http://lwn.net/Articles/411776/</a> for a C++ version that calls <code>f()</code> via <code>boost::thread</code>.</p>
<p>Update: I also reported a bug at <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46186">http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46186</a>.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>FAIL: Arch Linux switch python executable to Python 3</title>
      <link>https://blog.jak-linux.org/2010/10/22/arch-linux-python-3-and-users/</link>
      <pubDate>Fri, 22 Oct 2010 16:36:38 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/10/22/arch-linux-python-3-and-users/</guid>
      <description>&lt;p&gt;Today, I got an email from an user of one of my Python scripts asking why the script t does not work on Arch Linux anymore. As it turns out, the Arch Linux team decided to &lt;a href=&#34;http://www.archlinux.org/news/python-is-now-python-3/&#34;&gt;switch /usr/bin/python to Python 3.0&lt;/a&gt; and use python2 for Python 2.X versions. By doing this, they decided to make their distribution incompatible to almost any Python script in the world.&lt;/p&gt;
&lt;p&gt;Arch Linux&amp;rsquo;s decision to diverge from the rest of the world that uses python for Python 2.X and python3 for Python 3.X is stupid. And doing this without updating reverse dependencies beforehand and thus breaking packages in their own distribution is insane. In the end this means that if you use Arch Linux, you should consider switching to a distribution that does things the right way: Debian. You can also switch to Ubuntu, that&amp;rsquo;s normally just a bit less right (= faster). But using a distribution that does those crazy things in such an irresponsible way is really insane.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today, I got an email from an user of one of my Python scripts asking why the script t does not work on Arch Linux anymore. As it turns out, the Arch Linux team decided to <a href="http://www.archlinux.org/news/python-is-now-python-3/">switch /usr/bin/python to Python 3.0</a> and use python2 for Python 2.X versions. By doing this, they decided to make their distribution incompatible to almost any Python script in the world.</p>
<p>Arch Linux&rsquo;s decision to diverge from the rest of the world that uses python for Python 2.X and python3 for Python 3.X is stupid. And doing this without updating reverse dependencies beforehand and thus breaking packages in their own distribution is insane. In the end this means that if you use Arch Linux, you should consider switching to a distribution that does things the right way: Debian. You can also switch to Ubuntu, that&rsquo;s normally just a bit less right (= faster). But using a distribution that does those crazy things in such an irresponsible way is really insane.</p>
<p>Really, how can they be so stupid in the Arch world?</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>The Three Levels of Package Management</title>
      <link>https://blog.jak-linux.org/2010/10/20/the-three-levels-of-package-management/</link>
      <pubDate>Wed, 20 Oct 2010 15:01:47 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/10/20/the-three-levels-of-package-management/</guid>
      <description>&lt;p&gt;In today&amp;rsquo;s Linux distributions, there are usually two to three levels of package management. In this blog post, I will explain the three levels of package management.&lt;/p&gt;
&lt;h3 id=&#34;1-local-dpkg-rpm&#34;&gt;1. Local (dpkg, rpm)&lt;/h3&gt;
&lt;p&gt;The first level of package management is the &amp;rsquo;local&amp;rsquo; level. This level consists of package management tools that install and/or remove packages via package archives such as .deb or .rpm files and a database of the local&amp;rsquo;s system state.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>In today&rsquo;s Linux distributions, there are usually two to three levels of package management. In this blog post, I will explain the three levels of package management.</p>
<h3 id="1-local-dpkg-rpm">1. Local (dpkg, rpm)</h3>
<p>The first level of package management is the &rsquo;local&rsquo; level. This level consists of package management tools that install and/or remove packages via package archives such as .deb or .rpm files and a database of the local&rsquo;s system state.</p>
<h3 id="2-connected-apt-yum-smart">2. Connected (APT, YUM, Smart)</h3>
<p>The second level of package management is the &lsquo;connected&rsquo; level. In this level, tools are fetching packages and information about them from (remote) locations known as &lsquo;repositories&rsquo; or &lsquo;sources&rsquo;. A level 2 package manager is usually built on top of a level 1 package manager, for example, APT uses dpkg - but there are also cases where one tool is both, such as opkg.</p>
<h3 id="3-abstract-packagekit-smart">3. Abstract (PackageKit, Smart)</h3>
<p>A level 3 package manager is a tool that supports different level 1 package managers via one generic interface. It may be implemented on top of a level 2 package manager (PackageKit), or may be implemented directly in level 2 (Smart).</p>
<h3 id="conclusion-merge-level-2-and-3">Conclusion: Merge Level 2 and 3</h3>
<p>Most level 2 package managers share a great deal of tasks, such as solving dependency problems. Merging level 2 package management and level 3 package management would enable us to reduce the number of dependency problem solvers and combine our efforts into a few package managers. Such an implementation would need to be written in C and support all common level 1 package managers in order to be successful. As some might have guessed, this is what I plan to do with the project codenamed APT2, although work is not progressing very fast.</p>
<h3 id="ps-back-from-vacation">PS: Back from vacation</h3>
<p>I spent the more than the complete last week in (mostly rainy) Corfu, Greece and am now getting back to my usual development stuff. I have already processed my news &amp; blogs backlog (1000+ messages) and will now start with my email backlog, so don&rsquo;t be angry if the answer to your email takes some time.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Google Public DNS blocks wikileaks.org (Update: No, they don&#39;t)</title>
      <link>https://blog.jak-linux.org/2010/08/30/google-public-dns-blocks-wikileaks-org/</link>
      <pubDate>Mon, 30 Aug 2010 13:12:34 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/08/30/google-public-dns-blocks-wikileaks-org/</guid>
      <description>&lt;p&gt;It seems that Google is blocking wikileaks.org in its &amp;lsquo;Public DNS&amp;rsquo; servers (8.8.8.8 and 8.8.4.4):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div id=&amp;quot;_mcePaste&amp;quot;&amp;gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.7.1-P2 &amp;lt;&amp;lt;&amp;gt;&amp;gt; @8.8.8.8 wikileaks.org
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: SERVFAIL, id: 50227
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;wikileaks.org.			IN	A

;; Query time: 2457 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Fri Aug 27 18:10:43 2010
;; MSG SIZE  rcvd: 31&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Sorry Google, for me doubting you. As it turns out, you did no evil, you were just a bit slower than the others.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>It seems that Google is blocking wikileaks.org in its &lsquo;Public DNS&rsquo; servers (8.8.8.8 and 8.8.4.4):</p>
<pre><code>&lt;div id=&quot;_mcePaste&quot;&gt;; &lt;&lt;&gt;&gt; DiG 9.7.1-P2 &lt;&lt;&gt;&gt; @8.8.8.8 wikileaks.org
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: SERVFAIL, id: 50227
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;wikileaks.org.			IN	A

;; Query time: 2457 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Fri Aug 27 18:10:43 2010
;; MSG SIZE  rcvd: 31&lt;/div&gt;
</code></pre>
<p><strong>Update:</strong> Sorry Google, for me doubting you. As it turns out, you did no evil, you were just a bit slower than the others.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>APT2 is now UPS</title>
      <link>https://blog.jak-linux.org/2010/08/13/apt2-is-now-ups/</link>
      <pubDate>Fri, 13 Aug 2010 20:15:05 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/08/13/apt2-is-now-ups/</guid>
      <description>&lt;p&gt;APT2 is now called UPS (Universal Package System). The name is inspired by &lt;a href=&#34;http://ups.com/&#34;&gt;the company that delivers packages in those brown trucks&lt;/a&gt; and from the Image Packaging System (IPS) of OpenSolaris; and mvo writing ups after I proposed upt (über package tool) in IRC. It&amp;rsquo;s definitely better than my first thought which was &amp;lsquo;moo&amp;rsquo; (and libmoo).&lt;/p&gt;
&lt;p&gt;Update: OK, let&amp;rsquo;s cancel this rename insanity.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>APT2 is now called UPS (Universal Package System). The name is inspired by <a href="http://ups.com/">the company that delivers packages in those brown trucks</a> and from the Image Packaging System (IPS) of OpenSolaris; and mvo writing ups after I proposed upt (über package tool) in IRC. It&rsquo;s definitely better than my first thought which was &lsquo;moo&rsquo; (and libmoo).</p>
<p>Update: OK, let&rsquo;s cancel this rename insanity.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>APT2 - this time in C</title>
      <link>https://blog.jak-linux.org/2010/08/11/apt2-this-time-in-c/</link>
      <pubDate>Wed, 11 Aug 2010 20:22:36 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/08/11/apt2-this-time-in-c/</guid>
      <description>&lt;p&gt;As I wrote a few hours ago on &lt;a href=&#34;mailto:deity@l.d.o&#34;&gt;deity@l.d.o&lt;/a&gt; (see &lt;a href=&#34;http://lists.debian.org/deity/2010/08/msg00057.html&#34;&gt;http://lists.debian.org/deity/2010/08/msg00057.html&lt;/a&gt;), APT2 is back again. The first time, I tried Vala; but this time I wrote it in C (with the help of GLib, but no GObject) and the cache uses GVariant instead of an SQLite database. It&amp;rsquo;s really basic at the moment (no solver, package installation/removal), but it will improve. Read operation should be faster than with APT, although writes are slower (this will be fixed by reusing unchanged parts of the cache).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>As I wrote a few hours ago on <a href="mailto:deity@l.d.o">deity@l.d.o</a> (see <a href="http://lists.debian.org/deity/2010/08/msg00057.html">http://lists.debian.org/deity/2010/08/msg00057.html</a>), APT2 is back again. The first time, I tried Vala; but this time I wrote it in C (with the help of GLib, but no GObject) and the cache uses GVariant instead of an SQLite database. It&rsquo;s really basic at the moment (no solver, package installation/removal), but it will improve. Read operation should be faster than with APT, although writes are slower (this will be fixed by reusing unchanged parts of the cache).</p>
<p>See the announcement for further information.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Nokia/Intel/Google/Canonical - openness and professionality in MeeGo, Android, Ubuntu</title>
      <link>https://blog.jak-linux.org/2010/07/09/nokiaintelgooglecanonical-openness-and-professionality-in-meego-android-ubuntu/</link>
      <pubDate>Fri, 09 Jul 2010 12:21:00 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/07/09/nokiaintelgooglecanonical-openness-and-professionality-in-meego-android-ubuntu/</guid>
      <description>&lt;p&gt;MeeGo (Nokia/Intel): Openness does not seem to be very important for Nokia and Intel. They develop their stuff behind closed doors and then do a large code drop (once dropped, stuff gets developed in the open). In terms of professionality, it does not look much better: If you look at the meego-dev mailing list, you feel like you are in some kind of a kindergarten for open source developers - Things like HTML emails and top-posting appear to be completely normal for them, they don&amp;rsquo;t even follow the basic rules for emails and they also appear to ignore any advice on this topic. Oh, and writing a platform in GTK+ while pushing Qt as the supported toolset is not a good idea.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>MeeGo (Nokia/Intel): Openness does not seem to be very important for Nokia and Intel. They develop their stuff behind closed doors and then do a large code drop (once dropped, stuff gets developed in the open). In terms of professionality, it does not look much better: If you look at the meego-dev mailing list, you feel like you are in some kind of a kindergarten for open source developers - Things like HTML emails and top-posting appear to be completely normal for them, they don&rsquo;t even follow the basic rules for emails and they also appear to ignore any advice on this topic. Oh, and writing a platform in GTK+ while pushing Qt as the supported toolset is not a good idea.</p>
<p>Android (Google): The situation with Android appears to be even worse. Google keeps an internal development tree and the only time the public sees changes is when a new release is coming and Google does a new code drop. Such a behavior is not acceptable.</p>
<p>Ubuntu (Canonical): Canonical does an outstanding job on openness. Canonical employees develop their software completely in the open, and there are no big code drops. They basically have no competitive advantage and allow you to use their work for your own project before they use it themselves. Canonical employees basically behave like normal free software developers doing stuff in his free time, the only exception being that they are paid for it. Most Canonical employees also know how to behave on mailing lists and do not post HTML emails or do top-posting. There are of course also other people: The design process of the Ubuntu font on the other hand is a disaster, with the font being created using proprietary software running on Windows; for a free software company, that&rsquo;s not acceptable (such persons should probably not be hired at all). Furthermore, the quality of Ubuntu packages is often bad when compared to the quality of a Debian package (especially in terms of API documentation of Canonical-created software); a result of vastly different development cycles and different priorities.</p>
<p>On a scale from 0 to 15 (15 being the best), Nokia/Intel receive 5 points (&ldquo;D&rdquo; in U.S. grades), Google receives 3 points (&ldquo;F&rdquo; in U.S. grades), and Canonical receives 12 points (&ldquo;B&rdquo; in U.S. grades). Please note that those grades only apply for the named projects, the companies may behave better or worse in other projects.</p>
<p>Final tips for the companies:</p>
<pre><code>  * Nokia/Intel: Teach your employees how to behave in email discussions.
  * Nokia/Intel/Google: Don't do big code drops, develop in the open. If someone else can create something awesome using your work before you can, you are on the right way. Competitive Advantage must not exist.
  * Canonical: Fire those who used Windows to create the Ubuntu font and restart using free tools.
  * All: Document your code.
</code></pre>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Build systems</title>
      <link>https://blog.jak-linux.org/2010/07/09/build-systems/</link>
      <pubDate>Fri, 09 Jul 2010 11:22:36 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/07/09/build-systems/</guid>
      <description>&lt;p&gt;In the past weeks, I was looking at several build systems. As it turned out, there is not a single sane generic build system out there.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Autotools&lt;/strong&gt;: Autotools are ugly, slow, and require an immense amount of code copies in the source tree.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;WAF&lt;/strong&gt;: WAF is not as ugly as autools and it&amp;rsquo;s faster and does not generate Makefiles or stuff like this. But it has serious issues: It requires one to copy it to the source tarball, has no stable API, and requires Python for building. Furthermore, support for unit testing is broken: It runs the unit tests, but does not abort the build process if the tests fail and does not display why the tests fail.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>In the past weeks, I was looking at several build systems. As it turned out, there is not a single sane generic build system out there.</p>
<p><strong>Autotools</strong>: Autotools are ugly, slow, and require an immense amount of code copies in the source tree.</p>
<p><strong>WAF</strong>: WAF is not as ugly as autools and it&rsquo;s faster and does not generate Makefiles or stuff like this. But it has serious issues: It requires one to copy it to the source tarball, has no stable API, and requires Python for building. Furthermore, support for unit testing is broken: It runs the unit tests, but does not abort the build process if the tests fail and does not display why the tests fail.</p>
<p><strong>CMake</strong>: The syntax is ugly, it generates Makefiles, and support for pkg-config seems to be very very basic.</p>
<p>So how should a build system look like?</p>
<pre><code>  * It should be installed in the system and not require code copies in the source tree (and thus no pre-build actions)
  * It should not generate Makefiles, but build the project itself.
  * It should not require more than a standard C library.
  * It should support pkg-config out of the box.
  * It should support SONAMEs for libraries.
  * It should detect dependencies on headers automatically.
  * It should support unit testing and abort if the tests fail.
  * It should not require developers to specify how to do things, only what to do.
</code></pre>
<p>So, why is there no sane build system?</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Review: Lenovo ThinkPad Edge 15</title>
      <link>https://blog.jak-linux.org/2010/07/05/review-lenovo-thinkpad-edge-15/</link>
      <pubDate>Mon, 05 Jul 2010 14:27:52 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/07/05/review-lenovo-thinkpad-edge-15/</guid>
      <description>&lt;p&gt;Wednesday, after some weeks with a flickering screen (or more precisely, something is causing GTK+ to redraw and the kernel to print ^@ in the terminal when you touch the screen, see &lt;a href=&#34;http://jak-linux.org/tmp/20100628_002.mp4&#34;&gt;http://jak-linux.org/tmp/20100628_002.mp4&lt;/a&gt;) in my 3 years old HP Compaq 6720s (which seems to be a software-hardware combination problem, at least it works in Ubuntu); I decided to buy a new laptop. It took me a few minutes to find the Lenovo ThinkPad Edge 15 NVL7VGE; which I ordered at &lt;a href=&#34;http://www.notebooksbilliger.de/&#34;&gt;notebooksbilliger.de&lt;/a&gt; at around 14:30 CEST using Express. On Thursday morning at 6:40 CEST, the device arrived.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Wednesday, after some weeks with a flickering screen (or more precisely, something is causing GTK+ to redraw and the kernel to print ^@ in the terminal when you touch the screen, see <a href="http://jak-linux.org/tmp/20100628_002.mp4">http://jak-linux.org/tmp/20100628_002.mp4</a>) in my 3 years old HP Compaq 6720s (which seems to be a software-hardware combination problem, at least it works in Ubuntu); I decided to buy a new laptop. It took me a few minutes to find the Lenovo ThinkPad Edge 15 NVL7VGE; which I ordered at <a href="http://www.notebooksbilliger.de/">notebooksbilliger.de</a> at around 14:30 CEST using Express. On Thursday morning at 6:40 CEST, the device arrived.</p>
<p><a href="/images/2010-07-05-review-lenovo-thinkpad-edge-15/20100702_006.jpg"><img src="/images/2010-07-05-review-lenovo-thinkpad-edge-15/20100702_006.jpg?w=300" alt="">
</a></p>
<p>The laptop features an Intel Core i5 430 M processor with integrated graphics, 4 GiB of RAM, 320 GB hard disk storage, matte screen, and of course a TrackPoint. The machine comes pre-installed with Windows 7 Professional which is not very nice (and Lenovo does not take Windows licenses back). I booted Ubuntu 10.04 from an USB disk which worked a few times, but not always, so I upgraded the BIOS to make USB booting reliable (as Lenovo published multiple BIOS updates already, one fixing this USB booting issue).</p>
<p>The first step was booting Ubuntu 10.04 from an USB hard disk to check the Linux support. Using Ubuntu, everything worked out of the box, including stuff like HDMI audio support or output switching. An exception may be the DVD drive, which only works if you set the SATA mode to compatibility. Non-DVD media also works in AHCI mode, but only if you start with a disc inserted in the drive. Playing DVDs requires setting a region code using setregion(8) [otherwise they do not work at all] and SATA compatibility mode [otherwise they only work partially].</p>
<p>Another issue is the HDMI output, as the TV is not correctly detected and some parts at the top and the bottom of the image are missing (that is, the GNOME panels) (but that happens with different screens and ATI cards as well). Oh, and closing the lid with a screen attached and the internal screen disabled works only as long as you do not open it again, because that causes the GPU to stop.</p>
<p>On the input side, we have one keyboard, one TrackPoint, and a touch pad. All of them work out of the box, but they have a few problems on the hardware side: The cursor keys on the keyboard are incredibly small and the touchpad is very large. The keyboard is different from the one in the HP Compaq: First of all, there is space between the keys (like Apple keyboards); and secondly, you need to apply more pressure in order to use the keys.</p>
<p><a href="/images/2010-07-05-review-lenovo-thinkpad-edge-15/20100702_007b.jpg"><img src="/images/2010-07-05-review-lenovo-thinkpad-edge-15/20100702_007b.jpg?w=300" alt="">
</a></p>
<p>The device feels more solid than the HP Compaq 6720s, especially touching the screen does not change the colors on the screen. I don&rsquo;t know how long the keyboard will last, but I hope that I will still have symbols on them in 5 months (which was not the case for the HP Compaq 6720s keyboard).</p>
<p>Power consumption is another interesting point. When the device is idle and the screen is disabled, the device seems to consume about 10W. With screen enabled, consumption varies between 13W (idle) - 35W (building source code); if the values received via ACPI are correct. The device ships with a 48 Wh battery which after some time was displayed as 53 Wh in gnome-power-statistics (only the &lsquo;when loaded&rsquo; state, capacity is displayed as 47.5Wh). According to Lenovo, the laptop lasts 4.5 hours on battery, meaning consumption of 47.5 Wh / 4.5 h = 10.5 Wh which is a bit overly optimistic if you want to work on the device.</p>
<p>After checking everything, I took over my Debian sid installation from my old laptop (which I installed in 2008). It runs happely now, although I still need to get accustomed to the new keyboard and the large touch pad.</p>
<p>All in all, the price of 765€ I paid for the device seems to be OK. Now I only need to remove the Windows 7 sticker and hope that the device lasts long enough until I want to buy a new one (probably 2013, if the aliens don&rsquo;t invade us 2012).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>0x14</title>
      <link>https://blog.jak-linux.org/2010/05/30/0x14/</link>
      <pubDate>Sun, 30 May 2010 11:00:50 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/05/30/0x14/</guid>
      <description>&lt;p&gt;So, yesterday was my 0x14 (20th) birthday and Germany won the Eurovision Song Contest 2010. Next up is Formula One in Turkey and Sebastian Vettel starting from position 3, hopefully he manages to overtake Hamilton and Webber and win this race. Let&amp;rsquo;s see&amp;hellip;&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>So, yesterday was my 0x14 (20th) birthday and Germany won the Eurovision Song Contest 2010. Next up is Formula One in Turkey and Sebastian Vettel starting from position 3, hopefully he manages to overtake Hamilton and Webber and win this race. Let&rsquo;s see&hellip;</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>GNOME Icon Theme 2.30 looks really ugly</title>
      <link>https://blog.jak-linux.org/2010/04/20/gnome-icon-theme-2-30-looks-really-ugly/</link>
      <pubDate>Tue, 20 Apr 2010 16:13:44 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/04/20/gnome-icon-theme-2-30-looks-really-ugly/</guid>
      <description>&lt;p&gt;The 2.30 version of gnome-icon-theme is really one of the worst icon themes I&amp;rsquo;ve ever seen in the last years. First of all, it does not fit into the system due to the colors chosen. I was always satisfied with the GNOME icon theme, but with the 2.30 release I can&amp;rsquo;t use it anymore since it makes my system look like a piece of sh**. Secondly, it just does not fit with the tango icon theme. I&amp;rsquo;m currently using the tango icon theme on my laptop, and after installing g-i-t 2.30, some logos suddenly started to turn black and they just did not fit anymore.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>The 2.30 version of gnome-icon-theme is really one of the worst icon themes I&rsquo;ve ever seen in the last years. First of all, it does not fit into the system due to the colors chosen. I was always satisfied with the GNOME icon theme, but with the 2.30 release I can&rsquo;t use it anymore since it makes my system look like a piece of sh**. Secondly, it just does not fit with the tango icon theme. I&rsquo;m currently using the tango icon theme on my laptop, and after installing g-i-t 2.30, some logos suddenly started to turn black and they just did not fit anymore.</p>
<p>For now, I downgraded gnome-icon-theme to 2.28 to have a usable UI again. But once there are new icons in gnome-icon-theme I will be lost. Hopefully someone with a sense for UI design will fix this &ldquo;design hell&rdquo; created by <!-- raw HTML omitted -->the idiots<!-- raw HTML omitted --> those who created this icon theme. We don&rsquo;t need a 90s icon theme.</p>
<p><strong>Update:</strong> Here&rsquo;s one problem, the network icon just does not fit:
<a href="/images/2010-04-20-gnome-icon-theme-2-30-looks-really-ugly/icons.png"><img src="/images/2010-04-20-gnome-icon-theme-2-30-looks-really-ugly/icons.png" alt="">
</a> (not under the same license as the blog, due to legal reasons).</p>
<p><strong>Update 2:</strong> I don&rsquo;t like changes, but after a months or so I will probably accept it. Anyway, Google did even worse things with reordering the icons in Chromium 5. Previously, all actions were on the left (IIRC); now some are on the left, and some in the input box. Anyway, I replaced &ldquo;the idiots&rdquo; with &ldquo;those&rdquo; now, as some people felt this was overly offensive.</p>
<p><strong>Update 3:</strong> I just filed two bugs at gnome.org: <a href="https://bugzilla.gnome.org/show_bug.cgi?id=616324">616324</a> and <a href="https://bugzilla.gnome.org/show_bug.cgi?id=616325">616325</a>. Others will probably follow.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Python 3.1 bug: Objects in modules (m_size=-1) not deallocated</title>
      <link>https://blog.jak-linux.org/2010/04/20/python-3-1-bug/</link>
      <pubDate>Tue, 20 Apr 2010 12:50:39 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/04/20/python-3-1-bug/</guid>
      <description>&lt;p&gt;Last year, in July, I reported an issue to Python&amp;rsquo;s issue tracker. This issue can be seen at &lt;a href=&#34;http://bugs.python.org/issue6483&#34;&gt;http://bugs.python.org/issue6483&lt;/a&gt;. Since then, there has been no action on this bug from the developers.&lt;/p&gt;
&lt;p&gt;The bug describes that every object stored in a module will not be deallocated if the module is deallocated and it&amp;rsquo;s m_size = -1 (which it should be if the module has no state). The problem seems to be that Python copies the dictionary of the module but forgets to decrease the reference count of the copy when the module is deallocated. This bug may have serious impact if objects are stored in the module which write status to a file when they are deallocated, because the deallocation functions are never called.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Last year, in July, I reported an issue to Python&rsquo;s issue tracker. This issue can be seen at <a href="http://bugs.python.org/issue6483">http://bugs.python.org/issue6483</a>. Since then, there has been no action on this bug from the developers.</p>
<p>The bug describes that every object stored in a module will not be deallocated if the module is deallocated and it&rsquo;s m_size = -1 (which it should be if the module has no state). The problem seems to be that Python copies the dictionary of the module but forgets to decrease the reference count of the copy when the module is deallocated. This bug may have serious impact if objects are stored in the module which write status to a file when they are deallocated, because the deallocation functions are never called.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Google Street View in Germany</title>
      <link>https://blog.jak-linux.org/2010/03/02/google-street-view-in-germany/</link>
      <pubDate>Tue, 02 Mar 2010 18:02:39 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/03/02/google-street-view-in-germany/</guid>
      <description>&lt;p&gt;I wonder why the federal minister for consumer protection (hopefully a good enough translation for &amp;ldquo;Verbraucherschutzministerin&amp;rdquo;) Ilse Aigner has concerns about Street View, because those concerns are completely unrelated to protecting the consumer, because the consumer is the one viewing the images in the browser, and not the person being photographed.&lt;/p&gt;
&lt;p&gt;I have no reason to believe that Google Street View is illegal, I see no difference between a photo taken by a company and a photo taken by a single person. If Google Street View were illegal, distribution of every picture taken in the public would have to be considered illegal as well.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I wonder why the federal minister for consumer protection (hopefully a good enough translation for &ldquo;Verbraucherschutzministerin&rdquo;) Ilse Aigner has concerns about Street View, because those concerns are completely unrelated to protecting the consumer, because the consumer is the one viewing the images in the browser, and not the person being photographed.</p>
<p>I have no reason to believe that Google Street View is illegal, I see no difference between a photo taken by a company and a photo taken by a single person. If Google Street View were illegal, distribution of every picture taken in the public would have to be considered illegal as well.</p>
<p>And creating laws limiting the height at which the camera is placed to e.g. 1.8 meters sounds like discriminating against persons who are e.g. 1.85 meters (&ldquo;You&rsquo;re too tall, you&rsquo;re not allowed to take a picture&rdquo;).</p>
<p>More information about this topic can be found on e.g. <a href="http://www.spiegel.de/international/germany/0,1518,676616,00.html">http://www.spiegel.de/international/germany/0,1518,676616,00.html</a>.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Maemo &#43; Moblin = MeeGo = Failure</title>
      <link>https://blog.jak-linux.org/2010/02/15/maemo-moblin-meego-failure/</link>
      <pubDate>Mon, 15 Feb 2010 13:43:04 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/02/15/maemo-moblin-meego-failure/</guid>
      <description>&lt;p&gt;Today, Nokia and Intel announced the merge of Maemo and Moblin into the MeeGo project. This is sad, because it will end the era of the Debian-based mobile operating system Maemo and replace it with a system using RPM and probably some other evil stuff as well. In fact, dpkg &amp;amp; apt-get where two of my main reasons to buy the N900.&lt;/p&gt;
&lt;p&gt;And another question is why yet another name. Moblin was already a well-known name and they shouldn&amp;rsquo;t have changed the name just because they switch the servers and add some Nokia developers.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today, Nokia and Intel announced the merge of Maemo and Moblin into the MeeGo project. This is sad, because it will end the era of the Debian-based mobile operating system Maemo and replace it with a system using RPM and probably some other evil stuff as well. In fact, dpkg &amp; apt-get where two of my main reasons to buy the N900.</p>
<p>And another question is why yet another name. Moblin was already a well-known name and they shouldn&rsquo;t have changed the name just because they switch the servers and add some Nokia developers.</p>
<p>Furthermore, does this all mean that there will be no Maemo 6? What will happen to the Maemo users on the N900, will it be possible for them to use MeeGo?</p>
<p>Maybe this is the time to start a new project, Debian Mobile. Debian Mobile would take the MeeGo experience and apply it to a Debian system. This would probably the best mobile operating system ever, being backed by Debian&rsquo;s large repositories with thousands of software packages.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>N900 standby time</title>
      <link>https://blog.jak-linux.org/2010/02/08/n900-standby-time/</link>
      <pubDate>Mon, 08 Feb 2010 09:05:51 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/02/08/n900-standby-time/</guid>
      <description>&lt;p&gt;It seems that the N900 is able to run for &amp;gt; 3 days in standby, I unplugged it Friday on 7:00, and it lasted until Sunday 23:50. I used it for browsing the web a bit and to listen to music via FM transmitter.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>It seems that the N900 is able to run for &gt; 3 days in standby, I unplugged it Friday on 7:00, and it lasted until Sunday 23:50. I used it for browsing the web a bit and to listen to music via FM transmitter.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Just uninstalled hal</title>
      <link>https://blog.jak-linux.org/2010/02/07/just-uninstalled-hal/</link>
      <pubDate>Sun, 07 Feb 2010 22:15:57 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/02/07/just-uninstalled-hal/</guid>
      <description>&lt;p&gt;I have just uninstalled hal from my laptop running unstable, and everything still seems to work, including suspend &amp;amp; resume.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I have just uninstalled hal from my laptop running unstable, and everything still seems to work, including suspend &amp; resume.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>python-apt 0.7.93 just hit unstable.</title>
      <link>https://blog.jak-linux.org/2010/01/20/python-apt-0-7-93-just-hit-unstable/</link>
      <pubDate>Wed, 20 Jan 2010 16:52:13 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2010/01/20/python-apt-0-7-93-just-hit-unstable/</guid>
      <description>&lt;p&gt;I just uploaded python-apt 0.7.93 to unstable with support for Python 2.6 and Python 3.1, meaning that there is now a single development branch again.&lt;/p&gt;
&lt;p&gt;This uploads brings developers the new API with real classes in apt_pkg (you can now use pydoc to view documentation), C++ bindings for making apt-pkg applications scriptable (although they should be considered experimental), a test suite (although aptsources fails in one test for now) and many new context managers for enhanced Python 3 coding fun. And objects are now freed when their reference count reaches 0. A more complete list of news can be found in the &lt;a href=&#34;http://apt.alioth.debian.org/python-apt-doc/whatsnew/0.7.100.html&#34;&gt;What’s New In python-apt 0.7.100&lt;/a&gt; part of the documentation.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I just uploaded python-apt 0.7.93 to unstable with support for Python 2.6 and Python 3.1, meaning that there is now a single development branch again.</p>
<p>This uploads brings developers the new API with real classes in apt_pkg (you can now use pydoc to view documentation), C++ bindings for making apt-pkg applications scriptable (although they should be considered experimental), a test suite (although aptsources fails in one test for now) and many new context managers for enhanced Python 3 coding fun. And objects are now freed when their reference count reaches 0. A more complete list of news can be found in the <a href="http://apt.alioth.debian.org/python-apt-doc/whatsnew/0.7.100.html">What’s New In python-apt 0.7.100</a> part of the documentation.</p>
<p>For the next releases until 0.7.100 release, the focus is clearly on fixing bugs and improving the documentation. We need more tests of the Python 3 builds, especially in areas dealing with str and unicode stuff.</p>
<p>Have fun, read the <a href="http://apt.alioth.debian.org/python-apt-doc/">documentation</a>, and code.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>New keyboard</title>
      <link>https://blog.jak-linux.org/2009/12/30/new-keyboard/</link>
      <pubDate>Wed, 30 Dec 2009 13:27:43 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/12/30/new-keyboard/</guid>
      <description>&lt;p&gt;My brother and I just replaced the keyboard of my HP Compaq 6720s with a new HP replacement part (a christmas present). The old one had no characters on some keys anymore and it did not look very well. Replacing the keyboard was a matter of removing two screws, and then just &amp;lsquo;clicking&amp;rsquo; the keyboard out. The old keyboard lost a few keys during the process, but this is not really important anymore. Typing now feels a bit different and I have to get used to it during the next days.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>My brother and I just replaced the keyboard of my HP Compaq 6720s with a new HP replacement part (a christmas present). The old one had no characters on some keys anymore and it did not look very well. Replacing the keyboard was a matter of removing two screws, and then just &lsquo;clicking&rsquo; the keyboard out. The old keyboard lost a few keys during the process, but this is not really important anymore. Typing now feels a bit different and I have to get used to it during the next days.</p>
<p>In other news, the defect N900 with QWERTZ keyboard is back to Amazon.de; and I have ordered a QWERTY one on expansys.de yesterday. Let&rsquo;s see when that one arrives.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Nokia N900</title>
      <link>https://blog.jak-linux.org/2009/12/22/nokia-n900/</link>
      <pubDate>Tue, 22 Dec 2009 15:35:11 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/12/22/nokia-n900/</guid>
      <description>&lt;p&gt;Yesterday, an N900 I bought from Amazon Warehouse Deals arrived. The device is great, but I discovered today that the AV output only outputs sound on the right speaker and nothing on the left one. So it seems that I have to send it back and will thus not have a N900 during Christmas.&lt;/p&gt;
&lt;p&gt;Appart from that problem, the device works almost perfectly. The internet browsing experience is faboulus, the camera is good, and the device is fast; the screen is great and the speakers are great as well. The keyboard is easy to type with and you can type fast after a short time. The video player does not seem to like my H.264 files (the OpenMAX decoder fails whereas on my PC ffmpeg is able to play it).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Yesterday, an N900 I bought from Amazon Warehouse Deals arrived. The device is great, but I discovered today that the AV output only outputs sound on the right speaker and nothing on the left one. So it seems that I have to send it back and will thus not have a N900 during Christmas.</p>
<p>Appart from that problem, the device works almost perfectly. The internet browsing experience is faboulus, the camera is good, and the device is fast; the screen is great and the speakers are great as well. The keyboard is easy to type with and you can type fast after a short time. The video player does not seem to like my H.264 files (the OpenMAX decoder fails whereas on my PC ffmpeg is able to play it).</p>
<p>That&rsquo;s all for now, I&rsquo;ll write again when I have a N900 with working AV output.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>The previous post</title>
      <link>https://blog.jak-linux.org/2009/12/15/the-previous-post/</link>
      <pubDate>Tue, 15 Dec 2009 19:44:53 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/12/15/the-previous-post/</guid>
      <description>&lt;p&gt;Well, it seems that several news sites (&lt;a href=&#34;http://www.golem.de/0912/71903.html&#34;&gt;golem.de&lt;/a&gt;, &lt;a href=&#34;http://www.pro-linux.de/news/2009/15080.html&#34;&gt;pro-linux.de&lt;/a&gt;, &lt;a href=&#34;http://www.linux-magazin.de/NEWS/Apt2-beschleunigt-Paketsuche&#34;&gt;linux-magazin.de&lt;/a&gt;, &lt;a href=&#34;http://www.linux-magazine.com/Online/News/APT2-to-Accelerate-Debian-Package-Installation&#34;&gt;linux-magazine.com&lt;/a&gt;, &lt;a href=&#34;http://www.ubuntu-user.de/Online/News/Apt2-soll-die-Installation-von-Debian-Paketen-beschleunigen&#34;&gt;ubuntu-user.de&lt;/a&gt; [the last ones all from the same publishing house]), especially German ones have picked up the last blog post with same false impressions.&lt;/p&gt;
&lt;p&gt;First, they stated that I am planning an APT2 release for Christmas.  They took the statement&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;as a proof for this. But in the context of this paragraph, &amp;lsquo;publish&amp;rsquo; was not meant in the term of publishing a release, but in the term of publishing the code (of the internal branch) in the public repository. The code is public now and lives in a &amp;rsquo;temp&amp;rsquo; branch and will be reworked there for inclusion in the master branch.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Well, it seems that several news sites (<a href="http://www.golem.de/0912/71903.html">golem.de</a>, <a href="http://www.pro-linux.de/news/2009/15080.html">pro-linux.de</a>, <a href="http://www.linux-magazin.de/NEWS/Apt2-beschleunigt-Paketsuche">linux-magazin.de</a>, <a href="http://www.linux-magazine.com/Online/News/APT2-to-Accelerate-Debian-Package-Installation">linux-magazine.com</a>, <a href="http://www.ubuntu-user.de/Online/News/Apt2-soll-die-Installation-von-Debian-Paketen-beschleunigen">ubuntu-user.de</a> [the last ones all from the same publishing house]), especially German ones have picked up the last blog post with same false impressions.</p>
<p>First, they stated that I am planning an APT2 release for Christmas.  They took the statement</p>
<!-- raw HTML omitted -->
<p>as a proof for this. But in the context of this paragraph, &lsquo;publish&rsquo; was not meant in the term of publishing a release, but in the term of publishing the code (of the internal branch) in the public repository. The code is public now and lives in a &rsquo;temp&rsquo; branch and will be reworked there for inclusion in the master branch.</p>
<p>Secondly, those news sites called me an Ubuntu developer. While I do contribute to Ubuntu, and am an Ubuntu Member, I am NOT an Ubuntu Developer, as I am NOT a member of the relevant ubuntu-dev team at launchpad.</p>
<p>Thirdly, those who stated that speed is a goal (mostly pro-linux, at least from my understanding): It is not, at least not now. It is just a coincidence caused by using a relational database. Furthermore, the test was not really fair, since the other package managers both provide more information than capt; information which has yet to be made accessible in APT2. It was just an initial conclusion that SQLite is quite fast.</p>
<p>Please note that APT2 is a free time project in development, and the programming language used is still in development as well; as well as some other reverse dependencies. I should also state that neither Debian nor Ubuntu have any plans to drop apt at the moment; and APT is still actively developed.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>APT2 progress report for the 1st half of December</title>
      <link>https://blog.jak-linux.org/2009/12/13/apt2-progress-report-for-the-1st-half-of-december/</link>
      <pubDate>Sun, 13 Dec 2009 20:07:09 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/12/13/apt2-progress-report-for-the-1st-half-of-december/</guid>
      <description>&lt;p&gt;This week was successful. I have pushed some changes from November to the repository which change the license to LGPL-2.1+ (which makes bi-directional sharing of code with other projects easier, since most Vala code is under the same license) and implement HTTP using libsoup2.4 directly, instead of using GIO and GVFS for this. I also added a parser for the sources.list format which uses regular expressions to parse the file and is relatively fast. The code needs a current checkout of Vala&amp;rsquo;s git master to work correctly; as released versions had a bug which I noticed today and Jürg Billeter fixed in Vala 25 minutes later; thank you Jürg.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>This week was successful. I have pushed some changes from November to the repository which change the license to LGPL-2.1+ (which makes bi-directional sharing of code with other projects easier, since most Vala code is under the same license) and implement HTTP using libsoup2.4 directly, instead of using GIO and GVFS for this. I also added a parser for the sources.list format which uses regular expressions to parse the file and is relatively fast. The code needs a current checkout of Vala&rsquo;s git master to work correctly; as released versions had a bug which I noticed today and Jürg Billeter fixed in Vala 25 minutes later; thank you Jürg.</p>
<p>While nothing else happened in the public repository, the internal branch has seen a lot of new code; including SQLite 3 caches; Acquire text progress handling; and capt; the command-line advanced package tool. Most of the code will need to be reworked before it will be published, but I hope to have this completed until Christmas. It will also depend on Vala 0.7.9 or newer, which is yet to be released.</p>
<p>The decision to use SQLite 3 as a backend means that we won&rsquo;t see the size limitations APT has and that development can be simplified by using SQL queries for filtering requests. It also means that APT2 will be very fast in most actions, like searching; which currently happens in 0.140 seconds (unstable,experimental and more repositories enabled), whereas aptitude takes 1.101 seconds, cupt (which has no on-disk cache) 1.292 seconds, and apt-cache 0.475 seconds. Searching is performed by one SQL query. I also want to thank Jens Georg <a href="mailto:mail@jensge.org">mail@jensge.org</a>, who wrote Rygel&rsquo;s Database class which is also used with minor modifications (like defaulting to in-memory journals) in APT2 as well. Rygel.Database is a small wrapper around sqlite3 which makes it easier to program for Vala programmers.</p>
<p>The command-line application &lsquo;capt&rsquo; provides a shell based on readline with history (and later on command completion) as well as direct usage like &lsquo;capt config dump&rsquo; or &lsquo;capt search python-apt&rsquo;. Just as with Eugene&rsquo;s cupt, &lsquo;capt&rsquo; will be the only program in the core APT2 distribution and provide the same functionality currently provided by apt-get, apt-config and friends. The name is not perfect and can be easily confused with &lsquo;cupt&rsquo;, but it was the closest option for now; considering that the name &lsquo;apt&rsquo; is already used by Java (for its &ldquo;Annotation Processing Tool&rdquo;).</p>
<p>That&rsquo;s all for now, I&rsquo;ll tell you once all those features have passed my QA, and there is really something usable in the repository. In the meanwhile, you can discuss external dependency solvers, database layouts and other stuff in their threads on <a href="mailto:deity@lists.debian.org">deity@lists.debian.org</a>.</p>
<p>And a &lsquo;screenshot&rsquo; from capt:</p>
<pre><code>jak@hp:~/Desktop/APT2:temp$ capt
apt$ help
APT2 0.0.20091213 command-line frontend

Commands:
  config dump               Dump the configuration
  config get OPTION         Get the given option
  config set OPTION VALUE   Set the given option
  search EXPRESSION         Search for the given expression
  show PACKAGE              Show all versions of the given package
  sources list              Print a list of all sources
  version                   Print the version of APT2
apt$ search python-apt
build-depends-python-apt - Dummy package to fulfill package dependencies
python-apt - Python interface to libapt-pkg
python-apt-dbg - Python interface to libapt-pkg (debug extension)
python-apt-dev - Python interface to libapt-pkg (development files)
python-aptdaemon - Python module for the server and client of aptdaemon
python-aptdaemon-gtk - Python GTK+ widgets to run an aptdaemon client
apt$ 
</code></pre>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>MySQL</title>
      <link>https://blog.jak-linux.org/2009/12/13/mysql/</link>
      <pubDate>Sun, 13 Dec 2009 12:51:02 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/12/13/mysql/</guid>
      <description>&lt;p&gt;If Oracle owned MySQL, it would not make a big difference with regards to competition on the database market. Oracle would then own 2 relational databases. But there is also the BSD-licensed PostgreSQL, the world&amp;rsquo;s most advanced open source database with several enhanced products from companies.&lt;/p&gt;
&lt;p&gt;If Oracle closed MySQL, the community would step in. I truly believe that the free software community is strong enough to support MySQL. There already is &lt;a href=&#34;http://askmonty.org/&#34;&gt;MariaDB&lt;/a&gt; and I believe that this project could serve as the base in case Oracle closes MySQL or stops MySQL completely. The community was strong enough to build complete operating systems and maintain them, so it should not be that hard to support one database.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>If Oracle owned MySQL, it would not make a big difference with regards to competition on the database market. Oracle would then own 2 relational databases. But there is also the BSD-licensed PostgreSQL, the world&rsquo;s most advanced open source database with several enhanced products from companies.</p>
<p>If Oracle closed MySQL, the community would step in. I truly believe that the free software community is strong enough to support MySQL. There already is <a href="http://askmonty.org/">MariaDB</a> and I believe that this project could serve as the base in case Oracle closes MySQL or stops MySQL completely. The community was strong enough to build complete operating systems and maintain them, so it should not be that hard to support one database.</p>
<p>All in all, I don&rsquo;t see how Oracle buying Sun (and thus MySQL) could negatively influence competition in the database market, and I would therefore recommend the EC to approve the Oracle-Sun deal as it, without imposing any conditions on Oracle.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Ubuntu Software Center coming to Debian</title>
      <link>https://blog.jak-linux.org/2009/11/30/ubuntu-software-center-coming-to-debian/</link>
      <pubDate>Mon, 30 Nov 2009 18:57:37 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/11/30/ubuntu-software-center-coming-to-debian/</guid>
      <description>&lt;p&gt;I just uploaded aptdaemon 0.11-1 and software-center 1.1debian1 to Debian unstable. They are currently waiting in NEW, and will hopefully pass it in a short time. I plan to replace gnome-app-install with software-center for Squeeze, but you can currently have both installed.&lt;/p&gt;
&lt;p&gt;Ubuntu Software Center (or just &amp;lsquo;Software Center&amp;rsquo;) is a new graphical user interface for installing and removing applications; replacing gnome-app-install. Under the hood, it uses aptdaemon which exposes an interface to APT via D-Bus; i.e. something in the direction of PackageKit. At a later stage, the Software Center shall replace Synaptic, Update Manager and various other programs related to package management.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I just uploaded aptdaemon 0.11-1 and software-center 1.1debian1 to Debian unstable. They are currently waiting in NEW, and will hopefully pass it in a short time. I plan to replace gnome-app-install with software-center for Squeeze, but you can currently have both installed.</p>
<p>Ubuntu Software Center (or just &lsquo;Software Center&rsquo;) is a new graphical user interface for installing and removing applications; replacing gnome-app-install. Under the hood, it uses aptdaemon which exposes an interface to APT via D-Bus; i.e. something in the direction of PackageKit. At a later stage, the Software Center shall replace Synaptic, Update Manager and various other programs related to package management.</p>
<p>The aptdaemon package is completely compatible to the Ubuntu one, and could thus be synced directly to Ubuntu without any change (if Ubuntu supports &ldquo;3.0 (quilt)&rdquo; source packages now, I have not looked into this). The software-center package is based on the latest Ubuntu lucid package; and contains some generalization (e.g. replacing &lsquo;Ubuntu Software Center&rsquo; with &lsquo;Software Center&rsquo;) at some more places. It still needs some work in the documentation and some parts of the program will have to be adjusted for Debian aswell. We also do not have a debianized icon yet; this will be worked on later.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Back to the &#39;90s - Bye PC, welcome back thin clients</title>
      <link>https://blog.jak-linux.org/2009/11/20/back-to-the-90s-bye-pc-welcome-back-thin-clients/</link>
      <pubDate>Fri, 20 Nov 2009 16:56:54 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/11/20/back-to-the-90s-bye-pc-welcome-back-thin-clients/</guid>
      <description>&lt;p&gt;In the &amp;rsquo;90s, you had a large machine and several thin clients accessing it by using X11 via network. In 2010, you will have large datacenters providing applications to and storing the data of millions of users. As you might have guessed, I am talking about Google Chrome OS.&lt;/p&gt;
&lt;p&gt;It seems that the PC era is slowly coming to an end, with devices being increasingly connected &amp;rsquo;to the cloud&amp;rsquo; and people being always online; and storing their data on Google&amp;rsquo;s servers. We do emails online using Google Mail, we do navigation online using Google Maps, we edit and view our documents using Google Docs, our newspaper is Google News; and when we want entertainment we open the browser and type youtube.com into the URL bar. Even if we were formatting the hard disk and reinstalling the system, most people wouldn&amp;rsquo;t even notice; because all there data is stored online.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>In the &rsquo;90s, you had a large machine and several thin clients accessing it by using X11 via network. In 2010, you will have large datacenters providing applications to and storing the data of millions of users. As you might have guessed, I am talking about Google Chrome OS.</p>
<p>It seems that the PC era is slowly coming to an end, with devices being increasingly connected &rsquo;to the cloud&rsquo; and people being always online; and storing their data on Google&rsquo;s servers. We do emails online using Google Mail, we do navigation online using Google Maps, we edit and view our documents using Google Docs, our newspaper is Google News; and when we want entertainment we open the browser and type youtube.com into the URL bar. Even if we were formatting the hard disk and reinstalling the system, most people wouldn&rsquo;t even notice; because all there data is stored online.</p>
<p>There is also the question of freedom. Free software is not very widespread in the SaaS world. You also lose the control over your data. But RMS can <a href="http://www.guardian.co.uk/technology/2008/sep/29/cloud.computing.richard.stallman">tell you more about it</a>.</p>
<p>So it seems that 2010, Google is the new mainframe and netbooks and smartphones are the new terminals. Whether this is good or not cannot be said. The question you have to ask yourself is whether you can trust Google to keep your data secure or not. I trust them enough to host all of my emails, the RSS feeds I read, my searches.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>My First upload with new source format</title>
      <link>https://blog.jak-linux.org/2009/11/03/my-first-upload-with-new-source-format/</link>
      <pubDate>Tue, 03 Nov 2009 17:51:34 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/11/03/my-first-upload-with-new-source-format/</guid>
      <description>&lt;p&gt;Yesterday, I uploaded command-not-found 0.2.38-1 (based on version 0.2.38ubuntu4) to Debian unstable, using the &amp;ldquo;3.0 (quilt)&amp;rdquo; source format. All steps worked perfectly, including stuff like cowbuilder, lintian, debdiff, dput and the processing on ftp-master. Next steps are reverting my machine from Ubuntu 9.10 to my Debian unstable system and uploading new versions of gnome-main-menu, python-apt (0.7.93, not finished yet) and some other packages.&lt;/p&gt;
&lt;p&gt;In other news, the development of Ubuntu 10.04 Lucid Lynx just started. For the first time in Ubuntu&amp;rsquo;s history, the development will be based on the testing tree of Debian and not on the unstable tree. This is done in order to increase the stability of the distribution, as this release is going to be a long term supported release. Ubuntu will freeze in February, one month before the freeze of Debian Squeeze. This should give us enough room to collaborate, especially on bugfixes. This also means that I will freeze my packages in February, so they will have the same version in Squeeze and Lucid (applying the earliest freeze to both distributions; exceptions where needed).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Yesterday, I uploaded command-not-found 0.2.38-1 (based on version 0.2.38ubuntu4) to Debian unstable, using the &ldquo;3.0 (quilt)&rdquo; source format. All steps worked perfectly, including stuff like cowbuilder, lintian, debdiff, dput and the processing on ftp-master. Next steps are reverting my machine from Ubuntu 9.10 to my Debian unstable system and uploading new versions of gnome-main-menu, python-apt (0.7.93, not finished yet) and some other packages.</p>
<p>In other news, the development of Ubuntu 10.04 Lucid Lynx just started. For the first time in Ubuntu&rsquo;s history, the development will be based on the testing tree of Debian and not on the unstable tree. This is done in order to increase the stability of the distribution, as this release is going to be a long term supported release. Ubuntu will freeze in February, one month before the freeze of Debian Squeeze. This should give us enough room to collaborate, especially on bugfixes. This also means that I will freeze my packages in February, so they will have the same version in Squeeze and Lucid (applying the earliest freeze to both distributions; exceptions where needed).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>I&#39;m back</title>
      <link>https://blog.jak-linux.org/2009/10/25/im-back/</link>
      <pubDate>Sun, 25 Oct 2009 22:28:35 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/10/25/im-back/</guid>
      <description>&lt;p&gt;I returned to Germany from my vacation in Greece yesterday, and I just installed my new hard drive into my laptop. The old Hitachi hard drive had some bad sectors after a very long usage time (compared to my other disks) - we&amp;rsquo;ll see how the new Samsung SpinPoint M7 will work. Another side benefit is the upgrade from 120GB to 500GB which means I don&amp;rsquo;t have to delete files during the next months. It is also much faster (hdparm -t was 80MB/s, 2 times faster than the old one).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I returned to Germany from my vacation in Greece yesterday, and I just installed my new hard drive into my laptop. The old Hitachi hard drive had some bad sectors after a very long usage time (compared to my other disks) - we&rsquo;ll see how the new Samsung SpinPoint M7 will work. Another side benefit is the upgrade from 120GB to 500GB which means I don&rsquo;t have to delete files during the next months. It is also much faster (hdparm -t was 80MB/s, 2 times faster than the old one).</p>
<p>I&rsquo;m currently running the release candidate of Ubuntu 9.10 &ldquo;Karmic Koala&rdquo; on this system, but I expect to return to my full Debian unstable developer environment during the next week(s). Karmic seems to be pretty stable already, but I have experienced problems with PulseAudio and my PCM control getting set to +13dB which is horrible.</p>
<p>I will probably also pre-order a Nokia N900 soon, which will be my largest investment this year - but I really need a new mobile phone, camera and music player. And not to forget the ability to develop software for it, and testing my software on those less powerful devices (compared to my laptop).</p>
<p>All in all, I&rsquo;m back and soon ready to hack again.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>upgrade failures</title>
      <link>https://blog.jak-linux.org/2009/09/29/upgrade-failures/</link>
      <pubDate>Tue, 29 Sep 2009 14:45:17 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/09/29/upgrade-failures/</guid>
      <description>&lt;p&gt;Today I wanted to upgrade my &amp;ldquo;sid&amp;rdquo; system again (like I do 1-3 times per day, especially when I have nothing else to do). First of all, I was hit by a bug in APT &amp;ldquo;Could not perform immediate configuration (2) on perl&amp;rdquo;. I worked around it by running the latest git commit of cupt, which then started to upgrade my system. At some stage however, after upgrading parts of perl it seems, the progress stopped and perl complained that it could not find English.pm anymore. I tried to manually install the perl packages using dpkg -i, but this did not work. Then I just thought I should just try to unpack it and run &lt;code&gt;dpkg -x &amp;lt;package&amp;gt; /&lt;/code&gt; on the perl packages. Now dpkg -i was working again and I could run dpkg -i on the packages again and continue my upgrade using apt-get.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today I wanted to upgrade my &ldquo;sid&rdquo; system again (like I do 1-3 times per day, especially when I have nothing else to do). First of all, I was hit by a bug in APT &ldquo;Could not perform immediate configuration (2) on perl&rdquo;. I worked around it by running the latest git commit of cupt, which then started to upgrade my system. At some stage however, after upgrading parts of perl it seems, the progress stopped and perl complained that it could not find English.pm anymore. I tried to manually install the perl packages using dpkg -i, but this did not work. Then I just thought I should just try to unpack it and run <code>dpkg -x &lt;package&gt; /</code> on the perl packages. Now dpkg -i was working again and I could run dpkg -i on the packages again and continue my upgrade using apt-get.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Results of the APT2 config parser testing</title>
      <link>https://blog.jak-linux.org/2009/09/26/results-of-the-apt2-config-parser-testing/</link>
      <pubDate>Sat, 26 Sep 2009 18:12:09 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/09/26/results-of-the-apt2-config-parser-testing/</guid>
      <description>&lt;p&gt;Thanks to those who have tested it (and/or will test it). The results where helpful and resulted in &lt;a href=&#34;http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=548443&#34;&gt;Bug#548443&lt;/a&gt; filed against localepurge and &lt;a href=&#34;https://bugzilla.gnome.org/show_bug.cgi?id=596429&#34;&gt;GNOME Bug #596429&lt;/a&gt; against glib. The first one is a case where quotes where used inside a value, although this has never been defined to work, and the second one is a problem with GLib&amp;rsquo;s GScanner not ignoring multi-line C-style comments although it was configured to do so.&lt;/p&gt;
&lt;p&gt;I also fixed some bugs in APT2, like the missing build-depends on libgee-dev and the configuration parser now accepts &amp;lsquo;.&amp;rsquo;, &amp;lsquo;_&amp;rsquo;, &amp;lsquo;+&amp;rsquo; in the option name. I also talked with Eugene about some differences in the way cupt and APT2 handle quotes and about some other parts of the configuration format. Seems this was a good day.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Thanks to those who have tested it (and/or will test it). The results where helpful and resulted in <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=548443">Bug#548443</a> filed against localepurge and <a href="https://bugzilla.gnome.org/show_bug.cgi?id=596429">GNOME Bug #596429</a> against glib. The first one is a case where quotes where used inside a value, although this has never been defined to work, and the second one is a problem with GLib&rsquo;s GScanner not ignoring multi-line C-style comments although it was configured to do so.</p>
<p>I also fixed some bugs in APT2, like the missing build-depends on libgee-dev and the configuration parser now accepts &lsquo;.&rsquo;, &lsquo;_&rsquo;, &lsquo;+&rsquo; in the option name. I also talked with Eugene about some differences in the way cupt and APT2 handle quotes and about some other parts of the configuration format. Seems this was a good day.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>APT2: config parser testing</title>
      <link>https://blog.jak-linux.org/2009/09/25/apt2-config-parser-testing/</link>
      <pubDate>Fri, 25 Sep 2009 22:19:58 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/09/25/apt2-config-parser-testing/</guid>
      <description>&lt;p&gt;If you have an amd64 system, install the apt2 package from &amp;ldquo;deb &lt;a href=&#34;http://people.debian.org/~jak/debian/&#34;&gt;http://people.debian.org/~jak/debian/&lt;/a&gt; unstable/&amp;rdquo; and run the apt2-config command. Make sure that the parser reports no errors, otherwise send me an email or leave a comment here. One known exception is that all values must be quoted in the configuration file, I have no plans to fix this (probably just deprecate unquoted strings in APT instead). The parser is not as strict as cupt&amp;rsquo;s parser, but it gives you more help if something wents wrong. We also ignore most semicolons for now (they will be turned into warnings or errors later on). It is using GScanner from GLib for parsing the files.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>If you have an amd64 system, install the apt2 package from &ldquo;deb <a href="http://people.debian.org/~jak/debian/">http://people.debian.org/~jak/debian/</a> unstable/&rdquo; and run the apt2-config command. Make sure that the parser reports no errors, otherwise send me an email or leave a comment here. One known exception is that all values must be quoted in the configuration file, I have no plans to fix this (probably just deprecate unquoted strings in APT instead). The parser is not as strict as cupt&rsquo;s parser, but it gives you more help if something wents wrong. We also ignore most semicolons for now (they will be turned into warnings or errors later on). It is using GScanner from GLib for parsing the files.</p>
<p>apt2-config replicates the functionality of apt-config. It currently do not read the configuration files in the correct order, so don&rsquo;t expect &ldquo;apt2-config dump&rdquo; to produce exactly the same output as &ldquo;apt-config dump&rdquo;. To build APT2 yourself, you need a patch for waf from <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=548329">http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=548329</a>.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Chromium on Linux can print now</title>
      <link>https://blog.jak-linux.org/2009/09/23/chromium-on-linux-can-print-now/</link>
      <pubDate>Wed, 23 Sep 2009 14:58:52 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/09/23/chromium-on-linux-can-print-now/</guid>
      <description>&lt;p&gt;Just updated to revision 26808 of Chromium today, and it supports printing now. But it still does not support password encryption it seems. It also has some problems with displaying pages sometimes (buttons missing, style not loaded, etc.). But it improved a lot since I first tried it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Just updated to revision 26808 of Chromium today, and it supports printing now. But it still does not support password encryption it seems. It also has some problems with displaying pages sometimes (buttons missing, style not loaded, etc.). But it improved a lot since I first tried it.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>cupt and how to write package managers</title>
      <link>https://blog.jak-linux.org/2009/09/23/cupt-and-how-to-write-package-managers/</link>
      <pubDate>Wed, 23 Sep 2009 11:41:43 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/09/23/cupt-and-how-to-write-package-managers/</guid>
      <description>&lt;p&gt;cupt is a new package manager written in Perl by Eugene V. Lyubimkin, who previously contributed to APT. And more than all, the project makes no sense at all.&lt;/p&gt;
&lt;p&gt;First of all, there is a language issue. Implementing a package manager in Perl has some major drawbacks. One of the features of APT was it being written in a lower-level language (i.e. C++ which really is below Perl), making it possible to write applications like synaptic and python bindings which in turn lead to applications like gnome-app-install or Ubuntu&amp;rsquo;s new Software Store.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>cupt is a new package manager written in Perl by Eugene V. Lyubimkin, who previously contributed to APT. And more than all, the project makes no sense at all.</p>
<p>First of all, there is a language issue. Implementing a package manager in Perl has some major drawbacks. One of the features of APT was it being written in a lower-level language (i.e. C++ which really is below Perl), making it possible to write applications like synaptic and python bindings which in turn lead to applications like gnome-app-install or Ubuntu&rsquo;s new Software Store.</p>
<p>Furthermore, writing a package manager in Perl means that Distributions such as Emdebian might not be able to use it since they have excluded Perl due to its space requirements. This becomes even more important considering that cupt depends on even more perl libraries. This means that cupt will never be able to replace APT.</p>
<p>Secondly, a package manager should not be designed specifically for one distribution. This is another major drawback of cupt and other package managers such as yum or zypper. The smart package manager, written in Python and funded by Canonical Ltd. is an example for a distribution-neutral package manager.</p>
<p>Now let&rsquo;s take a look at package management in modern distributions. Usually we have two levels of package managers, the first being tools like dpkg and rpm which take care of installing and removing the packages and level-2 package managers implementing dependency resolvers and package retrieval from remote locations. Recently, distributions started to add a third layer named PackageKit, which shall provide distribution-independent package management user interfaces. The project was well-received by RPM-based distributions, but failed in Debian-based distributions due to not supporting debconf. Furthermore, adding a third layer just increases the possibility of problems.</p>
<p>The right way to do package management is a distribution-independent level-2 package manager written in C. The smart project shows us that this is possible although itself fails to meet the lower-level language (C) requirement. That&rsquo;s why I decided to write a package manager in Vala, a GObject-based language which gets converted to C and then compiled. If successful, this project will be able to replace most of the current level-2 package managers and will also provide the same distribution-independence as provided by a level-3 package manager such as PackageKit. It is also easy to create binding for other programming language such as Python or Perl thus enabling application developers to choose the language they like most.</p>
<p>The core of this project is a vendor-neutral library, temporarily called libapt (as the project is called APT2 for now). This library contains all the code which is not specific to a vendor i.e. file retrieval, dependency resolver, caches, etc and  is then enhanced by several vendor-specific plugins, each implementing a PackageManager (interface to the distribution&rsquo;s level-1 package manager) and a Repository (well, repositories from which you can download packages) interface.</p>
<p>We could even enhance the vendor-independent interface to include more details of a repository. Most repositories nowadays consist of 4 components: A meta index (Release files for Debian, repomd.xml for Fedora/openSUSE/etc.), a package index (e.g. Packages files for Debian, <em>primary.xml.gz on Fedora, etc. ), a source index (e.g Sources files in Debian) and a files index (e.g. Contents-</em>.gz for Debian). I took a look at the repository formats of Slackware, openSUSE and Fedora and it seems that this concept can be applied to all of them. So maybe all we need are distribution dependent parsers for those files.</p>
<p>One of the most important issues with APT is its use of mmap() for the cache. Using mmap() makes it hard to grow the cache, which is sometimes needed. We see a lot of bug reports from people with too small cache sizes. We can circumvent this problem by utilizing an embedded database like SQLite for this, but we would probably loose some speed and it may be harder to maintain a flexible API. We should see what the best option is here, both ways are possible since Vala 0.7.6 includes my patches for adding mmap(), ftruncate(), mremap() and some other functions. An idea to circumvent the mmap() issue is gathering statistics about the relation between the number of repositories and the size of the cache and then using a value which is slightly above the average statistical value.</p>
<p>The project is not very mature yet, it only includes basic library functions for downloading files and parsing configuration files, etc. You can find the (MIT licensed) code at <a href="http://git.debian.org/?p=users/jak/apt2.git">http://git.debian.org/?p=users/jak/apt2.git</a>. I also have some local code for repository management and multi-threaded file fetching, but it&rsquo;s just not ready to be merged yet.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Chromium</title>
      <link>https://blog.jak-linux.org/2009/09/03/chromium/</link>
      <pubDate>Thu, 03 Sep 2009 14:12:34 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/09/03/chromium/</guid>
      <description>&lt;p&gt;I have just switched to Chromium as my primary browser. I am running the daily-built version from the Ubuntu Jaunty PPA at &lt;a href=&#34;https://edge.launchpad.net/~chromium-daily/+archive/ppa&#34;&gt;https://edge.launchpad.net/~chromium-daily/+archive/ppa&lt;/a&gt; on my Debian unstable box. It seems quite stable, plugins are also working (with the &amp;ndash;enable-plugins option) and it can use the system&amp;rsquo;s GTK+ theme for most parts (the buttons, etc. inside webpages are not rendered using GTK+ yet, but the UI is). It currently cannot print and it also has some formatting issues on some websites, and it&amp;rsquo;s not passing the ACID3 test yet (there is a &amp;lsquo;X&amp;rsquo; in the top-right corner). I could have switched to Midori instead, but Midori is missing a cache it seems (the option can not be enabled).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I have just switched to Chromium as my primary browser. I am running the daily-built version from the Ubuntu Jaunty PPA at <a href="https://edge.launchpad.net/~chromium-daily/+archive/ppa">https://edge.launchpad.net/~chromium-daily/+archive/ppa</a> on my Debian unstable box. It seems quite stable, plugins are also working (with the &ndash;enable-plugins option) and it can use the system&rsquo;s GTK+ theme for most parts (the buttons, etc. inside webpages are not rendered using GTK+ yet, but the UI is). It currently cannot print and it also has some formatting issues on some websites, and it&rsquo;s not passing the ACID3 test yet (there is a &lsquo;X&rsquo; in the top-right corner). I could have switched to Midori instead, but Midori is missing a cache it seems (the option can not be enabled).</p>
<p>I ran the V8 and SunSpider benchmarks to compare Iceweasel 3.5, Midori 0.1.9 (using WebKit GTK+ 1.1.12) and Chromium 4.0.206.0 (r25168). The result was that Iceweasel was 10x times slower than the others in the V8 benchmark and about 5 times slower in the SunSpider benchmark. The others were almost equally fast, but Chromium won the V8 benchmark with 2338 points compared to Midori&rsquo;s 1666. More details are in the PDF <em><a href="/images/2009-09-03-chromium/browser-performance.pdf">Browser Performance</a>, which should have been an ODP, but uploading ODPs is not allowed on wordpress.com. I also ran the V8 benchmark on Arora some time ago, but it was almost as slow as iceweasel. All tests were done on my laptop running Debian GNU/Linux unstable (amd64 architecture).</em></p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>The APT2 project</title>
      <link>https://blog.jak-linux.org/2009/08/24/the-apt2-project/</link>
      <pubDate>Mon, 24 Aug 2009 15:07:45 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/08/24/the-apt2-project/</guid>
      <description>&lt;p&gt;I just started working on a replacement for APT written in Vala and called APT2 (I know, the name could be better). The main idea behind the project is to create a library for working with Debian repositories and packages, and on top of this library a few applications. This is different from APT because the project focuses on the library part, whereas APT is primarily focused on the application part.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I just started working on a replacement for APT written in Vala and called APT2 (I know, the name could be better). The main idea behind the project is to create a library for working with Debian repositories and packages, and on top of this library a few applications. This is different from APT because the project focuses on the library part, whereas APT is primarily focused on the application part.</p>
<p>I chose Vala for this task because it has an easy syntax and allows me to use the features provided by GLib and Co. really easily. GLib provides many functions needed for APT like file access, unicode handling, hashsums creation. It also provides us with signals which are useful for implementing progress reporting.</p>
<p>Another project, called &lsquo;cupt&rsquo; tries to provide an APT replacement in Perl. Apart from the fact that I don&rsquo;t like Perl, it also has the disadvantage of being too big to ship on embedded devices and is not useable from other languages such as Python or C/C++. Yet another project, &lsquo;smart&rsquo; provides a different package manager written in Python. While I like Python, it can&rsquo;t be used from languages such as Perl or C/C++ and is too large. APT2 will only require GLib, Gee and libarchive, which require about 2MB of space; about 1/10 of Perl&rsquo;s size.</p>
<p>The core of APT2 is a library called &rsquo;libapt&rsquo;. At the moment, this library provides classes for reading tag files (TagFile&amp;TagSection) and an incomplete configuration class based on libgee&rsquo;s HashMap (to ease coding, it will probably be changed to a special data structure like those in apt-pkg). The next step will be implementing a parser for configuration files (currently we only support in-memory objects) and writing the Acquire system.</p>
<p>The planned Acquire system uses GModule to modularize the support for different URI schemes. Each module provides a worker class which implements one or more URI schemes. The first of these modules will provide a worker using GIO, which deals with local file access, samba shares, FTP, SFTP, WebDAV and various other protocols, including HTTP until a replacement has been written (since we don&rsquo;t want to force gvfs-backends). The workers communicate with the parent Acquire object using signals and can cause the whole acquisition to be aborted by emiting an &ldquo;abort&rdquo; signal (or similar).</p>
<p>The whole project has just been started and may take some months until it becomes useful (if it becomes useful at all). The code can be found at <a href="http://git.debian.org/?p=users/jak/apt2.git">http://git.debian.org/?p=users/jak/apt2.git</a> and is licensed under the MIT license (see <a href="http://www.opensource.org/licenses/mit-license.php">http://www.opensource.org/licenses/mit-license.php</a>). It is a secondary project and will not affect my work on apt (not much yet) and python-apt (0.8 series).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>notify-osd in Debian</title>
      <link>https://blog.jak-linux.org/2009/08/19/notify-osd-in-debian/</link>
      <pubDate>Wed, 19 Aug 2009 12:07:43 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/08/19/notify-osd-in-debian/</guid>
      <description>&lt;p&gt;I forgot to write about this but I uploaded notify-osd to Debian some time ago which brings the passive notification bubbles known from Ubuntu. There are still some applications that do not behave correctly when using notify-osd. One example is giver which utilizes buttons on the notifications to accept or reject file transfers - As notify-osd is passive, it just displays a notification without the buttons. Using the notify plugin for Pidgin is also no good idea, as it now creates dialogs instead of displaying notifications, due to some (unneeded) buttons on the notification.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I forgot to write about this but I uploaded notify-osd to Debian some time ago which brings the passive notification bubbles known from Ubuntu. There are still some applications that do not behave correctly when using notify-osd. One example is giver which utilizes buttons on the notifications to accept or reject file transfers - As notify-osd is passive, it just displays a notification without the buttons. Using the notify plugin for Pidgin is also no good idea, as it now creates dialogs instead of displaying notifications, due to some (unneeded) buttons on the notification.</p>
<p>I personally don&rsquo;t like passive notifications that much, as I loose the control over the stuff on my display because I can&rsquo;t close the notification once I read it. But I like the design of notify-osd&rsquo;s notifications.</p>
<p>In other news python-apt 0.7.92 is now available in experimental, accepted by ftpmasters 3 hours after it entered NEW.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Python APT 0.7.92 released</title>
      <link>https://blog.jak-linux.org/2009/08/18/python-apt-0-7-92-released/</link>
      <pubDate>Tue, 18 Aug 2009 15:27:06 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/08/18/python-apt-0-7-92-released/</guid>
      <description>&lt;p&gt;The release of Python APT 0.7.92 is the first (pre-)release to introduce the new C++ bindings to create Python objects for almost every C++ object in the apt-pkg and apt-inst libraries. It is also the first version of python-apt which correctly deallocates its objects. It also introduces classes in apt_inst which are modelled after the &amp;rsquo;tarfile&amp;rsquo; module in Python. The new progress classes behave more like the ones in apt, which allows you to write even more perfect apt-get clones (if you want to). There are also several new classes and functions.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>The release of Python APT 0.7.92 is the first (pre-)release to introduce the new C++ bindings to create Python objects for almost every C++ object in the apt-pkg and apt-inst libraries. It is also the first version of python-apt which correctly deallocates its objects. It also introduces classes in apt_inst which are modelled after the &rsquo;tarfile&rsquo; module in Python. The new progress classes behave more like the ones in apt, which allows you to write even more perfect apt-get clones (if you want to). There are also several new classes and functions.</p>
<p>I expect this pre-release to be one of the most buggiest in the 0.8 series, because it changes a lot of the core stuff, like memory management. The release is currently waiting in NEW due to the new python-apt-dev package, if you want to test it, you can use the repository at <a href="http://people.debian.org/~jak/debian/experimental/">http://people.debian.org/~jak/debian/experimental/</a>, where the source package and the binaries for amd64 are provided. Most applications should continue to work with python-apt 0.7.92, if you find a non-working application, report a bug (unless its an error related to apt_pkg.Version, which has been renamed to apt_pkg.VERSION due to naming conflicts).</p>
<p>The next release should hopefully reach RC-quality. It will primarily focus on documentation updates (there is a lot of stuff missing and parts are wrong currently) and bugfixing, but will also introduce the new Qt4 progress classes. The next release will also feature the ABI and API freezes. It is scheduled for release in September (next month), and 0.8 is scheduled for October.</p>
<p>For further information, you can send me an email or ask in #debian-apt on OFTC.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>kill cdbs</title>
      <link>https://blog.jak-linux.org/2009/08/17/kill-cdbs/</link>
      <pubDate>Mon, 17 Aug 2009 21:34:21 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/08/17/kill-cdbs/</guid>
      <description>&lt;p&gt;Let&amp;rsquo;s kill CDBS and help debhelper 7 gain world domination!&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Let&rsquo;s kill CDBS and help debhelper 7 gain world domination!</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Debian&#39;s new time-based freezes</title>
      <link>https://blog.jak-linux.org/2009/07/29/debians-new-time-based-freezes/</link>
      <pubDate>Wed, 29 Jul 2009 12:34:29 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/07/29/debians-new-time-based-freezes/</guid>
      <description>&lt;p&gt;Overall, having time-based freezes is a good idea. But the chosen cycle is problematic, especially if one considers Ubuntu&amp;rsquo;s LTS release cycles. The problem is that if Debian releases a new version at approximately the same time as Ubuntu, there will not be much synchronization and Ubuntu will have newer program versions.&lt;/p&gt;
&lt;p&gt;Consider the releases of Ubuntu 8.04 LTS (April 2008) and Debian GNU/Linux 5.0 (February 2009). Whereas Ubuntu 8.04 provides GNOME 2.22 including a new Nautilus, Debian provides GNOME 2.22 with nautilus 2.20. Ubuntu&amp;rsquo;s release made at about the same time (Ubuntu 9.04) already included GNOME 2.26.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Overall, having time-based freezes is a good idea. But the chosen cycle is problematic, especially if one considers Ubuntu&rsquo;s LTS release cycles. The problem is that if Debian releases a new version at approximately the same time as Ubuntu, there will not be much synchronization and Ubuntu will have newer program versions.</p>
<p>Consider the releases of Ubuntu 8.04 LTS (April 2008) and Debian GNU/Linux 5.0 (February 2009). Whereas Ubuntu 8.04 provides GNOME 2.22 including a new Nautilus, Debian provides GNOME 2.22 with nautilus 2.20. Ubuntu&rsquo;s release made at about the same time (Ubuntu 9.04) already included GNOME 2.26.</p>
<p>The reason for this are the different development processes. Whereas a Debian release is based on stable upstream versions, the development of Ubuntu releases happens using newest pre-releases, causing Ubuntu releases to be one generation ahead in most technologies, although released at the same time.</p>
<p>Another difference is the way of freezing and the duration of the total freeze. Ubuntu has a freeze process split into multiple stages. The freeze which is comparable to Debian&rsquo;s freeze is the feature freeze, which usually happens two months before the release. Debian&rsquo;s freeze happens 6 month before the release, just about the time when Ubuntu has just defined the features to be included in the next release.</p>
<p>Synchronizing the release cycles of Debian and Ubuntu basically means that Ubuntu will always provide the newer features, better hardware support, etc. Ubuntu is the winner of this decision. It will have less bugs because it inherits from a frozen Debian branch and it can include newer versions where required because it freezes 3 months later.</p>
<p>To synchronize the package versions shipped in Debian and Ubuntu you have to make your release schedules asynchronous, in a way that the Debian release freezes after the Ubuntu release. This basically means that I expect Debian 6.0 (2010/H1) to be more similar to Ubuntu 9.10 than to Ubuntu 10.04. I would have preferred to freeze Squeeze in December 2010 and release in April 2011, and Ubuntu LTS to be re-scheduled for October 2010.</p>
<p>Now let&rsquo;s say you are a Debian and Ubuntu user (and you prefer none of them) and you want to setup a new system in 2010/H2 (so the systems have a half year to stabilize). This system should be supported for a long time. You have two options: Debian 6.0 and Ubuntu 10.04. Which will you choose? Most people would probably consider Ubuntu now, because it provides better support for their hardware and has the newer features. A (partial) solution to this problem would be to make backports an official part of Debian starting with Debian 6.0.</p>
<p>Furthermore, there is the question of security support. If we want to provide the ability to upgrade directly from Debian 5.0 to Debian 7.0, we will have to support Lenny until 2012/H2 (to give users enough time to upgrade, when we release 7.0 in 2012/H1). This means that we would have to support in 2012: Debian 5.0, 6.0 and 7.0. And another side effect is that Debian 6.0 would have a 3 year security support, just like Ubuntu 10.04.</p>
<p>All in all, the decision means that Debian and Ubuntu LTS releases will occur at about the same time, will be supported for about the same time and that Ubuntu has the newer packages and less bugs to fix.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>python-apt 0.7.91 released</title>
      <link>https://blog.jak-linux.org/2009/06/05/python-apt-0-7-91-released/</link>
      <pubDate>Fri, 05 Jun 2009 18:34:53 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/06/05/python-apt-0-7-91-released/</guid>
      <description>&lt;p&gt;As I promised, I released python-apt 0.7.91 today. This version provides a new API, with real classes in apt_pkg, new names which conform to PEP 8 conventions, and it supports new language features such as the &amp;lsquo;with&amp;rsquo; statement. Old code should still continue to work, if it does not and it is using only public interfaces, report a bug against python-apt or send an email.&lt;/p&gt;
&lt;p&gt;I can not guarantee that all the names will be kept like they are at the moment (it&amp;rsquo;s a pre-release), but there should not be many more changes needed. The series will hit Ubuntu Karmic later this month, and the final 0.8.0 release is going to be shipped in the final Karmic release.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>As I promised, I released python-apt 0.7.91 today. This version provides a new API, with real classes in apt_pkg, new names which conform to PEP 8 conventions, and it supports new language features such as the &lsquo;with&rsquo; statement. Old code should still continue to work, if it does not and it is using only public interfaces, report a bug against python-apt or send an email.</p>
<p>I can not guarantee that all the names will be kept like they are at the moment (it&rsquo;s a pre-release), but there should not be many more changes needed. The series will hit Ubuntu Karmic later this month, and the final 0.8.0 release is going to be shipped in the final Karmic release.</p>
<p>If you want to help with python-apt, consider to write some examples of what can be done with python-apt, and some tutorials for the documentation. You can also check for spelling mistakes and alike. If you want, you can also contribute code. See the documentation (in the package, or <a href="http://apt.alioth.debian.org/python-apt-doc-exp/">online</a>) for guidelines on how to contribute.</p>
<p>You can get the 0.7.91 release from Debian experimental, and you can view the documentation online at <a href="http://apt.alioth.debian.org/python-apt-doc-exp/">http://apt.alioth.debian.org/python-apt-doc-exp/</a>.</p>
<p>And of course, a short example:</p>
<pre><code>with cache.actiongroup(): # apt.Cache 'cache'
    for package in my_selected_packages:
        package.mark_install() # New PEP 8 names, previously named markInstall()
</code></pre>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Ubuntu One</title>
      <link>https://blog.jak-linux.org/2009/05/14/ubuntu-one/</link>
      <pubDate>Thu, 14 May 2009 19:50:39 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/05/14/ubuntu-one/</guid>
      <description>&lt;p&gt;Today, I was testing Canonical&amp;rsquo;s new &lt;a href=&#34;http://ubuntuone.com/&#34;&gt;Ubuntu One&lt;/a&gt; service. Ubuntu One is a service for syncing and sharing files online, with 2GB storage for free. I installed the Ubuntu One client on Ubuntu 9.04 and it&amp;rsquo;s cool.&lt;/p&gt;
&lt;p&gt;Ubuntu One creates a directory named Ubuntu One in your home directory. Within this directory, there are two subdirectories. The first one is &amp;ldquo;My Files&amp;rdquo; and the second one is named &amp;ldquo;Shared With Me&amp;rdquo;. When you place files in the &amp;ldquo;My Files&amp;rdquo; directory, the Ubuntu One client gets notified (using inotify) about the change and begins uploading the file to the Ubuntu one server.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today, I was testing Canonical&rsquo;s new <a href="http://ubuntuone.com/">Ubuntu One</a> service. Ubuntu One is a service for syncing and sharing files online, with 2GB storage for free. I installed the Ubuntu One client on Ubuntu 9.04 and it&rsquo;s cool.</p>
<p>Ubuntu One creates a directory named Ubuntu One in your home directory. Within this directory, there are two subdirectories. The first one is &ldquo;My Files&rdquo; and the second one is named &ldquo;Shared With Me&rdquo;. When you place files in the &ldquo;My Files&rdquo; directory, the Ubuntu One client gets notified (using inotify) about the change and begins uploading the file to the Ubuntu one server.</p>
<p>When you access the web interface, which should work in every modern browser, and upload a file there, the next time your local client connects the files are fetched to your local hard disk. This also works when you have two different computers and create a file on the one computer, it will be visible on the second one as soon as it has fetched the new file.</p>
<p>You could also copy your .mozilla directory into the synced directory, and create a symlink from your home directory to it. I have not tried it myself, but in theory this would allow you to have your profile synced on all your computers.</p>
<p>And the best thing about Ubuntu One is that the client is completely free software and written in Python. This makes it possible to package the client for other distributions, like Debian. Packaging it for RPM-based distribution such as Fedora should also be doable, but may require some more time.</p>
<p>There seems to have been some criticism that the server side is not free software. While that may not be the good, it&rsquo;s certainly better than other services where even the client is proprietary. And there still is the possibility to write your own server as the protocol is available.</p>
<p>Ubuntu One is currently in private beta, if you want to try it out, you need an invitation (visit <a href="http://ubuntuone.com/">ubuntuone.com</a> for further information).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>PHP, MySQL, PostgreSQL, etc.</title>
      <link>https://blog.jak-linux.org/2009/05/14/php-mysql-postgresql-etc/</link>
      <pubDate>Thu, 14 May 2009 16:02:45 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/05/14/php-mysql-postgresql-etc/</guid>
      <description>&lt;p&gt;Well, I&amp;rsquo;m currently writing a PHP and SQL application at school, so here are some of my thoughts on the problems I encounter.&lt;/p&gt;
&lt;h2 id=&#34;php-is-crap&#34;&gt;PHP is crap&lt;/h2&gt;
&lt;p&gt;Many PHP applications are low quality applications. The problem is that PHP makes it hard for developers to write good applications. PHP developers tend to use many global variables, global code, and not many classes or functions. And when writing applications for the web, PHP makes it easy to mix PHP and HTML, in my opinion even too easy.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Well, I&rsquo;m currently writing a PHP and SQL application at school, so here are some of my thoughts on the problems I encounter.</p>
<h2 id="php-is-crap">PHP is crap</h2>
<p>Many PHP applications are low quality applications. The problem is that PHP makes it hard for developers to write good applications. PHP developers tend to use many global variables, global code, and not many classes or functions. And when writing applications for the web, PHP makes it easy to mix PHP and HTML, in my opinion even too easy.</p>
<p>Well-written applications follow some basic rules. First, separate your code into functions and classes, and (2) split your code over multiple files. And there is one rule which is especially important for non-commandline applications: (3) seperate logic and presentation. This means if you write a web application, use a template engine.</p>
<p>PHP error and exception handling is also an interesting topic. The problem here lies in the distinction between the both. In my opinion, there should only be one way to handle such stuff: Using exceptions. Exceptions are a very widespread way to program today, and are used in languages like Java and Python for cases where PHP uses errors. The concept of PHP&rsquo;s errors results in code like <code>@do_something or die(&quot;blah&quot;); </code> being written in libraries which is a problem as it clearly violates rule (3) I wrote above, because there is no way to catch this die() error.</p>
<p>Furthemore, PHP has no clear concept of namespaces in the current stable versions (&lt; 5.3). PHP 5.3 finally gets namespaces, but using a backslash character, which looks really bad and makes everyone think of eithers Windows systems or escape characters.</p>
<p>There are even more problems with PHP. From time to time, PHP just crashes with a segmentation fault.</p>
<h2 id="mysql-vs-postgresql">MySQL vs. PostgreSQL</h2>
<p>MySQL seems to have many problems with checking data, which can confuse me. It got better in MySQL 5 with the introduction of the new sql_modes like STRICT_ALL_TABLES and TRADITIONAL. And using storage engines like InnoDB also allows you to take advantage of stuff like foreign keys and transactions. But MySQL is still problematic.</p>
<p>For example, in an application I wrote I had multiple entries identified by a numeric id (an INTEGER). One day, I wanted to check whether my error handling was OK and requested an entry with the invalid ID &lsquo;1X&rsquo;, which resulted in <code>SELECT * from A where id='1X';</code>. Now I expected to get an error or at least no result, but MySQL happily proceeded with the query and returned the entry with the ID 1. I tried the same thing on PostgreSQL and got an error message that &lsquo;1X&rsquo; is not integer, as I expected it.</p>
<p>As another example, when I run the same PHP application using PDO on a MySQL database and a PostgreSQL database, I always get strings from the MySQL database whereas I get integers from PostgreSQL if the columns are integers.</p>
<p>Another thing which PostgreSQL does better than MySQL is password encryption. MySQL only provides access to the standard crypt() function and by default only generates DES passwords. It allows other methods to be used (although not all are available everywhere and therefore not documented), but it provides no way to create a salt for them, which makes them not very useful. PostgreSQL in contrast provides less encryption methods but it provides the gen_salt() function which can be used to generate salts for blowfish encryption (<code>gen_salt('bf')</code>).</p>
<p>Another problem is that MySQL simply ignores references when they are added to the column definition instead of a separate &lsquo;FOREIGN KEY&rsquo;. Because MySQL gives no errors when a feature like REFERENCES is not supported, developers may think that the feature is supported and write code using this feature just to realize later that what they wrote does not what they want.</p>
<p>And you can&rsquo;t write AGPL applications using MySQL client libraries, because MySQL is GPL-2 which is incompatible with the AGPL. You might think that the &ldquo;<a href="http://www.mysql.com/about/legal/licensing/foss-exception/">FOSS License Exception</a>&rdquo; helps here, but this only lists (among others) the GPL-3. Or am I wrong?</p>
<p>But PostgreSQL has other problems, at least when it comes to the performance of the information_schema.columns view. This may be related to the fact that PostgreSQL has &gt; 1000 rows whereas MySQL only has 250. And PostgreSQL may be a bit harder to configure.</p>
<h2 id="final-words">Final words</h2>
<p>All in all, PHP and MySQL are not the best choices for writing applications. They are to tolerant, and do not treat errors in an acceptable way &ndash; by aborting the current action. I can get around some problems in PHP by using error handlers which raise exceptions and setting error_reporting to E_ALL, but in fact this should be the default. MySQL problems can be solved to a large extend by setting sql_mode to TRADTIONAL and using InnoDB databases, which should in my opinion be the default and not an option.</p>
<p>My recommendation is to use PostgreSQL servers and for the applications: use frameworks (if you are allowed to, which may not be always the case [e.g. when you are learning SQL, using a ORM is clearly the wrong way]), document your code, separate your code into classes and functions, and make sure you are not using to many global variables. And use a SCM to track your changes.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>python-apt to become first Debian package to support Python 3</title>
      <link>https://blog.jak-linux.org/2009/04/15/python-apt-to-become-first-debian-package-to-support-python-3/</link>
      <pubDate>Wed, 15 Apr 2009 18:35:57 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/04/15/python-apt-to-become-first-debian-package-to-support-python-3/</guid>
      <description>&lt;p&gt;Python 3.1 is still in experimental, but python-apt already has a fully working Python 3 version. With the patch being available in the &amp;lsquo;jak&amp;rsquo; branch, python-apt &lt;a href=&#34;http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=523645&#34;&gt;Bug#523645&lt;/a&gt; can be closed soon.&lt;/p&gt;
&lt;p&gt;And this is not the only change. Memory usage has been decreased by 10MB by creating the Package() objects on the fly instead of pre-creating all 25000 ones. All classes which previously supported the has_key() method now support &lt;strong&gt;contains&lt;/strong&gt;, which allows you to write &amp;lsquo;key in mapping&amp;rsquo;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Python 3.1 is still in experimental, but python-apt already has a fully working Python 3 version. With the patch being available in the &lsquo;jak&rsquo; branch, python-apt <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=523645">Bug#523645</a> can be closed soon.</p>
<p>And this is not the only change. Memory usage has been decreased by 10MB by creating the Package() objects on the fly instead of pre-creating all 25000 ones. All classes which previously supported the has_key() method now support <strong>contains</strong>, which allows you to write &lsquo;key in mapping&rsquo;.</p>
<p>But that&rsquo;s not all. The Package class now gained support for setting the candidate version of a package, in the same way you get it, using the property: <code>mypkg.candidate = max(mypkg.versions)</code>. And you can now pass file descriptors to functions previously only working with file() objects.</p>
<p>But we&rsquo;re not done yet. The complete API change is pending, renaming everything to PEP-8 compliant names and deprecating the old ones, which will be removed at a later time (after the release of Squeeze). The module <code>apt.debfile</code> is not affected by this change, because it already used the correct names. But for Python 3, we will not keep backward compatibility, in order to make coding easier and to make it clear that applications should be ported to the new API.</p>
<p>And if you want to get your feature into python-apt now is your time. If you want something merged, provide the code, the documentation (with example) and a list of use cases; and report a wishlist bug in the Debian BTS.</p>
<p>And if you want to write a tutorial about python-apt, write it in reStructuredText and I will add it to the documentation. The documentation is currently basically an API reference and there could be much more text.</p>
<p>Python-apt 0.7.90 is currently uploading. The whole development will result in python-apt 0.8.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Python 3.1 and python-apt</title>
      <link>https://blog.jak-linux.org/2009/04/11/python-31-and-python-apt/</link>
      <pubDate>Sat, 11 Apr 2009 20:28:04 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/04/11/python-31-and-python-apt/</guid>
      <description>&lt;p&gt;So, I have started to port python-apt to Python 3. Most things work already, but there is one single problem. I can not access the attributes of the objects, only their methods.&lt;/p&gt;
&lt;p&gt;In Python 2.5, everything works perfectly. In Python 3.1, the same code produces an error. An example is &lt;code&gt;apt_pkg.GetCache().Packages&lt;/code&gt;. I defined the slots &lt;code&gt;tp_getattro&lt;/code&gt; and &lt;code&gt;tp_methods&lt;/code&gt;. In Python 3.1, tp_getattro seems to be ignored.&lt;/p&gt;
&lt;p&gt;If you want to help,
&lt;a href=&#34;http://bzr.debian.org/loggerhead/users/jak/python-apt/py3k/changes&#34;&gt;http://bzr.debian.org/loggerhead/users/jak/python-apt/py3k/changes&lt;/a&gt; for browsing the branch and &lt;a href=&#34;http://bzr.debian.org/users/jak/python-apt/py3k/&#34;&gt;http://bzr.debian.org/users/jak/python-apt/py3k/&lt;/a&gt; for branching it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>So, I have started to port python-apt to Python 3. Most things work already, but there is one single problem. I can not access the attributes of the objects, only their methods.</p>
<p>In Python 2.5, everything works perfectly. In Python 3.1, the same code produces an error. An example is <code>apt_pkg.GetCache().Packages</code>. I defined the slots <code>tp_getattro</code> and <code>tp_methods</code>. In Python 3.1, tp_getattro seems to be ignored.</p>
<p>If you want to help,
<a href="http://bzr.debian.org/loggerhead/users/jak/python-apt/py3k/changes">http://bzr.debian.org/loggerhead/users/jak/python-apt/py3k/changes</a> for browsing the branch and <a href="http://bzr.debian.org/users/jak/python-apt/py3k/">http://bzr.debian.org/users/jak/python-apt/py3k/</a> for branching it.</p>
<p>This branch contains the current state and allows you to build a python-apt package shipping with Python 3.1 modules and extensions. But as I wrote above, not everything works yet. But its far enough for about 5 hours of work.</p>
<p><strong>Update 2009-04-12 00:17 CEST</strong>: I just fixed a bunch of problems, including the one listed above. Most of python-apt should work now, including the &lsquo;apt&rsquo; package.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>python-apt 0.7.10 released</title>
      <link>https://blog.jak-linux.org/2009/04/01/python-apt-0710-released/</link>
      <pubDate>Wed, 01 Apr 2009 16:15:29 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/04/01/python-apt-0710-released/</guid>
      <description>&lt;p&gt;I have just uploaded a version of python-apt 0.7.10 to unstable ( my first upload of python-apt, all previous uploads were done by Michael Vogt).&lt;/p&gt;
&lt;p&gt;This release is mainly a bugfix release, but also brings new features like apt.package.Version.uri and apt.package.Version.fetch_binary().I also added a Breaks: debdelta (&amp;laquo; 0.28~) because debdelta 0.27 is not working anymore since python-apt 0.7.9 and I expect that this problem will be fixed in 0.28, which could then use the new apt.package.Version.uri API to fetch the uris of the packages).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I have just uploaded a version of python-apt 0.7.10 to unstable ( my first upload of python-apt, all previous uploads were done by Michael Vogt).</p>
<p>This release is mainly a bugfix release, but also brings new features like apt.package.Version.uri and apt.package.Version.fetch_binary().I also added a Breaks: debdelta (&laquo; 0.28~) because debdelta 0.27 is not working anymore since python-apt 0.7.9 and I expect that this problem will be fixed in 0.28, which could then use the new apt.package.Version.uri API to fetch the uris of the packages).</p>
<p>Here is the changelog:</p>
<p>python-apt (0.7.10) unstable; urgency=low</p>
<pre><code>  * Build-Depend on python-debian, use it to get version number from changelog
  * Depend on libjs-jquery, and remove internal copy (Closes: #521532)
  * apt/package.py:

    *  Introduce Version.{uri,uris,fetch_binary()}


  * debian/control:

    * Remove mdz from Uploaders (Closes: #521477), add myself.
    * Update Standards-Version to 3.8.1
    * Use ${binary:Version} instead of ${Source-Version}
    * Fix spelling error: python -&gt; Python


  * debian/copyright: Switch to machine-interpretable copyright
  * Fix documentation building

    * doc/source/conf.py: Only include directories for current python version.
    * debian/control: Build-Depend on python-gtk2, python-vte.
    * setup.py: If pygtk can not be imported, do not build the documentation.


  * Breaks: debdelta (&lt;&lt; 0.28~) to avoid more problems due to the internal API changes from 0.7.9.
</code></pre>
<p>&ndash; Julian Andres Klode <a href="mailto:jak@debian.org">jak@debian.org</a>  Wed, 01 Apr 2009 15:24:29 +0200</p>
<p>Have fun.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Change has come to python-apt - aka 0.7.9 released</title>
      <link>https://blog.jak-linux.org/2009/03/23/change-has-come-to-python-apt-aka-079-released/</link>
      <pubDate>Mon, 23 Mar 2009 15:26:31 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/03/23/change-has-come-to-python-apt-aka-079-released/</guid>
      <description>&lt;p&gt;With version 0.7.9 &amp;ldquo;change has come&amp;rdquo; to python-apt, and I will tell you now what the new stuff is about:&lt;/p&gt;
&lt;h2 id=&#34;1-introduction-of-the-documentation&#34;&gt;1. Introduction of the documentation&lt;/h2&gt;
&lt;p&gt;As you may know, python-apt 0.7.8&amp;rsquo;s only documentation was available from the source code and to some parts from the docstrings. This changed in python-apt 0.7.9&lt;del&gt;exp2, when I introduced a complete documentation written in reStructuredText, and generated using Sphinx. This documentation has even improved in the final 0.7.9 release, and I will push it to the online mirror at &lt;a href=&#34;http://apt.alioth.debian.org/python-apt-doc/&#34;&gt;http://apt.alioth.debian.org/python-apt-doc/&lt;/a&gt; soon (it currently still has 0.7.9&lt;/del&gt;exp2).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>With version 0.7.9 &ldquo;change has come&rdquo; to python-apt, and I will tell you now what the new stuff is about:</p>
<h2 id="1-introduction-of-the-documentation">1. Introduction of the documentation</h2>
<p>As you may know, python-apt 0.7.8&rsquo;s only documentation was available from the source code and to some parts from the docstrings. This changed in python-apt 0.7.9<del>exp2, when I introduced a complete documentation written in reStructuredText, and generated using Sphinx. This documentation has even improved in the final 0.7.9 release, and I will push it to the online mirror at <a href="http://apt.alioth.debian.org/python-apt-doc/">http://apt.alioth.debian.org/python-apt-doc/</a> soon (it currently still has 0.7.9</del>exp2).</p>
<h2 id="2-graphical-progress">2. Graphical Progress</h2>
<p>The module apt.progress.gtk2 provides widgets for Python GTK+ coders, allowing them to easily build graphical applications interacting directly with apt. I am still looking for someone to write a apt.progress.qt4 module, if no one wants to do this, I will do it myself.</p>
<h2 id="3-enhanced-aptdebfile-module">3. Enhanced apt.debfile module</h2>
<p>A lot of code has been merged from gdebi, now allowing to do a large set of operations on local .deb files. For example, you can now install these packages. This module is also the first module to follow PEP8 naming conventions (lowercase_with_underscores), the others will be adapted at a later point.</p>
<h2 id="4-complete-code-cleanup">4. Complete code cleanup</h2>
<p>I have worked on cleaning up the whole code, fixing white space problems, and more. Ben Finney was very helpful, I merged some of his patches for whitespace. I also fixed several other problems related to PEP8 conformance. Previously the PEP8 checking tool (see documentation) found about possible 964 issues, this has been reduced to 7 (-957), but these 7 &lsquo;issues&rsquo; are simply the usage of has_key() at locations where it can&rsquo;t be avoided [interfacing with TagSection objects], i.e. they are false positives.</p>
<h2 id="5-introduction-of-aptpackageversion">5. Introduction of apt.package.Version</h2>
<p>In python-apt 0.7.9 I am introducing a new class apt.package.Version. This class provides access to various attributes of a version, like the record, the version number, the origin and even allows you to fetch the corresponding source code. But one of the best things about it is that it is sortable, allowing you to write:</p>
<pre><code>print 'Highest bash version:', max(apt.Cache()['bash'].versions)
</code></pre>
<p>This makes it very clear that you can build really cool applications with it. The various candidate*() and installed*() methods of apt.Package objects haven been deprecated, and you should use the Version() objects available via Package.installed or Package.candidate properties.</p>
<h2 id="summary">Summary</h2>
<p>All in all, the python-apt 0.7.9 is a big step forward. It is one of the largest releases in the history of python-apt and provides various new features to make developing easier. With all the code cleanups, and the documentation, you should be able to find everything you need; if not please report a bug. When we are asked &ldquo;Can we do this with python-apt?&rdquo;, we can finally say: &ldquo;Yes we can!&rdquo;</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>March updates</title>
      <link>https://blog.jak-linux.org/2009/03/19/march-updates/</link>
      <pubDate>Thu, 19 Mar 2009 19:12:11 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/03/19/march-updates/</guid>
      <description>&lt;p&gt;(This is a more or less a TODO list for my Debian packages and other stuff I&amp;rsquo;m working on)&lt;/p&gt;
&lt;h2 id=&#34;already-done&#34;&gt;Already done&lt;/h2&gt;
&lt;h3 id=&#34;new-package-metatheme-gilouche&#34;&gt;New package: metatheme-gilouche&lt;/h3&gt;
&lt;p&gt;Today I uploaded the new package metatheme-gilouche, which builds the binary package gnome-theme-gilouche. The Gilouche theme has been created by openSUSE and is used there as the default theme in GNOME. For users of gnome-app-install, this theme provides a &amp;ldquo;better&amp;rdquo; style for your main menu. It contains icons (replacing industrial-icon-theme), GTK+, and Metacity themes. The package is currently NEW, once it is in the archive, I will request removal of industrial-icon-theme. And once this package reaches Ubuntu, Ubuntu&amp;rsquo;s &lt;a href=&#34;https://bugs.launchpad.net/ubuntu/+bug/96042&#34;&gt;Bug#96042&lt;/a&gt; is closed.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>(This is a more or less a TODO list for my Debian packages and other stuff I&rsquo;m working on)</p>
<h2 id="already-done">Already done</h2>
<h3 id="new-package-metatheme-gilouche">New package: metatheme-gilouche</h3>
<p>Today I uploaded the new package metatheme-gilouche, which builds the binary package gnome-theme-gilouche. The Gilouche theme has been created by openSUSE and is used there as the default theme in GNOME. For users of gnome-app-install, this theme provides a &ldquo;better&rdquo; style for your main menu. It contains icons (replacing industrial-icon-theme), GTK+, and Metacity themes. The package is currently NEW, once it is in the archive, I will request removal of industrial-icon-theme. And once this package reaches Ubuntu, Ubuntu&rsquo;s <a href="https://bugs.launchpad.net/ubuntu/+bug/96042">Bug#96042</a> is closed.</p>
<h3 id="python-apt">python-apt</h3>
<p>Two weeks ago, Sunday (on 2009-03-08), I coded a bit in python-apt, and introduced a new class apt.package.Version, which contains information about a specific version of a package; and an interface to fetch the source package for that version. You can now simply call something like package.candidate.get_source() to fetch it.</p>
<p>The Package class now provides three new properties: Package.candidate, Package.installed and Package.version. The first two return a Version() object for the candidate/installed version or None, if no one is available (which only happens for installed; because there should always be a candidate [because Package() objects are only created for packages where at least one source is available]). These properties replace those like Package.candidateOrigin, which now is Package.candidate.origins [which also fixes the naming]. The old ones are still available, but accessing them results in a DeprecationWarning.</p>
<p>The whole thing should be hitting unstable soon as 0.7.9.</p>
<h3 id="other-stuff">Other stuff</h3>
<p>Less interesting, but also true - I have uploaded a new version of ndiswrapper (1.54), and the last snapshot of aufs1 (0+20090302-1). I have also renamed the method debimg.core.resolver.Resolver.add_task() to debimg.core.resolver.Resolver.add_tasks(), but this is a really boring change.</p>
<h2 id="planned-changes">Planned changes</h2>
<h3 id="planned-changes-in-aufs-packaging-switching-to-aufs2">Planned changes in aufs packaging: switching to aufs2</h3>
<p>This is a bit complicated, as aufs2 seems to require a large amount of new exports in the kernel. But we need to switch, because the old version of aufs is not developed anymore upstream. With the switch to aufs2, we will loose functionality like exporting the filesystem via NFS and other ones. The code will be split into two source packages, aufs-utils and aufs.</p>
<h3 id="planned-changes-in-gnome-app-install">Planned changes in gnome-app-install</h3>
<p>First of all, I need to merge the new version of gnome-app-install from Ubuntu. Afterwards, I will start working on various packaging related issues. I will switch the package from CDBS to debhelper 7; install the modules to /usr/share/gnome-app-install/, not systemwide; and also try to create a single package which works on Debian and Ubuntu, so we can have a shared package in future.</p>
<h3 id="planned-changes-in-command-not-found">Planned changes in command-not-found</h3>
<p>First of all, I need to merge the new version from Ubuntu. The version of command-not-found in Debian has various differences from the one shipped by Ubuntu. It uses the files from apt-file to create our command list, it is installed in /usr/share/command-not-found, not /usr/lib/command-not-found, and more.</p>
<p>My plans for the next upload include the inclusion of a pre-generated command-list, for those who do not want to use the apt-file based method; and because it will be available out of the box.</p>
<h3 id="planned-changes-in-python-apt">Planned changes in python-apt</h3>
<p>First of all, I am still working on improving the documentation. While everything should be listed already, there are still some problems with their descriptions, and some are missing them. I intent to fix this in python-apt 0.7.10 (or whatever version it will be). Everyone can help, for example by sending new documentation texts or more examples (see <a href="http://apt.alioth.debian.org/python-apt-doc/coding.html">http://apt.alioth.debian.org/python-apt-doc/coding.html</a> for further information).</p>
<p>Secondly, I will work on a QT4 progress module, in order to equally support GTK+ and QT4 toolkits. This is not really an important task, and if someone else wants to do this, I would be happy too.</p>
<p>Thirdly, I will work on the complete deprecation of mixedCase naming conventions, and switch everything to lowercase_with_underscores; while still providing backward compatibility.</p>
<p>Fourthly, I will complete my work on restructuring the progress module (now a package), to introduce a generic naming scheme, and modules like apt.progress.text who will implement them.</p>
<h3 id="thats-all">That&rsquo;s all</h3>
<p>If you are a developing for Python, be sure to checkout python2.6 in experimental and thank doko for uploading it. I really hope that python3.1 leaves NEW soon, so I can &ldquo;play with it&rdquo;.</p>
<p>If you know something else I did or will do in near future, please leave a comment. ;-)</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>GParted eats my day...</title>
      <link>https://blog.jak-linux.org/2009/03/15/gparted-eats-my-day/</link>
      <pubDate>Sun, 15 Mar 2009 18:14:36 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/03/15/gparted-eats-my-day/</guid>
      <description>&lt;p&gt;Today, I wanted to shrink a partition by 5GB, and move it 5GB to the right. Well, I expected that it would take some minutes, but now it seems to take more than 5 hours, because GParted moves around the whole 87GB of the resized partition.&lt;/p&gt;
&lt;p&gt;This is what happens:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  * Check file system for errors (30min)
  * Resize the file system (30min?)
  * Resize the partition
  * Check file system for errors (30min)
  * Move the file system

    * Read-only Simulation (!!!!!!!!!!!!!)
    * Do it (~5 hours)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It really should tell me that it takes such a long time. I mean, why does it have to copy all 87GB, when all I want to do is get 5GB moved to the front? It should free these 5GB on the filesystem, move them to the end of the filesystem, decrease the partition size and finish.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today, I wanted to shrink a partition by 5GB, and move it 5GB to the right. Well, I expected that it would take some minutes, but now it seems to take more than 5 hours, because GParted moves around the whole 87GB of the resized partition.</p>
<p>This is what happens:</p>
<pre><code>  * Check file system for errors (30min)
  * Resize the file system (30min?)
  * Resize the partition
  * Check file system for errors (30min)
  * Move the file system

    * Read-only Simulation (!!!!!!!!!!!!!)
    * Do it (~5 hours)
</code></pre>
<p>It really should tell me that it takes such a long time. I mean, why does it have to copy all 87GB, when all I want to do is get 5GB moved to the front? It should free these 5GB on the filesystem, move them to the end of the filesystem, decrease the partition size and finish.</p>
<p>It should not copy 87 GB 2 times, and should not run 2 filesystem checks without informing me before how long this will take. Now I wonder what happens when it resizes my 110 GB extended partition to 105 GB, and moves it?</p>
<p>Bad software, bad day.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>debian-cd, dependencies, debimg, comments</title>
      <link>https://blog.jak-linux.org/2009/03/02/debian-cd-dependencies-debimg-comments/</link>
      <pubDate>Mon, 02 Mar 2009 16:54:40 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/03/02/debian-cd-dependencies-debimg-comments/</guid>
      <description>&lt;p&gt;Looking at the amd64 CD images of Lenny, I just saw that there is the package &amp;lsquo;gnome&amp;rsquo; on disk 1, while some of its dependencies are on disk 2. I don&amp;rsquo;t think that this is good. Same also applies to K3B on disk 3, and openoffice.org-kde on KDE-disk 1.&lt;/p&gt;
&lt;p&gt;In my opinion, all packages which are located on a disk X, should only depend on a disk N (N&amp;lt;X). This means that the package gnome would be moved to disk 2, or its dependencies to disk 1.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Looking at the amd64 CD images of Lenny, I just saw that there is the package &lsquo;gnome&rsquo; on disk 1, while some of its dependencies are on disk 2. I don&rsquo;t think that this is good. Same also applies to K3B on disk 3, and openoffice.org-kde on KDE-disk 1.</p>
<p>In my opinion, all packages which are located on a disk X, should only depend on a disk N (N&lt;X). This means that the package gnome would be moved to disk 2, or its dependencies to disk 1.</p>
<p>This is exactly the way debimg works. Debimg uses so-called package groups, which simply represents a set of packages with cyclic dependencies. These package groups are returned in a specific order, so that a group N only requires a group &lt;N. This order is kept when the groups are added to the disk. Furthermore, we treat the groups as one when adding them to the disk, ie. we check whether the whole group fits on the disk (and add it) or not (create a new disk). This way, we ensure that all dependencies can be satisfied.</p>
<p>Today, I decided to try it out and therefore wrote a small script reading the debian-cd task files and comparing the file list (of the packages added to the disk) with the file list of the official KDE disk.</p>
<p>The results look very good, debimg adds 11 packages and removes 26 which is not that much, and mostly caused by wrong size limits, etc. You can look at the results your self, and regenerate them using:</p>
<pre><code>  * [http://debimg.alioth.debian.org/tests/debian-500-amd64-kde-CD-1.diff](http://debimg.alioth.debian.org/tests/debian-500-amd64-kde-CD-1.diff) - The results
  * [http://debimg.alioth.debian.org/tests/debian-cd.py](http://debimg.alioth.debian.org/tests/debian-cd.py) - The script used.
  * [http://debimg.alioth.debian.org/tests/debimg.tar.gz](http://debimg.alioth.debian.org/tests/debimg.tar.gz) - The version of debimg used (current HEAD)
</code></pre>
<p>Anyway, debimg still needs real configuration and handling of the debian installer and source packages, but this should give you an idea of how debimg works. And a tarball, for those who don&rsquo;t want to use git all the time.</p>
<p>BTW, I have now enabled comment threading here, a <a href="http://en.blog.wordpress.com/2009/02/19/comment-threading-is-here-plus-other-cool-comment-settings/">new Wordpress feature</a>. I hope that it works, as I have not tried it out yet.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>debimg update - creating images</title>
      <link>https://blog.jak-linux.org/2009/03/01/debimg-update-creating-images/</link>
      <pubDate>Sun, 01 Mar 2009 19:02:32 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/03/01/debimg-update-creating-images/</guid>
      <description>&lt;p&gt;Much happened since the last time  I wrote about debimg. The project is now registered on Alioth and has a mailing list. On the code side, there have also been several changes.&lt;/p&gt;
&lt;p&gt;First of all, the repository module has been merged into the master branch. This was the first step towards the creation of the image building, which happened today by introducing the &amp;lsquo;image&amp;rsquo; module.&lt;/p&gt;
&lt;p&gt;The code should be treated as Beta quality, but the project as a whole is Alpha, because the application utilizing debimg.core is still missing. As always, I hereby encourage to try out debimg, have a look at the examples, and help to develop it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Much happened since the last time  I wrote about debimg. The project is now registered on Alioth and has a mailing list. On the code side, there have also been several changes.</p>
<p>First of all, the repository module has been merged into the master branch. This was the first step towards the creation of the image building, which happened today by introducing the &lsquo;image&rsquo; module.</p>
<p>The code should be treated as Beta quality, but the project as a whole is Alpha, because the application utilizing debimg.core is still missing. As always, I hereby encourage to try out debimg, have a look at the examples, and help to develop it.</p>
<p>Patches should be sent to the mailing list, created with git format-patch, and its usual settings (eg. prefixed with eg. &lsquo;[PATCH 1/2]&rsquo;). The patches should be inline and validate in pyflakes and using pep8.py. See the <a href="http://git.debian.org/?p=debimg/debimg.git;a=blob_plain;f=README;hb=HEAD">README</a> for some more recommendations.</p>
<p>Because NEW seems to be really busy at the moment (and doko uploaded python2.6 and python3.1), I&rsquo;m not uploading the current state as 0.1.0<del>a1 to experimental, but wait until NEW is smaller (maybe it will be 0.1.0</del>b1 then).</p>
<h2 id="what-is-wantedplanned">What is wanted/planned?</h2>
<pre><code>  * Compatibility configuration formats

    * (debimg.config.simple_cdd) A reimplementation of simple-cdd using debimg. This probably needs to wait until there is a module for dealing with the installer, but I want to implement an application to support simple-cdd configuration files.
    * (debimg.config.debian_cd) There could be an implementation of debian-cd's configuration format. This would allow people to easily try out debimg. We can only support a subset, though.


  * New configuration formats

    * (debimg.config.yaml) Debimg's native configuration format. This is the only one supported by the graphical frontends. Where possible, configuration between compatibility formats and this format will be provided.


  * Graphical Frontends:

    * (debimg.frontend.gtk2) The graphical GTK+ frontend for inexperienced users who just want to create their own disk.
    * (debimg.frontend.qt4) The graphical frontend written in QT4.


  * Text frontends

    * (debimg.frontend.text) The basic command-line frontend.
    * (debimg.ubuntu.frontend.text) A script to build Ubuntu images, which could be used to build the official Ubuntu Images. This requires interaction with the germinate tool for dependency resolution, and more. It's also not flexible enough for building custom images.
</code></pre>
<h2 id="requirements-for-01-beta">Requirements for 0.1 Beta</h2>
<pre><code>  * Implement at least one configuration format and the build frontend.
  * Have at least one external contributor.
</code></pre>
<h2 id="more">More</h2>
<pre><code>  * Mailing-List: [debimg-devel@lists.alioth.debian.org ](mailto:debimg-devel@lists.alioth.debian.org) (Archive at [http://lists.alioth.debian.org/pipermail/debimg-devel/](http://lists.alioth.debian.org/pipermail/debimg-devel/))
  * Wiki: [http://wiki.debian.org/DebImg](http://wiki.debian.org/DebImg)
  * VCS-Git: git://git.debian.org/debimg/debimg.git
  * VCS-Browser: [http://git.debian.org/?p=debimg/debimg.git](http://git.debian.org/?p=debimg/debimg.git)
</code></pre>
<h2 id="changes">Changes</h2>
<p>Julian Andres Klode (6):</p>
<pre><code>  * debimg/core/files: When creating a file object allow filename as source
  * debimg/core/resolver.py: Introduce Package.fullname, Package.component
  * debimg/core/repository.py: Merge the repository module.
  * debimg/core/resolver.py: Improve handling of certain dependency types
  * debimg/core/repository.py: Allow Repository.add_group to take a 'distro' parameter
  * debimg/core/image.py: Introduce the image module.
</code></pre>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>GStreamer Python bindings are effectively GPL</title>
      <link>https://blog.jak-linux.org/2009/02/19/gstreamer-python-bindings-are-effectively-gpl/</link>
      <pubDate>Thu, 19 Feb 2009 18:20:47 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/02/19/gstreamer-python-bindings-are-effectively-gpl/</guid>
      <description>&lt;p&gt;While most of the bindings are LGPL licensed, modules like pygst are licensed under the terms of the GPL-2+. This means, together with the fact that you need to use pygst for any application wishing to use these binding, that you can not create proprietary or non-GPL-compatible programs using the GStreamer Python bindings.&lt;/p&gt;
&lt;p&gt;You can read more about this in the Debian Bug Tracker in &lt;a href=&#34;http://bugs.debian.org/516190&#34;&gt;Bug#516190&lt;/a&gt;. I expect that this should be forwarded to upstream but I haven&amp;rsquo;t checked their bug tracker yet.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>While most of the bindings are LGPL licensed, modules like pygst are licensed under the terms of the GPL-2+. This means, together with the fact that you need to use pygst for any application wishing to use these binding, that you can not create proprietary or non-GPL-compatible programs using the GStreamer Python bindings.</p>
<p>You can read more about this in the Debian Bug Tracker in <a href="http://bugs.debian.org/516190">Bug#516190</a>. I expect that this should be forwarded to upstream but I haven&rsquo;t checked their bug tracker yet.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Top blog posts</title>
      <link>https://blog.jak-linux.org/2009/02/19/top-blog-posts/</link>
      <pubDate>Thu, 19 Feb 2009 13:34:47 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/02/19/top-blog-posts/</guid>
      <description>&lt;p&gt;Viewing the statistics for my blog, I have come to some conclusions about what topics people are interested in. First let&amp;rsquo;s take a look at the statistics for 1 year:&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;Next would be the review of OpenSolaris and other posts, but they have less than 1000 views and are therefore not included in this post. So if you want to get many visitors, just review 2 distributions, do a benchmark of SCMs, or something like this. If you don&amp;rsquo;t want many visitors, don&amp;rsquo;t write about such topics.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Viewing the statistics for my blog, I have come to some conclusions about what topics people are interested in. First let&rsquo;s take a look at the statistics for 1 year:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Next would be the review of OpenSolaris and other posts, but they have less than 1000 views and are therefore not included in this post. So if you want to get many visitors, just review 2 distributions, do a benchmark of SCMs, or something like this. If you don&rsquo;t want many visitors, don&rsquo;t write about such topics.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Python modules, licenses, and more</title>
      <link>https://blog.jak-linux.org/2009/02/18/python-modules-licenses-and-more/</link>
      <pubDate>Wed, 18 Feb 2009 17:27:11 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/02/18/python-modules-licenses-and-more/</guid>
      <description>&lt;p&gt;Today, I want to present you some things I have asked myself and some ideas about them. You should not expect the information to be correct. Therefore, if you find mistakes, please leave a comment.&lt;/p&gt;
&lt;h2 id=&#34;copyright-statements--comments&#34;&gt;Copyright statements / Comments&lt;/h2&gt;
&lt;p&gt;MIT license: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - If you had a python module released under the MIT license, and this is in the comment of the module and you somehow ship only pyc or pyo files, you would be violating the license by not including the copyright notice, because these files do not contain the modules. This is also true for many other licenses, but this seems to be the best example.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today, I want to present you some things I have asked myself and some ideas about them. You should not expect the information to be correct. Therefore, if you find mistakes, please leave a comment.</p>
<h2 id="copyright-statements--comments">Copyright statements / Comments</h2>
<p>MIT license: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - If you had a python module released under the MIT license, and this is in the comment of the module and you somehow ship only pyc or pyo files, you would be violating the license by not including the copyright notice, because these files do not contain the modules. This is also true for many other licenses, but this seems to be the best example.</p>
<p>If you include this in the docstrings, you would only violate such license terms if you distribute bytecode created with the -OO option. This also does not apply if the code is a program which prints the license (eg. via a commandline &ndash;license option).</p>
<h2 id="gpl-vs-lgpl">GPL vs LGPL</h2>
<p>Is there any difference at all? The LGPL requires you to publish all changes you make to the code, while the GPL also requires you to publish source files you have created. This also means that you can&rsquo;t link a non-free program to a GPL library, but you can link it to a LGPL library.</p>
<p>Because Python modules are not linked to each other, everything you do is normally considered a use of the module. Therefore, if there is a module G released under the GPL, and a module X released under a different, incompatible license X, you would still be able to use the facilities provided by the module G. This also effects subclassing classes of G in X.</p>
<p>Due to the enormous flexibility provided by Python you can easily break the intented rules of the GPL. Instead of editing the class definition you subclass the class and edit it. You can also replace stuff inside the module G during run-time, simply by setting the relevant attributes.</p>
<p>In summary, Python makes it very easy to work around the restrictions of the GPL, therefore, using the LGPL instead of the GPL makes no sense. You can&rsquo;t give others more rights than they already have. You would just make it easier for others in case they want to write new code and want to copy some of yours.</p>
<h2 id="what-about-the-agpl">What about the AGPL?</h2>
<p>The AGPL exposes (compared to the GPL3) further restrictions on using the software on eg. websites. It is intended for programs which may be used by SaaS providers. Like with the GPL, the enormous flexibility of Python compensates most of the restrictions the license.</p>
<h2 id="btw-which-license-to-choose">BTW, which license to choose?</h2>
<p>I normally choose to release my programs and modules, etc. under the terms of the GNU General Public License, version 3 (or at your option) any later version. But it also depends on the size of the project. When I work on small scripts, like hardlink, I generally choose the MIT license. This is also somehow related to the fact that I don&rsquo;t want to have a license which takes more than 50% of the size of my project.</p>
<p>This is actually a bit different to what Bruce Perens <a href="http://itmanagement.earthweb.com/osrc/article.php/12068_3803101_2/Bruce-Perens-How-Many-Open-Source-Licenses-Do-You-Need.htm">does</a>. Bruce recommends 3 types of licenses. The first one is what he calls the &ldquo;gift&rdquo; license. He recommends the Apache License 2.0, because it provides better &ldquo;protection from software patent lawsuites&rdquo;. The MIT license is another example for this type of license. While not providing the patent protection, this is not that critical for persons like me who live in Germany. Furthermore, the number of patents possibly infringed by the code is proportional to the amount of code.</p>
<p>The second type he recommends is a &ldquo;sharing-with-rules&rdquo; license, like the GPL 3. Like him, I mostly use this license for my code. Sometimes I also use the GPL 2, but only when I am required to do so, or because of tradition. In generally, I only upgrade software from GPL-2+ to GPL-3+ when I introduce new features, not for bug fixes or similar.</p>
<p>The third type he describes is the &ldquo;in-between license&rdquo;, like the LGPL. As I pointed out above, this type of license is not much different than the GPL, at least if applied to Python modules. Therefore, I never release any Python module under such a license. Things may be different for C libraries (and others), but I never released one.</p>
<h2 id="documentation-etc">Documentation, etc.</h2>
<p>Well, I license all my documentation under the same license as the software. This makes it easier for the user because he does not need to read yet another license (at least if he reads all the licenses of the software he uses). If I distribute non-code content independent of code, I generally choose a Creative Commons License (CC-BY-SA 3.0, CC-BY 3.0), Germany.</p>
<p>This also has an effect on this blog. From now on, all content (ever) provided by me via this blog is licensed under the terms of the <a href="http://creativecommons.org/licenses/by-sa/3.0/de/">Creative Commons Attribution-Share Alike 3.0 Germany</a>, unless a different license information is included as part of the post. The design and comments from other persons are not included.</p>
<h2 id="why-i-wrote-this">Why I wrote this</h2>
<p>Really, I don&rsquo;t know. Maybe I just want to write something, maybe I want to write these things down, so I can read them. Anyway, please tell me if I my conclusions/ideas are wrong.</p>
<p><strong>Update 1:</strong> There was a mistake &ldquo;should expect the information to be correct&rdquo;, fixed now: &ldquo;should not expect [&hellip;]&rdquo;. I may be wrong with the GPL vs. LGPL thing, have not completely checked this. <em>(2009-02-18 19:18 CET)</em></p>
<p><strong>Update 2</strong>: Seems the GPL vs LGPL thing is not correct, as written by &ldquo;Anonymous&rdquo; and Bruce. <em>(2009-02-18 19:26 CET)</em></p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>debimg core: creating a repository</title>
      <link>https://blog.jak-linux.org/2009/02/12/debimg-core-creating-a-repository/</link>
      <pubDate>Thu, 12 Feb 2009 17:42:19 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/02/12/debimg-core-creating-a-repository/</guid>
      <description>&lt;p&gt;As I wrote Monday in &amp;ldquo;debimg core example&amp;rdquo;, I have an extended version which creates a repository. The problem on Monday was that the code was not far enough to be published. Not much has changed yet, but I considered to create a temporary branch temp/repository to be able to show you the example, and to give you an impression of what the final API will look like (it&amp;rsquo;s not complete yet, trust me).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>As I wrote Monday in &ldquo;debimg core example&rdquo;, I have an extended version which creates a repository. The problem on Monday was that the code was not far enough to be published. Not much has changed yet, but I considered to create a temporary branch temp/repository to be able to show you the example, and to give you an impression of what the final API will look like (it&rsquo;s not complete yet, trust me).</p>
<p>Now I will present you the example. It is not much longer than the pool example I gave on monday, but it does much more - it creates a repository (and it has some commandline options). The concept of the Repository is very simple, too. We have two classes, Repository and Distribution, and a Repository object contains multiple Distribution objects, which are responsible for packages and related stuff.</p>
<pre><code>#!/usr/bin/python
# Copyright (C) 2009 Julian Andres Klode.
#
# Released under the terms of the GNU General Publice License, version 3
# or (at your option) any later version.
#
&quot;&quot;&quot;Example to demonstrate the power of debimg's repository management.

This example creates a directory example.debimg, with two subdirectories:
    - pool: This holds debimg's file pool (see debimg.core.files.Pool)
    - repo: This holds the created repository (debimg.core.repository)

It creates a repository of all required packages, using your local apt sources.
&quot;&quot;&quot;
from __future__ import with_statement
import operator
import optparse
import sys

from debimg.core.resolver import Resolver
from debimg.core.files import Pool
from debimg.core.repository import Distribution, Repository

def main():
    &quot;&quot;&quot;Called when the script is executed.&quot;&quot;&quot;
    parser = optparse.OptionParser()
    parser.add_option('-u', '--user', help='Same as in GPG')
    parser.add_option('-c', '--contents', action=&quot;store_true&quot;,
                     help='Create Contents-*.gz files')
    opts, args = parser.parse_args()

    # Create a pool, which manages the access to the files.
    pool = Pool('example.debimg/pool')

    # Create a resolver using your local apt configuration.
    pkgs = Resolver()

    # Create a new repository
    repo = Repository(pool, 'example.debimg/repo')

    # Create a new distribution and store it in dist.
    dist = repo.add_distribution('lenny')

    # Add all packages with priority required to the resolver
    pkgs.add_priority('required')

    # Add the packages from the resolver to the distribution
    for group in pkgs.groups():
        for package in group:
            dist.add_package(package)

    pool.compact()   # Optional step
    pool.fetch()     # Fetch all the packages from the mirror
    dist.finalize_files() # Link the files into the repository
    dist.finalize_packages() # Create Packages files (uncompressed and gzip)

    ##
    # If we want to create Contents-*.gz files, we can do this as well:
    # but we don't want to
    if opts.contents:
        dist.finalize_contents()

    # Now create our Release files, and sign them using the key provided on
    # the commandline. If no key has been provided, do not sign it.
    dist.finalize_release(Suite='testing', key=opts.user)

    for file in sorted(pool._files, key=operator.attrgetter('uri')):
        print file   # Print information about every file, sorted by URI.

if __name__ == '__main__':
    main()
</code></pre>
<p>To try the code, checkout the temp/repository branch at git://git.debian.org/users/jak/debimg.git and execute the script named test-repository, which is the same as printed above. If you have questions, please ask. Also read the docstring of debimg.core.repository to see which changes are not yet done (eg. common base class for Distribution and Repository, and of course adding files manually).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>debimg core example</title>
      <link>https://blog.jak-linux.org/2009/02/09/debimg-core-example/</link>
      <pubDate>Mon, 09 Feb 2009 17:03:07 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/02/09/debimg-core-example/</guid>
      <description>&lt;p&gt;The following example demonstrates the features of debimg core, and how it can be used to fetch a some packages. As you will see when you run this example, debimg uses SHA1 filenames for the downloaded files. This may be changed in a future version.&lt;/p&gt;
&lt;p&gt;There is also an improved version of this example, which creates a repository, but the needed module (debimg.core.repository) is not public yet, because its far from being finished. I expect to complete repository code on Wednesday.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>The following example demonstrates the features of debimg core, and how it can be used to fetch a some packages. As you will see when you run this example, debimg uses SHA1 filenames for the downloaded files. This may be changed in a future version.</p>
<p>There is also an improved version of this example, which creates a repository, but the needed module (debimg.core.repository) is not public yet, because its far from being finished. I expect to complete repository code on Wednesday.</p>
<pre><code>#!/usr/bin/python
# Copyright (C) 2009 Julian Andres Klode.
#
# Released under the terms of the GNU General Publice License, version 3
# or (at your option) any later version.
#
&quot;&quot;&quot;Example to demonstrate the power of debimg's pool

This example creates a directory example.debimg, with two subdirectories:
- pool: This holds debimg's file pool (see debimg.core.files.Pool)
&quot;&quot;&quot;
from debimg.core.resolver import Resolver
from debimg.core.files import Pool

def main():
    &quot;&quot;&quot;Called when the script is executed.&quot;&quot;&quot;

    # Create a pool, which manages the access to the files.
    pool = Pool('example.debimg/pool')

    # Create a resolver using your local apt configuration.
    pkgs = Resolver()

    # Add all packages with priority required to the resolver
    pkgs.add_priority('required')

    # Add the packages from the resolver to the pool
    for group in pkgs.groups():
        for package in group:
            pool.add_package(package)

    pool.fetch() # Fetch all the packages from the mirror

    for file in sorted(pool._files, key=lambda k: k.uri):
        print file # Print information about every file, sorted by URI.

if __name__ == '__main__':
    main()
</code></pre>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>debimg reloaded - debimg core started</title>
      <link>https://blog.jak-linux.org/2009/02/07/debimg-reloaded-debimg-core-started/</link>
      <pubDate>Sat, 07 Feb 2009 19:43:00 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/02/07/debimg-reloaded-debimg-core-started/</guid>
      <description>&lt;p&gt;Today, I have published the first pieces of debimg 0.1. The published code includes the resolver, the compression module and the fetcher module. It is rewritten from scratch, this time with a PEP8-conforming style, and more flexible.&lt;/p&gt;
&lt;p&gt;Because debimg.core does not depend on any specific configuration format, but is configured solely via parameters, it is more flexible than debimg 0.0. This new code enables people to write their own programs related to Debian images easily. And if you want to, you can use the facilities provided by debimg.configuration and debimg.frontend to write your own program using debimg configuration files (not implemented yet, core needs to be finished first).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today, I have published the first pieces of debimg 0.1. The published code includes the resolver, the compression module and the fetcher module. It is rewritten from scratch, this time with a PEP8-conforming style, and more flexible.</p>
<p>Because debimg.core does not depend on any specific configuration format, but is configured solely via parameters, it is more flexible than debimg 0.0. This new code enables people to write their own programs related to Debian images easily. And if you want to, you can use the facilities provided by debimg.configuration and debimg.frontend to write your own program using debimg configuration files (not implemented yet, core needs to be finished first).</p>
<p>Debimg 0.1 will use YAML configuration files, supports multiple repositories, and much more. We could even implement support for pinning packages.</p>
<p>Debimg 0.1 is more than the others. It is a library (actually a python package, debimg.core), it is a program designed for end-users and developers. The enormous flexibility allows us to create applications for almost everyone.</p>
<p>My vision is that someone who needs a custom Debian image simply fires up the debimg GTK+ frontend, selects the packages he/she wants and clicks build. And when someone needs more flexibility, there will be configuration files which lets you configure most aspects. And if this does not suffice, you can write your own application by importing the modules, replacing some functions, methods, etc. and simply call the main() function of the frontend.</p>
<p><strong>The goals:</strong></p>
<pre><code>  * flexibility, high speed, and cool features.
  * be a show case for the features of the low-level python-apt bindings (apt_pkg, apt_inst)
  * high-quality code, no hacks, every single function/method/class/module documented.
  * be a library, and a program.
  * provide a graphical front-end to assist the unexperienced users.
  * provide powerful file-based configuration for advanced developers.
  * And finally, provide a replacement for debian-cd in the near future.
</code></pre>
<p><strong>More:</strong></p>
<pre><code>  * Email: [http://lists.debian.org/debian-cd/2009/02/msg00034.html](http://lists.debian.org/debian-cd/2009/02/msg00034.html)
  * Vcs-Git: git://git.debian.org/users/jak/debimg.git
  * Vcs-Browser: [http://git.debian.org/?p=users/jak/debimg.git;a=summary](http://git.debian.org/?p=users/jak/debimg.git;a=summary)
</code></pre>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Really, don&#39;t use codenames for pinning.</title>
      <link>https://blog.jak-linux.org/2009/02/02/really-dont-use-codenames-for-pinning/</link>
      <pubDate>Sun, 01 Feb 2009 22:32:15 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/02/02/really-dont-use-codenames-for-pinning/</guid>
      <description>&lt;p&gt;You can not use codenames for pinning packages to a specific release. Everything like this just fails, and can result in apt not finding any candidate for a package. You can see this for example in Bug#512318, and Bug#513864 seems to be related to that one.&lt;/p&gt;
&lt;p&gt;If you want to target Lenny and you don&amp;rsquo;t have Etch in your sources.list, pin stable at a higher priority than testing. This means that the pin automatically migrates once Lenny becomes stable (which happens hopefully in 2 weeks).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>You can not use codenames for pinning packages to a specific release. Everything like this just fails, and can result in apt not finding any candidate for a package. You can see this for example in Bug#512318, and Bug#513864 seems to be related to that one.</p>
<p>If you want to target Lenny and you don&rsquo;t have Etch in your sources.list, pin stable at a higher priority than testing. This means that the pin automatically migrates once Lenny becomes stable (which happens hopefully in 2 weeks).</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>What have you done this week?</title>
      <link>https://blog.jak-linux.org/2009/01/11/what-have-you-done-this-week/</link>
      <pubDate>Sun, 11 Jan 2009 20:02:25 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/01/11/what-have-you-done-this-week/</guid>
      <description>&lt;p&gt;Well,&lt;/p&gt;
&lt;p&gt;I wrote** 2599 lines** of documentation. More detailed I wrote 2599 lines of documentation from Thursday to Sunday.&lt;/p&gt;
&lt;p&gt;In total, the jak branch of python-apt now has a diffstat (compared to debian-sid) of:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Changes:&lt;/strong&gt; &lt;strong&gt;113 files&lt;/strong&gt; changed, &lt;strong&gt;5845 insertions&lt;/strong&gt; (+), &lt;strong&gt;2763 deletions&lt;/strong&gt;(-)&lt;/p&gt;
&lt;p&gt;Partly responsible is Ben Finney, whose patches I merged. I also closed 7 bugs not relevant anymore in current versions of python-apt.&lt;/p&gt;
&lt;p&gt;This is the changelog to from debian-sid to jak:&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Well,</p>
<p>I wrote** 2599 lines** of documentation. More detailed I wrote 2599 lines of documentation from Thursday to Sunday.</p>
<p>In total, the jak branch of python-apt now has a diffstat (compared to debian-sid) of:</p>
<p><strong>Changes:</strong> <strong>113 files</strong> changed, <strong>5845 insertions</strong> (+), <strong>2763 deletions</strong>(-)</p>
<p>Partly responsible is Ben Finney, whose patches I merged. I also closed 7 bugs not relevant anymore in current versions of python-apt.</p>
<p>This is the changelog to from debian-sid to jak:</p>
<pre><code>python-apt (0.7.9~exp2) experimental; urgency=low

  * apt/*.py:
    - Almost complete cleanup of the code
    - Remove inconsistent use of tabs and spaces (Closes: #505443)
    - Improved documentation
  * apt/debfile.py:
    - Drop get*() methods, as they are deprecated and were
      never in a stable release
    - Make DscSrcPackage working
  * apt/gtk/widgets.py:
    - Fix the code and document the signals
  * Introduce new documentation build with Sphinx
    - Contains style Guide (Closes: #481562)
    - debian/rules: Build the documentation here
    - setup.py: Remove pydoc building and add new docs.
    - debian/examples: Include examples from documentation
    - debian/python-apt.docs:
      + Change html/ to build/doc/html.
      + Add build/doc/text for the text-only documentation
  * setup.py:
    - Only create build/data when building, not all the time
    - Remove build/mo and build/data on clean -a
  * debian/control:
    - Remove the Conflicts on python2.3-apt, python2.4-apt, as
      they are only needed for oldstable (sarge)
    - Build-Depend on python-sphinx (&gt;= 0.5)
  * aptsources/distinfo.py:
    - Allow @ in mirror urls (Closes: #478171) (LP: #223097)
  * Merge Ben Finney's whitespace changes (Closes: #481563)
  * Merge Ben Finney's do not use has_key() (Closes: #481878 )
  * Do not use deprecated form of raise statement (Closes: #494259)
  * Add support for PkgRecords.SHA256Hash (Closes: #456113)

 -- Julian Andres Klode   Sun, 11 Jan 2009 20:01:59 +0100
</code></pre>
<p>&hellip;</p>
<p>This will again close 7 bugs. But the most important part is to actually have the complete documentation (OK, some descriptions are missing, but all classes,functions,methods,attributes,data should be there now).</p>
<p>I still need to rearrange parts of the documentation and add some descriptions to some pieces, but all in all I am satisfied with what I have done this week.</p>
<p>Take a look at the documentation: <a href="http://people.debian.org/~jak/python-apt-doc/apt/">http://people.debian.org/~jak/python-apt-doc/apt/</a>, it received documentation for 9 new classes today.</p>
<p>I also added an entry to the DeveloperNews page on wiki.debian.org.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>python-apt documentation - 2nd time</title>
      <link>https://blog.jak-linux.org/2009/01/10/python-apt-documentation-2nd-time/</link>
      <pubDate>Sat, 10 Jan 2009 17:38:10 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/01/10/python-apt-documentation-2nd-time/</guid>
      <description>&lt;p&gt;News: &lt;a href=&#34;http://bzr.debian.org/loggerhead/users/jak/python-apt/jak/revision/219&#34;&gt;http://bzr.debian.org/loggerhead/users/jak/python-apt/jak/revision/219&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;introduced again some new documentation.&lt;/p&gt;
&lt;p&gt;doc/source/apt/debfile.rst            |    6
doc/source/apt_pkg/cache.rst          |  540 +++++++++++++++++++++++++++++++++-
doc/source/apt_pkg/index.rst          |   24 +
doc/source/conf.py                    |    5
doc/source/examples/cache-packages.py |   22 +
doc/source/examples/cache-pkgfile.py  |   29 +
doc/source/examples/missing-deps.py   |   51 +++&lt;/p&gt;
&lt;p&gt;7 files changed, 659 insertions(+), 18 deletions(-)&lt;/p&gt;
&lt;p&gt;You can see them at &lt;a href=&#34;http://people.debian.org/~jak/python-apt-doc/&#34;&gt;http://people.debian.org/~jak/python-apt-doc/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Missing seem to be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AcquireFile&lt;/li&gt;
&lt;li&gt;AcquireItem&lt;/li&gt;
&lt;li&gt;ActionGroup&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;li&gt;MetaIndex&lt;/li&gt;
&lt;li&gt;PackageIndexFile&lt;/li&gt;
&lt;li&gt;PkgManager&lt;/li&gt;
&lt;li&gt;PkgRecords&lt;/li&gt;
&lt;li&gt;PkgSourceList&lt;/li&gt;
&lt;li&gt;PkgSrcRecords&lt;/li&gt;
&lt;li&gt;ProblemResolver&lt;/li&gt;
&lt;li&gt;TagFile&lt;/li&gt;
&lt;li&gt;TagSection&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But the weekend is not over yet. I will blog tomorrow again, and once I&amp;rsquo;m finished with everything (which may be tomorrow, too).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>News: <a href="http://bzr.debian.org/loggerhead/users/jak/python-apt/jak/revision/219">http://bzr.debian.org/loggerhead/users/jak/python-apt/jak/revision/219</a></p>
<p>introduced again some new documentation.</p>
<p>doc/source/apt/debfile.rst            |    6
doc/source/apt_pkg/cache.rst          |  540 +++++++++++++++++++++++++++++++++-
doc/source/apt_pkg/index.rst          |   24 +
doc/source/conf.py                    |    5
doc/source/examples/cache-packages.py |   22 +
doc/source/examples/cache-pkgfile.py  |   29 +
doc/source/examples/missing-deps.py   |   51 +++</p>
<p>7 files changed, 659 insertions(+), 18 deletions(-)</p>
<p>You can see them at <a href="http://people.debian.org/~jak/python-apt-doc/">http://people.debian.org/~jak/python-apt-doc/</a></p>
<p>Missing seem to be:</p>
<ul>
<li>AcquireFile</li>
<li>AcquireItem</li>
<li>ActionGroup</li>
<li>Configuration</li>
<li>MetaIndex</li>
<li>PackageIndexFile</li>
<li>PkgManager</li>
<li>PkgRecords</li>
<li>PkgSourceList</li>
<li>PkgSrcRecords</li>
<li>ProblemResolver</li>
<li>TagFile</li>
<li>TagSection</li>
</ul>
<p>But the weekend is not over yet. I will blog tomorrow again, and once I&rsquo;m finished with everything (which may be tomorrow, too).</p>
<p>Have fun, read the documentation, find the mistakes. Some things are currently written as &lsquo;???&rsquo;, if you know what fits there, please tell me.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>News from the python-apt front: NEW and COOL DOCUMENTATION</title>
      <link>https://blog.jak-linux.org/2009/01/09/news-from-the-python-apt-front/</link>
      <pubDate>Fri, 09 Jan 2009 18:00:31 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/01/09/news-from-the-python-apt-front/</guid>
      <description>&lt;p&gt;I have been working the whole week on python-apt and the result is the jak branch. This implements some of the proposals I made in my last post, but has one very interesting feature: &lt;strong&gt;REAL COOL DOCUMENTATION&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;After &lt;strong&gt;Sandro Tosi&lt;/strong&gt; told me in a comment in my last post that the real big problem with python-apt is a lack of documentation, I immediately started writing it. Using&lt;strong&gt;reStructuredText and Sphinx&lt;/strong&gt;, we now have a really cool and much more detailed documentation. (Although it is not really finished yet [it contains everything, but there is still room to improve]).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I have been working the whole week on python-apt and the result is the jak branch. This implements some of the proposals I made in my last post, but has one very interesting feature: <strong>REAL COOL DOCUMENTATION</strong>.</p>
<p>After <strong>Sandro Tosi</strong> told me in a comment in my last post that the real big problem with python-apt is a lack of documentation, I immediately started writing it. Using<strong>reStructuredText and Sphinx</strong>, we now have a really cool and much more detailed documentation. (Although it is not really finished yet [it contains everything, but there is still room to improve]).</p>
<p>The whole documentation is available at  <a href="http://people.debian.org/~jak/python-apt-doc/">http://people.debian.org/~jak/python-apt-doc/</a>, and the source is in my branch at <a href="http://bzr.debian.org/users/jak/python-apt/jak">http://bzr.debian.org/users/jak/python-apt/jak&quot;</a>, which can be browsed via Loggerhead at: <a href="http://bzr.debian.org/loggerhead/users/jak/python-apt/jak/changes">http://bzr.debian.org/loggerhead/users/jak/python-apt/jak/changes</a></p>
<p>It also contains a lot of cleanup, whitespace removal (bundled in one commit), and improved docstrings. And apt.debfile and apt.gtk.widgets should work completely now. Oh, and apt.cdrom now supports sources.list.d.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>python-apt: Deprecation of mixedCase names, re-organisation of apt.progress, and more</title>
      <link>https://blog.jak-linux.org/2009/01/04/python-apt-deprecation-of-mixedcase-names-re-organisation-of-aptprogress-and-more/</link>
      <pubDate>Sun, 04 Jan 2009 00:03:09 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2009/01/04/python-apt-deprecation-of-mixedcase-names-re-organisation-of-aptprogress-and-more/</guid>
      <description>&lt;p&gt;[as sent to deity@lists.debian.org]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hello&lt;/strong&gt;,&lt;/p&gt;
&lt;p&gt;while hacking a bit on python-apt in the last days, I formulated some
proposals which I want to present to you.&lt;/p&gt;
&lt;p&gt;I have already implemented proposals I and VII, started with the implementation
of proposal II, and have partially implemented proposal III, all in
my local branch. I could implement the rest next week, and this could
result in python-apt 0.7.9~exp2 (at least this is my wish, I do not
have commit access to the python-apt repository, and this mail is not
discussed yet:) ).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>[as sent to deity@lists.debian.org]</p>
<p><strong>Hello</strong>,</p>
<p>while hacking a bit on python-apt in the last days, I formulated some
proposals which I want to present to you.</p>
<p>I have already implemented proposals I and VII, started with the implementation
of proposal II, and have partially implemented proposal III, all in
my local branch. I could implement the rest next week, and this could
result in python-apt 0.7.9~exp2 (at least this is my wish, I do not
have commit access to the python-apt repository, and this mail is not
discussed yet:) ).</p>
<p>My local branch is not online yet, but I&rsquo;m working on it. It is based
off debian-sid revision 202 (which is 0.7.9~exp1).</p>
<p>I would have also suggest to (at least partially) follow PEP 7 (C code),
but re-indenting the whole extension code is not a good idea.</p>
<p>Before I go on, I would like to know your opinions about these proposals,
what you like and what not, your suggestions, etc, etc&hellip;</p>
<h2 id="list-of-proposals">List of Proposals</h2>
<pre><code> I   Deprecation of mixedCase naming conventions in apt module
 II  Re-organisation of the apt.progress module
 III Language updates
 IV  Unification of testing code
 V   Cleanup of the code
 VI  Using unique variable names throughout the modules
 VII Some other changes
</code></pre>
<h2 id="i-deprecation-of-mixedcase-naming-conventions-in-apt-module">I. Deprecation of mixedCase naming conventions in apt module</h2>
<p>In order to comply with PEP 8, we should start to change our names
from mixedCase to lowercase_with_underscores style. This style is
more common in the Python world, and used eg. in the Python library.</p>
<h3 id="i-hereby-propose-that">I hereby propose that:</h3>
<ol>
<li>a new module apt.deprecate is introduced, which provides functions
for compatibility and a class named DeprecateMixedCase</li>
<li>Most classes are changed to subclass DeprecateMixedCase instead of
object.</li>
<li>All methods, attributes and variable names are changed from the
mixedCase style to the lowercase_with_underscores style.</li>
<li>apt_pkg will be changed to call the new methods on progress objects,
and fall back to the old names if methods with new names are not
available.</li>
</ol>
<h3 id="how-backward-compatibility-is-implemented">How backward compatibility is implemented:</h3>
<p>The DeprecatedMixedName class provides the methods <strong>getattr</strong>()
and <strong>setattr</strong>(). These classes will forward all access to attributes
with mixedNames to the ones with lowercase_with_underscores names.</p>
<p>In case of methods, the <strong>getattr</strong>() method returns a helper function
which fixes all keyword arguments with mixedCase names and than calls
the right function.</p>
<p>As this only works for methods with mixedCase names, methods which have
mixedCase-named args, get the argument **kwds, and its content will be
checked for mixedCase-named arguments. [On the other side, given that
the API is marked as not stable, we could also drop that level of
compatibility.]</p>
<h3 id="schedule">Schedule:</h3>
<ol>
<li>Implement all the changes in an experimental version of python-apt
as soon as possible.</li>
<li>(A) Once all packages have been adjusted to use the new names, remove
the old ones (about 50 binary packages, and I would write the needed
patches). This would Breaks: about 50 packages.
or
(B) After the release of Debian Squeeze, remove the compatibility
functions (and the deprecate module from apt). This is the same
as (A), but does not require Breaks on 50 packages.</li>
</ol>
<h3 id="known-issues">Known Issues:</h3>
<ol>
<li>The methods will not be available using their oldName at class
level, only at object level. This means that some code subclassing
apt.* classes may fail. Most code will not break, however.</li>
</ol>
<h2 id="ii-re-organisation-of-the-aptprogress-module">II. Re-organisation of the apt.progress module</h2>
<p>The apt.progress module is not very consistent in the way classes
are named. For example, there is OpTextProgress but TextFetchProgress.</p>
<h3 id="therefore-i-hereby-propose-that">Therefore, I hereby propose that:</h3>
<ol>
<li>For each of the for types of progress (&lsquo;Cdrom&rsquo;, &lsquo;Fetch&rsquo;, &lsquo;Install&rsquo;, &lsquo;Op&rsquo;),
a new class is introduced with the name: Abstract%sProgress % progress</li>
<li>For each type of progress a class Text%sprogress % progress is introduced,
which subclasses Abstract%sProgress and provides textual output</li>
<li>For further classes, a general naming scheme is introduced, which is
&ldquo;%(output_type)s%(progress_type)sProgress&rdquo; [whereas (1) and (2) implement
this naming scheme]</li>
</ol>
<h3 id="schedule-1">Schedule:</h3>
<p>Same as in proposal I.</p>
<h2 id="iii-language-updates">III. Language updates</h2>
<p>The apt package has been written some time ago, and has not been updated
to make use of the latest language features.</p>
<h3 id="therefore-i-propose-that">Therefore, I propose that:</h3>
<ol>
<li>all code using old language features is adjusted to use language
features as of Python 2.5.
1.1 Examples include the use of decorators, and the use
of str methods instead of functions of the string module.</li>
<li>The with statement will be used where appropriate, and that
apt_pkg.*Lock() gain support for being used as context managers.</li>
</ol>
<h3 id="schedule-2">Schedule:</h3>
<p>Implement as soon as possible.</p>
<h2 id="iv-unification-of-testing-code">IV. Unification of testing code</h2>
<p>Most modules ship test code which will be called when the module is
run as a script.</p>
<h3 id="therefore-i-propose-that-1">Therefore, I propose that:</h3>
<ol>
<li>All testing code in the apt module is removed</li>
<li>All the tests in the &rsquo;tests&rsquo; directory of python-apt
are converted to a unified testing suite.</li>
<li>Testing code which has been removed as part of (1) is
reintroduced in the relevant test module, if appropriate.</li>
</ol>
<h3 id="schedule-3">Schedule:</h3>
<p>Implement as soon as possible.</p>
<h2 id="v-cleanup-of-the-code">V. Cleanup of the code</h2>
<p>In accordance to PEP 8, which is also named as a rule in apt/README.apt,
code will be reformatted where needed.</p>
<p>This includes 2 lines between module-level definitions, spaces after
&lsquo;,&rsquo;, comparing to None using &lsquo;is&rsquo; instead of &lsquo;=&rsquo;, and more.</p>
<h3 id="schedule-4">Schedule:</h3>
<p>Implement as soon as possible.</p>
<h2 id="vi-using-unique-variable-names-throughout-the-modules">VI. Using unique variable names throughout the modules</h2>
<p>I hereby propose the following names:</p>
<pre><code> cache    - An apt.cache.Cache() object
 pkg      - An object returned by cache[str()] (in special cases)
 pkg      - An apt.package.Package() object
 cand     - An object returned by depcache.GetCandidateVer()
</code></pre>
<p>This would remove some confusion for developers, especially
if you see that apt.Package() objects are named cand in debfile,
but pkg everywhere else.</p>
<h3 id="schedule-5">Schedule:</h3>
<p>Implement as soon as possible.</p>
<h2 id="vii-some-other-changes">VII. Some other changes</h2>
<p>Here is a list of other changes I have already made in my branch:</p>
<ul>
<li>Remove apt.package.Record(), it behaves exactly like the
object it is wrapping (apt_pkg.ParseTagFile() result)</li>
<li>Move the Origin class out of the Package() class and at
the module level.</li>
<li>If a package should be marked for upgrade, but is not upgradable
raise an exception (which will be apt.package.NotUpgradableError)</li>
</ul>
<h3 id="schedule-6">Schedule:</h3>
<p>Implement as soon as possible.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Filesystems</title>
      <link>https://blog.jak-linux.org/2008/12/19/filesystems/</link>
      <pubDate>Fri, 19 Dec 2008 15:09:22 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/12/19/filesystems/</guid>
      <description>&lt;p&gt;In the last months, I noticed that it was a bad decision to use XFS as my filesystem; and before I realized that ext3 was a bad choice as well.&lt;/p&gt;
&lt;p&gt;File systems have problems. I can&amp;rsquo;t use ext3 on my laptop, because it would check the whole disk (120GB) every 30 boots. And this check takes a very long time (15 or 30 minutes, I do not know it exactly). XFS is better, but also problematic because deleting a big directory with a deep hierarchy takes a very long time like 1.5 minutes , whereas ext3 needs a few seconds. Also I still wonder why XFS needs no checks.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>In the last months, I noticed that it was a bad decision to use XFS as my filesystem; and before I realized that ext3 was a bad choice as well.</p>
<p>File systems have problems. I can&rsquo;t use ext3 on my laptop, because it would check the whole disk (120GB) every 30 boots. And this check takes a very long time (15 or 30 minutes, I do not know it exactly). XFS is better, but also problematic because deleting a big directory with a deep hierarchy takes a very long time like 1.5 minutes , whereas ext3 needs a few seconds. Also I still wonder why XFS needs no checks.</p>
<p>Therefore I might go with ext4. The time needed to check the partition seemed to be much shorter and the speed is about the same as with ext3. The installation will probably be: Install Lenny on a ext3 partition, install kernel with ext4 support (which is kernel 2.6.28), add ext4 to /etc/initramfs-tools/modules, tar the partition, format it as ext4, and untar the contents again; because converting does not bring the advantags of ext4 to already existing files.</p>
<p>BTW, I did some benchmarking with bonnie++, and XFS had about 20,000 operations per second, whereas ext3 had 60,000. ext4dev from Kernel 2.6.27 was a bit slower than ext3</p>
<p>I also tested BTRFS, but BTRFS is 1) not stable enough 2) as slow as XFS. It also shows horrible write performance of 19MB/s using dd, whereas XFS reached 42MB/s. BTW, benchmarking btrfs with bonnie++ only works using &ldquo;-s 0&rdquo;, i.e. without I/O performance test, else you receive a kernel bug. I subscribed to the btrfs mailing list, and sent my bug report email 4 times, but it never reached the list it seems. This bug also happens <a href="http://permalink.gmane.org/gmane.comp.file-systems.btrfs/1744">in other cases</a>.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Short review: Fedora 10 and Ubuntu 8.10</title>
      <link>https://blog.jak-linux.org/2008/12/19/short-review-fedora-10-and-ubuntu-810/</link>
      <pubDate>Fri, 19 Dec 2008 12:20:22 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/12/19/short-review-fedora-10-and-ubuntu-810/</guid>
      <description>&lt;p&gt;After I tried OpenSolaris 2008.11, I also tried Fedora 10 and Ubuntu 8.10, each for almost one day.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Creation of bootable USB stick:&lt;/strong&gt; For both distributions, I created a bootable USB stick because it is faster to install from USB than from CD/DVD. The creation was easy in both cases. Fedora ships a shell script and Ubuntu a graphical program for this task. Both very equally easy to use.&lt;/p&gt;
&lt;p&gt;**Booting from USB: **Both distributions booted perfectly from USB. But there was a big difference in boot speed: Fedora 10 booted in about the same time Ubuntu needed to find the USB stick.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>After I tried OpenSolaris 2008.11, I also tried Fedora 10 and Ubuntu 8.10, each for almost one day.</p>
<p><strong>Creation of bootable USB stick:</strong> For both distributions, I created a bootable USB stick because it is faster to install from USB than from CD/DVD. The creation was easy in both cases. Fedora ships a shell script and Ubuntu a graphical program for this task. Both very equally easy to use.</p>
<p>**Booting from USB: **Both distributions booted perfectly from USB. But there was a big difference in boot speed: Fedora 10 booted in about the same time Ubuntu needed to find the USB stick.</p>
<p><strong>Installation from USB to HDD:</strong> Installation of both systems went very well, without any problems. Fedora&rsquo;s installer is far more powerful than Ubuntu&rsquo;s, e.g. it allows to use LVM or encrypted partitions. To setup LVM and encrypted volumes with Ubuntu, you need to use the text installer on Ubuntu&rsquo;s alternate disk (It&rsquo;s debian-installer). Ubuntu&rsquo;s graphical installer received a new partioning screen.</p>
<p><strong>Boot:</strong> Fedora&rsquo;s boot time seems to have improved a lot since the last release. Ubuntu&rsquo;s boot time seems to be roughly the same as in 8.04. Both distributions provide a progress bar, whereas Ubuntu&rsquo;s usplash looks better. But this may change once kernel-based modesetting works on Intel cards in Fedora, because Fedora&rsquo;s splash program needs it for graphics. Else, it only displays ASCII progress bar.</p>
<p><strong>Login:</strong> Fedora 10 shipped with GDM 2.24, which means that there are no themes yet. But this was no problem, as the non-themed design of GDM has improved a lot. I even like it more than any themed GDM I have seen. It reminds me a bit of OSX.</p>
<p><strong>Desktop:</strong> Both distributions ship with GNOME 2.24. The default themes look good, whereas Fedora&rsquo;s uses more GNOME-like icons, whereas Ubuntu uses Human, which is based on Tango. And that is important for me, since I normally do not change any aspect of my desktop, except for adding cpu frequency and tomboy applets to the panel.</p>
<p><strong>Hardware support:</strong> Both distributions provide good hardware support. Ubuntu leads here, at the cost of having non-free drivers included on the disk.For users needing windows wireless LAN drivers, Ubuntu is the right choice, as it ships ndiswrapper and the graphical frontend (ndisgtk) on the installation medium. Fedora does not include ndiswrapper, because of what it is used for (installing non-free Windows drivers). Both distributions <strong>ship firmware, and consider firmware images as free enough, as they do not run on the CPU.</strong></p>
<p><strong>EXT4:</strong> Fedora 10 ships with patches for EXT4 backported from Kernel 2.6.28. It also supports the installation on ext4 partitions, but only using the DVD and if booted with the ext4 option. The Live discs do not support installation to ext4.</p>
<p><strong>Package management:</strong> Both distributions ship with good package managment software. YUM really improved since the early times, where it downloaded an extra metadata file for every package. Nowadays, yum and apt seem to be on a nearly equal level, but aptitude lets Ubuntu win, because it can handle problems much better  (ie. it proposes ways to solve problems) than YUM.</p>
<p><strong>Graphical package management:</strong> Ubuntu wins here. Fedora only ships PackageKit for package managment, which, in my opinion, is not able to really compete with Synaptic and gnome-app-install.</p>
<p><strong>Conclusion:</strong> Both distributions are very solid. Ubuntu still has the better package managment, and a bigger selection of packages. <a href="http://www.ubuntu.com/community/ubuntustory/debian">This has only been possible due to Debian, which is the base of Ubuntu</a>. I tried to write this blog post not as an Ubuntu member. I always liked Red Hat and Fedora, and one of my first Linux distributions was Red Hat 9.</p>
<p><strong>Links:</strong></p>
<pre><code>  * [http://www.heise-online.co.uk/open/What-s-new-in-Fedora-10--/features/112093](http://www.heise-online.co.uk/open/What-s-new-in-Fedora-10--/features/112093)
  * [http://www.heise-online.co.uk/open/Ubuntu-8-10-first-tryout--/features/111823](http://www.heise-online.co.uk/open/Ubuntu-8-10-first-tryout--/features/111823)
  * [http://fedoraproject.org/](http://fedoraproject.org/)
  * [http://www.ubuntu.com/](http://www.ubuntu.com/)
</code></pre>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Short Review: OpenSolaris 2008.11</title>
      <link>https://blog.jak-linux.org/2008/12/19/short-review-opensolaris-200811/</link>
      <pubDate>Fri, 19 Dec 2008 11:33:32 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/12/19/short-review-opensolaris-200811/</guid>
      <description>&lt;p&gt;The &lt;strong&gt;installation&lt;/strong&gt; was fast and easy, comparable to the installation of Ubuntu.&lt;/p&gt;
&lt;p&gt;OpenSolaris seems to have big problems in terms of &lt;strong&gt;wireless LAN&lt;/strong&gt;. I am using a WPA/WPA2 encrypted wireless LAN, and it asked to me to enter my passphrase. I entered it, and nothing happened. I was able to get wireless working via commandline, but this lead me to the problem that domain names were not resolved. I could solve this, too. But none of this was permanently, and it should work the graphical way or tell me it does not work. Maybe this whole thing happened because I have a space in the name of my Wi-Fi network.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>The <strong>installation</strong> was fast and easy, comparable to the installation of Ubuntu.</p>
<p>OpenSolaris seems to have big problems in terms of <strong>wireless LAN</strong>. I am using a WPA/WPA2 encrypted wireless LAN, and it asked to me to enter my passphrase. I entered it, and nothing happened. I was able to get wireless working via commandline, but this lead me to the problem that domain names were not resolved. I could solve this, too. But none of this was permanently, and it should work the graphical way or tell me it does not work. Maybe this whole thing happened because I have a space in the name of my Wi-Fi network.</p>
<p>Another problem is <strong>suspend/resume</strong>, which is not yet working for most laptops; whereas recent Linux distributions support suspend/resume out-of-the-box.</p>
<p>OpenSolaris ships <strong>non-free components</strong>, e.g. NVIDIA display drivers, or Java 6 Update 10. Hopefully, there will be an option in future to install it without this stuff.</p>
<p>Talking about the <strong>desktop</strong>, there is GNOME 2.24 with a custom theme. In my opinion, the theme looks quite good, although I do not like the colours of the minimize,maximize,close buttons of the windows sometimes.</p>
<p>One feature introduced with this release is **Time Slider. **Time slider worked very well, although for  reasons I do not know, I do not really like it. The integration with nautilus is good, but I would still like to see an interface using a calender widget instead of this slider. I remember that the slider sometimes did not work as I expected, e.g. it jumped from left to right.</p>
<p><strong>The package management</strong> is interesting, but it is to hard to use in my opinion. Debian and derived distributions provide far better package managment in my opinion. Especially the graphical part needs a lot of work in order to compete with Debian.</p>
<p><strong>The overall speed</strong> was quiet good, and memory usage was 512MB. There is one problem with measuring memory consumption in gnome-system-monitor: I installed netbeans 6.5 and started it, and gnome-system-monitor showed a memory usage of around 20MB, while the program used more than 200MB (according to top).</p>
<p><strong>All in all</strong>, OpenSolaris gets closer to modern Linux distributions like Fedora 10 or Ubuntu 8.10, but it is not there yet. But with improvements in the area of Wi-Fi and Suspend/Resume,  future releases of OpenSolaris might become a good alternative to Linux distributions, at least if you do not really care about the ideas of free software.</p>
<p>**Links: **</p>
<pre><code>  * [http://www.heise-online.co.uk/open/OpenSolaris-2008-11-tested--/features/112274](http://www.heise-online.co.uk/open/OpenSolaris-2008-11-tested--/features/112274)
  * [http://www.opensolaris.org/](http://www.opensolaris.org/)
</code></pre>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Dear Wordpress.com users, Planet does not understand your post titles.</title>
      <link>https://blog.jak-linux.org/2008/12/08/dear-wordpresscom-users-planet-does-not-understand-your-post-titles/</link>
      <pubDate>Mon, 08 Dec 2008 13:54:17 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/12/08/dear-wordpresscom-users-planet-does-not-understand-your-post-titles/</guid>
      <description>&lt;p&gt;If you use wordpress.com, and added a Gravatar, always use the Atom feeds for Planet installation. There seem to be some problems with parsing the code, i.e. planet seems to understand media:title from your gravatar in the rss feed as the title of the post (therefore, the title of this post would be juliank).&lt;/p&gt;
&lt;p&gt;The URL of the feed is &lt;a href=&#34;http://juliank.wordpress.com/feed/atom/&#34;&gt;http://juliank.wordpress.com/feed/atom/&lt;/a&gt;, replace juliank with the name of your blog.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>If you use wordpress.com, and added a Gravatar, always use the Atom feeds for Planet installation. There seem to be some problems with parsing the code, i.e. planet seems to understand media:title from your gravatar in the rss feed as the title of the post (therefore, the title of this post would be juliank).</p>
<p>The URL of the feed is <a href="http://juliank.wordpress.com/feed/atom/">http://juliank.wordpress.com/feed/atom/</a>, replace juliank with the name of your blog.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>aufs 0&#43;20081023-1 uploaded to experimental</title>
      <link>https://blog.jak-linux.org/2008/10/25/aufs-20081023-1/</link>
      <pubDate>Sat, 25 Oct 2008 19:56:06 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/10/25/aufs-20081023-1/</guid>
      <description>&lt;p&gt;I just uploaded a new upstream snapshot of aufs (another unionFS) to experimental. But it is really more than just a new upstream snapshot:&lt;/p&gt;
&lt;p&gt;First of all, this release includes patches written by Jeff Mahoney &lt;a href=&#34;mailto:jeffm@suse.com&#34;&gt;jeffm@suse.com&lt;/a&gt;. These patches enable the usage of NFSv2 and NFSv3 file systems as branches, even on the standard Debian kernel. The package does not support NFSv4 yet, but will support it at a later point (but only with a patched kernel) - the code exists, it&amp;rsquo;s just not enabled yet.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I just uploaded a new upstream snapshot of aufs (another unionFS) to experimental. But it is really more than just a new upstream snapshot:</p>
<p>First of all, this release includes patches written by Jeff Mahoney <a href="mailto:jeffm@suse.com">jeffm@suse.com</a>. These patches enable the usage of NFSv2 and NFSv3 file systems as branches, even on the standard Debian kernel. The package does not support NFSv4 yet, but will support it at a later point (but only with a patched kernel) - the code exists, it&rsquo;s just not enabled yet.</p>
<p>This release also removes support for pre-lenny Kernels (&lt;2.6.26) and uses quilt instead of dpatch. It also removes any AppArmor support for the moment, but this may be added back later.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>I am a Debian Developer now!</title>
      <link>https://blog.jak-linux.org/2008/10/14/i-am-a-debian-developer-now/</link>
      <pubDate>Mon, 13 Oct 2008 23:41:00 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/10/14/i-am-a-debian-developer-now/</guid>
      <description>&lt;p&gt;14 months after applying for the NM process, I&amp;rsquo;m a Debian Developer.&lt;/p&gt;
&lt;p&gt;On Mon, Oct 13, 2008 at 10:51:43PM +0000, Martin Zobel-Helas wrote:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[ This is a long mail with important information, so please read it all
   carefully. ]&lt;/p&gt;
&lt;p&gt;Dear Julian Andres Klode!&lt;/p&gt;
&lt;p&gt;Your account &amp;lsquo;jak&amp;rsquo; has just been created in the central LDAP
database of the Debian project.  [&amp;hellip;]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thank you everyone (in chronological order):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  * Daniel Baumann (daniel) - Sponsored my first packages
  * Joerg Jaspert (joerg) - The first DD who signed my key
  * Niv Sardi-Altivanik (xaiki) - Advocated me for NM
  * Martin Zobel-Helas (zobel) - My first AM
  * Alexander Reichle-Schmehl (tolimar) - The second DD who signed my key (at CeBIT)
  * Bernd Zeimetz (bzed) - Took over in June, because zobel was very busy
  * Christoph Berg (myon) - For checking the AM report and requesting the account creation
  * Jonathan McDowell (noodles) - For adding me to the keyring
  * Martin Zobel-Helas (zobel) - This time for creating my account
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And many thanks to Google - for helping me to find &lt;a href=&#34;http://www.google.com/search?q=Answer%20to%20Life,%20the%20Universe,%20and%20Everything&#34;&gt;answers to important questions&lt;/a&gt;. Without you, I would know nothing. And of course all the others who helped to make this possible.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>14 months after applying for the NM process, I&rsquo;m a Debian Developer.</p>
<p>On Mon, Oct 13, 2008 at 10:51:43PM +0000, Martin Zobel-Helas wrote:</p>
<blockquote>
<p>[ This is a long mail with important information, so please read it all
   carefully. ]</p>
<p>Dear Julian Andres Klode!</p>
<p>Your account &lsquo;jak&rsquo; has just been created in the central LDAP
database of the Debian project.  [&hellip;]</p>
</blockquote>
<p>Thank you everyone (in chronological order):</p>
<pre><code>  * Daniel Baumann (daniel) - Sponsored my first packages
  * Joerg Jaspert (joerg) - The first DD who signed my key
  * Niv Sardi-Altivanik (xaiki) - Advocated me for NM
  * Martin Zobel-Helas (zobel) - My first AM
  * Alexander Reichle-Schmehl (tolimar) - The second DD who signed my key (at CeBIT)
  * Bernd Zeimetz (bzed) - Took over in June, because zobel was very busy
  * Christoph Berg (myon) - For checking the AM report and requesting the account creation
  * Jonathan McDowell (noodles) - For adding me to the keyring
  * Martin Zobel-Helas (zobel) - This time for creating my account
</code></pre>
<p>And many thanks to Google - for helping me to find <a href="http://www.google.com/search?q=Answer%20to%20Life,%20the%20Universe,%20and%20Everything">answers to important questions</a>. Without you, I would know nothing. And of course all the others who helped to make this possible.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Gentoo destroying earth?</title>
      <link>https://blog.jak-linux.org/2008/10/10/gentoo-destroying-earth/</link>
      <pubDate>Fri, 10 Oct 2008 15:23:15 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/10/10/gentoo-destroying-earth/</guid>
      <description>&lt;p&gt;I worked a bit with some Gentoo systems the last days and it was no fun. The whole compiling thing is no fun. In fact, it is a danger for the environment. If every computer in the world run Gentoo, power consumption would increase dramatically. There would also be no netbooks, as they are almost unusable for running Gentoo on it, compiling software.&lt;/p&gt;
&lt;p&gt;The path chosen by binary distributions like Debian is much better. Packages are compiled centrally and users download and install these pre-compiled packages. But it is also much less flexible in terms of which functionality is supported. We, as package maintainers, have to decide which functionality is likely to be used by the users. In Contrast, Gentoo has USE flags, which allows the user to enable the specific functionality he/she wants.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I worked a bit with some Gentoo systems the last days and it was no fun. The whole compiling thing is no fun. In fact, it is a danger for the environment. If every computer in the world run Gentoo, power consumption would increase dramatically. There would also be no netbooks, as they are almost unusable for running Gentoo on it, compiling software.</p>
<p>The path chosen by binary distributions like Debian is much better. Packages are compiled centrally and users download and install these pre-compiled packages. But it is also much less flexible in terms of which functionality is supported. We, as package maintainers, have to decide which functionality is likely to be used by the users. In Contrast, Gentoo has USE flags, which allows the user to enable the specific functionality he/she wants.</p>
<p>Should we combine the advantages of both technologies? Provide a normal binary distribution as we do now, but also provide a framework for users to easily recompile their packages, adding new functionality.</p>
<p>Imagine a combination of all these technologies:  User wants to install software X with feature F. The package maintainer has not enabled F in the binary. The user opens the website for his personal archive, selects the F flag and the software and clicks on build. The server builds the software and notifies the user once the binary is ready.</p>
<p>At Ubuntu, the first step has been made into this direction. While the package format is still the same, Launchpad allows users to create so-called PPAs (Personal Package Archives), where users can upload their source packages, which are then compiled and made available to other users. Let&rsquo;s say Project A releases version X of their software. They can create a source package for it, upload it to the PPA, and provide the binary packages to the users. Prior to PPAs, most users would have used an old version, compile their own version or use tarballs containing pre-compiled software (mozilla does this).</p>
<p>And sorry for the title. I respect the Gentoo community and the Gentoo developers, they are doing great work there. And ebuilds and Gentoo&rsquo;s boot system (with this runscript stuff) is really easy.</p>
<p>BTW: I also like the way Gentoo displays its boot messages. It looks much more organized than Debian&rsquo;s boot process. (In terms of the message logging, where Debian writes &ldquo;done&rdquo; when something is done, and Gentoo writes &ldquo;[OK]&rdquo; to the right side of the screen, in green letters. (This is partially possible in Debian using lsb-base-logging.sh, but not all init scripts use these functions, or they use the wrong ones.)</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>&#34;Birthdays 2008&#34;</title>
      <link>https://blog.jak-linux.org/2008/09/29/birthdays-2008/</link>
      <pubDate>Mon, 29 Sep 2008 11:31:17 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/09/29/birthdays-2008/</guid>
      <description>&lt;p&gt;The most important birthdays in the FLOSS world this year (where age mod 5 = 0):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  * **10 years: **Google (September), Open Source Initiative (February)
  * **15 years:** Debian, FreeBSD, NetBSD
  * **25 years:** GNU
  * **35 years:** Ian Murdock (April), Mark Shuttleworth (September)
  * **55 years:** Richard Stallman (March)
&lt;/code&gt;&lt;/pre&gt;</description>
      <content:encoded><![CDATA[ <p>The most important birthdays in the FLOSS world this year (where age mod 5 = 0):</p>
<pre><code>  * **10 years: **Google (September), Open Source Initiative (February)
  * **15 years:** Debian, FreeBSD, NetBSD
  * **25 years:** GNU
  * **35 years:** Ian Murdock (April), Mark Shuttleworth (September)
  * **55 years:** Richard Stallman (March)
</code></pre>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Now SPI contributing member</title>
      <link>https://blog.jak-linux.org/2008/08/14/spi-contrib-member/</link>
      <pubDate>Thu, 14 Aug 2008 08:04:53 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/08/14/spi-contrib-member/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m now an SPI contributing member.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I&rsquo;m now an SPI contributing member.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Joined Software in the Public Interest (SPI)</title>
      <link>https://blog.jak-linux.org/2008/08/13/joined-spi/</link>
      <pubDate>Wed, 13 Aug 2008 11:44:37 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/08/13/joined-spi/</guid>
      <description>&lt;p&gt;On Monday, I joined Software in the Public Interest (SPI). I&amp;rsquo;m currently a non-contributing member and have already applied for contributing membership.&lt;/p&gt;
&lt;p&gt;MJ Ray asked &lt;a href=&#34;http://www.news.software.coop/why-people-do-and-dont-join-spi/14/&#34;&gt;why people do and dont join SPI&lt;/a&gt;,  and &lt;a href=&#34;http://www.news.software.coop/spi-meeting-tonight-and-why-people-dont-join-spi/44/&#34;&gt;received answers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Not knowing SPI is no good reason, at least if you are participating in Debian&amp;rsquo;s development, and you should really know SPI if you are a Debian Developer.&lt;/p&gt;
&lt;p&gt;For me, personally, not joining the SPI would not make any sense. The existance of other organizations is no good reason. Look at me, I am also a Fellow of the Free Software Foundation Europe.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>On Monday, I joined Software in the Public Interest (SPI). I&rsquo;m currently a non-contributing member and have already applied for contributing membership.</p>
<p>MJ Ray asked <a href="http://www.news.software.coop/why-people-do-and-dont-join-spi/14/">why people do and dont join SPI</a>,  and <a href="http://www.news.software.coop/spi-meeting-tonight-and-why-people-dont-join-spi/44/">received answers</a>.</p>
<p>Not knowing SPI is no good reason, at least if you are participating in Debian&rsquo;s development, and you should really know SPI if you are a Debian Developer.</p>
<p>For me, personally, not joining the SPI would not make any sense. The existance of other organizations is no good reason. Look at me, I am also a Fellow of the Free Software Foundation Europe.</p>
<p>There is only one reason which seems to be a bit right: It&rsquo;s hard to join SPI. The membership information is located at &lsquo;About -&gt; Membership&rsquo; in the menu. Maybe this should be made a top-level menu-item and a big link &ldquo;JOIN!&rdquo; should be put on the homepage.</p>
<p>I see no reasons for anybody to not <a href="https://members.spi-inc.org/">join SPI</a>. All you need to <a href="https://members.spi-inc.org/">join</a> is a valid email address and interest in free software.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Ubuntu hardy: swfdec0.7 and swfdec-mozilla0.7 in the PPA</title>
      <link>https://blog.jak-linux.org/2008/05/23/ubuntu-hardy-swfdec07-and-swfdec-mozilla07-in-the-ppa/</link>
      <pubDate>Fri, 23 May 2008 19:35:51 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/05/23/ubuntu-hardy-swfdec07-and-swfdec-mozilla07-in-the-ppa/</guid>
      <description>&lt;p&gt;As promised, i have built a few development snapshots of the swfdec git branch for hardy. They are available in my PPA.&lt;/p&gt;
&lt;p&gt;To use it, add the following line to /etc/apt/sources.list and install swfdec-mozilla0.7.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;deb &amp;lt;a href=&amp;quot;http://ppa.launchpad.net/juliank/ubuntu&amp;quot;&amp;gt;http://ppa.launchpad.net/juliank/ubuntu&amp;lt;/a&amp;gt; &amp;lt;span&amp;gt;hardy&amp;lt;/span&amp;gt; main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Please note that these packages are experimental and are only for experienced users.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>As promised, i have built a few development snapshots of the swfdec git branch for hardy. They are available in my PPA.</p>
<p>To use it, add the following line to /etc/apt/sources.list and install swfdec-mozilla0.7.</p>
<pre><code>deb &lt;a href=&quot;http://ppa.launchpad.net/juliank/ubuntu&quot;&gt;http://ppa.launchpad.net/juliank/ubuntu&lt;/a&gt; &lt;span&gt;hardy&lt;/span&gt; main
</code></pre>
<p>Please note that these packages are experimental and are only for experienced users.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>The future of dir2ogg - gstreamer?</title>
      <link>https://blog.jak-linux.org/2008/05/23/the-future-of-dir2ogg-gstreamer/</link>
      <pubDate>Thu, 22 May 2008 22:23:03 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/05/23/the-future-of-dir2ogg-gstreamer/</guid>
      <description>&lt;p&gt;After playing a bit with gst-launch, I found out that it can convert music files and keeps the tags. Therefore, I think it would be great to rewrite dir2ogg using gstreamer (the python bindings).&lt;/p&gt;
&lt;p&gt;This version of dir2ogg will be much much smaller, and is really easy to extend. It will also support multiple output formats and does not need to know about the input files (use -i &amp;lsquo;SHELL PATTERN&amp;rsquo; to include other files).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>After playing a bit with gst-launch, I found out that it can convert music files and keeps the tags. Therefore, I think it would be great to rewrite dir2ogg using gstreamer (the python bindings).</p>
<p>This version of dir2ogg will be much much smaller, and is really easy to extend. It will also support multiple output formats and does not need to know about the input files (use -i &lsquo;SHELL PATTERN&rsquo; to include other files).</p>
<p>But it will not really replace dir2ogg. The old dir2ogg will still be supported.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>swfdec working perfectly with gstreamer</title>
      <link>https://blog.jak-linux.org/2008/05/22/swfdec-working-perfectly-with-gstreamer/</link>
      <pubDate>Thu, 22 May 2008 21:59:42 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/05/22/swfdec-working-perfectly-with-gstreamer/</guid>
      <description>&lt;p&gt;After the trouble with swfdec and gstreamer, I found out the source of the issue (the fluendo mp3 plugin, see below), and can now use swfdec with gstreamer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Warning: Do not use the mp3 plugin from fluendo.com&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;swfdec does not always work with the binary mp3 plugin from fluendo.com, at least not in Ubuntu 8.04 64bit. It works with the version shipped in Ubuntu (gstreamer0.10-fluendo-mp3) and with the mad plugin in gstreamer0.10-plugins-ugly. An example is &lt;a href=&#34;http://youtube.com/watch?v=CSp7jsV7oG0&#34;&gt;http://youtube.com/watch?v=CSp7jsV7oG0&lt;/a&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>After the trouble with swfdec and gstreamer, I found out the source of the issue (the fluendo mp3 plugin, see below), and can now use swfdec with gstreamer.</p>
<p><strong>Warning: Do not use the mp3 plugin from fluendo.com</strong></p>
<p>swfdec does not always work with the binary mp3 plugin from fluendo.com, at least not in Ubuntu 8.04 64bit. It works with the version shipped in Ubuntu (gstreamer0.10-fluendo-mp3) and with the mad plugin in gstreamer0.10-plugins-ugly. An example is <a href="http://youtube.com/watch?v=CSp7jsV7oG0">http://youtube.com/watch?v=CSp7jsV7oG0</a></p>
<p><strong>Installation of missing gstreamer plugins</strong></p>
<p>This works on both, Debian and Ubuntu, provided gnome-app-install is installed (default in Ubuntu). Simply open a youtube video, and you will be asked for searching the missing codecs. This also works in almost any other gstreamer application, like rhythmbox or totem.</p>
<p><strong>Builds of the development branch</strong></p>
<p>I will provide builds of the 0.7.1 git versions of swfdec and swfdec-mozilla in my PPA soon. This version even supports fullscreen mode in youtube! The PPA will build versions for hardy and intrepid.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Ubuntu: swfdec using ffmpeg in PPA</title>
      <link>https://blog.jak-linux.org/2008/05/22/swfdec-for-hardy-with-ffmpeg/</link>
      <pubDate>Thu, 22 May 2008 19:02:20 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/05/22/swfdec-for-hardy-with-ffmpeg/</guid>
      <description>&lt;p&gt;I created a version of swfdec 0.6.6 using mad and ffmpeg instead of gstreamer, because with gstreamer it failed to play multiple videos on youtube.com.&lt;/p&gt;
&lt;p&gt;The release is available in my PPA at:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;deb http://ppa.launchpad.net/juliank/ubuntu hardy main
deb-src http://ppa.launchpad.net/juliank/ubuntu hardy main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I will also provide some builds of the development branch (0.7.1) soon.&lt;/p&gt;
&lt;p&gt;**Update:**Maybe it was not clear, but the videos crashed the browser. It also didn&amp;rsquo;t really work in totem and I&amp;rsquo;m still looking for the source of the problem. I have every available gstreamer plugin package installed. Try it yourself, &lt;a href=&#34;http://youtube.com/watch?v=CSp7jsV7oG0&#34;&gt;http://de.youtube.com/watch?v=CSp7jsV7oG0&lt;/a&gt;. It works with gnash, but gnash does not work with wordpress stats page.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I created a version of swfdec 0.6.6 using mad and ffmpeg instead of gstreamer, because with gstreamer it failed to play multiple videos on youtube.com.</p>
<p>The release is available in my PPA at:</p>
<pre><code>deb http://ppa.launchpad.net/juliank/ubuntu hardy main
deb-src http://ppa.launchpad.net/juliank/ubuntu hardy main
</code></pre>
<p>I will also provide some builds of the development branch (0.7.1) soon.</p>
<p>**Update:**Maybe it was not clear, but the videos crashed the browser. It also didn&rsquo;t really work in totem and I&rsquo;m still looking for the source of the problem. I have every available gstreamer plugin package installed. Try it yourself, <a href="http://youtube.com/watch?v=CSp7jsV7oG0">http://de.youtube.com/watch?v=CSp7jsV7oG0</a>. It works with gnash, but gnash does not work with wordpress stats page.</p>
<p><strong>Update 2:</strong> I now found the real problem: I had an binary version of fluendo&rsquo;s mp3 plugin installed (from fluendo.com), which caused the crash. After removing the file, everything works. (using fluendo-mp3 shipped with Ubuntu).</p>
<p><strong>Update 3:</strong> I removed the ffmpeg version from my PPA, as it is not needed.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>News on debimg</title>
      <link>https://blog.jak-linux.org/2008/05/06/debimg-news/</link>
      <pubDate>Tue, 06 May 2008 18:21:54 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/05/06/debimg-news/</guid>
      <description>&lt;p&gt;Well, you may have noticed that debimg 0.1 is still not released. But a lot of work happened over the weekend in my local branch.&lt;/p&gt;
&lt;p&gt;First of all, debimg&amp;rsquo;s set support is almost finished. I uploaded a tarball containing the differences between the official lenny weekly build from yesterday and a build created today by debimg, using the tasks of debian-cd 3.0.4 (after manual conversion to a format supported by debimg). Look at &lt;a href=&#34;http://jak-linux.org/cdimage/tests/&#34;&gt;http://jak-linux.org/cdimage/tests/&lt;/a&gt; for the tarball.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Well, you may have noticed that debimg 0.1 is still not released. But a lot of work happened over the weekend in my local branch.</p>
<p>First of all, debimg&rsquo;s set support is almost finished. I uploaded a tarball containing the differences between the official lenny weekly build from yesterday and a build created today by debimg, using the tasks of debian-cd 3.0.4 (after manual conversion to a format supported by debimg). Look at <a href="http://jak-linux.org/cdimage/tests/">http://jak-linux.org/cdimage/tests/</a> for the tarball.</p>
<p>Secondly, the dependency resolver has been rewritten. It&rsquo;s a bit slower now (0.72 seconds for main), but creates much better results. Resolving the dependencies of all packages in Debian Lenny i386 in alphabetical order, debimg 0.0.X resolved 206 dependencies differently than apt. Now, these have been decreased to 15 dependencies, whereas 13 dependencies are false-positive (some packages were not installed because they were already installed). This means that only two ones were different, in this caseachims-guestbook and chdrv, which both depend on virtual-only packages (achims-guestbook: apache | httpd, chdrv: console-utilities).</p>
<p>The third big change is the addition of the hooks module. This module allows you to hook in custom functions, which have access to the Configuration object (ConfigObj) and the MediaSet. There are currently three types of hooks: pre_hooks (run before fetching packages, adding files to the disk), mid_hooks (run after the packages have been fetched) and post_hooks (run after the image has been built). Hooks can be added based on project and architecture, using a simple syntax which support shell patterns. (It&rsquo;s &lsquo;project/arch&rsquo;). The hooks module uses python decorators to register functions. debimg 0.2 will switch to hooks for internal functions, too, like bootloaders and other stuff.</p>
<p>The code has not been merged into the master branch, but I will hopefully be able to merge it tomorrow. The release of debimg 0.1 is now planned for this weekend.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>What will be in debimg 0.1</title>
      <link>https://blog.jak-linux.org/2008/04/29/what-will-be-in-debimg-01/</link>
      <pubDate>Tue, 29 Apr 2008 19:14:03 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/04/29/what-will-be-in-debimg-01/</guid>
      <description>&lt;p&gt;debimg 0.1 will be the first major milestone in the development of debimg. I will now list some changes compared to the current release, debimg 0.0.3 (&lt;em&gt;Please note that the following text is from an internal NEWS file and may not be correct in some aspects, as it is already some days old&lt;/em&gt;)&lt;/p&gt;
&lt;h4 id=&#34;support-for-disk-splitting&#34;&gt;Support for disk splitting&lt;/h4&gt;
&lt;p&gt;This release of debimg adds support for creating media sets, i.e. splitting the packages over multiple disks. This is achieved by providing a new class called MediaSet, which passes all calls to methods to all medias.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>debimg 0.1 will be the first major milestone in the development of debimg. I will now list some changes compared to the current release, debimg 0.0.3 (<em>Please note that the following text is from an internal NEWS file and may not be correct in some aspects, as it is already some days old</em>)</p>
<h4 id="support-for-disk-splitting">Support for disk splitting</h4>
<p>This release of debimg adds support for creating media sets, i.e. splitting the packages over multiple disks. This is achieved by providing a new class called MediaSet, which passes all calls to methods to all medias.</p>
<p>When a package is added to a MediaSet, MediaSet tries to find the first disk where it can be added, by checking if all dependencies of the package are provided on the disk (or previous ones). This dependency checker does no recursive dependency checks, and can be disabled via OptimizedDiskSplitting = False (or no, n, 0&hellip;) in the configuration file.</p>
<p>The MediaSet classes are also lists, so you can access disk one via the index 0. BaseMedia has been modified to also support being accessed via index, using disknumber-1 in order to have both classes share the same API.</p>
<h4 id="new-data-lists">New data lists</h4>
<p>This release of debimg brings users a more powerful way to include packages. Instead of various keys to include packages, debimg now uses the Include key.</p>
<p>To include packages, you have to use the &lsquo;Include&rsquo; field. The value is a list of items, separated by commas. An item may either be the name of a package or a special form written as key:value. In this case, the following keys are supported:</p>
<p>Task/Priority:
This includes all packages belonging to the specified task or priority. In
case of tasks, debimg first includes all Key packages, then the other
packages.</p>
<h4 id="configuration-files-are-easier">Configuration files are easier</h4>
<p>This release of debimg makes it possible to build multiple architectures using the Architectures option. This option replaces the previous Architecture option, which is now set automatically by the script for each architecture.</p>
<p>It also enables the Projects option, in case you want to build multiple projects. (All need to have the same MediaType and same NumberOfDisks). The project may also be cd-set, dvd-set, dvd9-set, netinst or businesscard. In these cases, MediaType is set automatically. [MediaType may also be moved in to data files].</p>
<p>This release also allows you to prefix any configuration value with path: in order to automatically convert the value to an absolute path. This is needed for many file options, but should not be used for some other stuff.</p>
<h4 id="improved-jigdo-support">Improved Jigdo Support</h4>
<p>debimg 0.1 allows you to define the public path (name) to (of) the image file and the template file that is written to the Jigdo file.</p>
<h4 id="use-urlgrabber-for-file-downloading">Use urlgrabber for file downloading</h4>
<p>Starting with this release, debimg uses urlgrabber to download all kinds of files (except packages). A urlgrab call has been added to BaseMedia.addFile() which now understands http:// and ftp:// urls.</p>
<h4 id="plugins-maybe">Plugins (maybe)</h4>
<p>debimg 0.1 may introduce support for registering custom functions. This feature is low-priority, although required for easy development of Ubuntu-related code.</p>
<h4 id="about-debimg">About debimg</h4>
<p>debimg is a GPL-3 licensed software designed to replace debian-cd, a tool to create Debian images. For further information about debimg, visit the <a href="http://wiki.debian.org/DebImg">Wiki page</a>. For more information about Debian, visit the website at <a href="http://www.debian.org/">www.debian.org</a>.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Python Speed: &#39;x in list&#39; vs &#39;x in set&#39;</title>
      <link>https://blog.jak-linux.org/2008/04/29/python-speed-x-in-list-vs-x-in-set/</link>
      <pubDate>Tue, 29 Apr 2008 17:42:25 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/04/29/python-speed-x-in-list-vs-x-in-set/</guid>
      <description>&lt;p&gt;Well, this is my second post about speed in Python. Today, I noticed that debimg&amp;rsquo;s dependency resolver was much much slower than before. I thought what the problem could be and finally realized that the problem was that I switched from sets to list. This is fixed now in &lt;a href=&#34;http://git.debian.org/?p=users/jak-guest/debimg.git;a=commit;h=d0fd700080de5c19cb5fd66918d14c5ffa26e805&#34;&gt;commit d0fd700080de5c19cb5fd66918d14c5ffa26e805&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, some benchmarks (using IPython):&lt;/p&gt;
&lt;p&gt;In [1]: a = range(10**6)&lt;/p&gt;
&lt;p&gt;In [2]: b = set(a)&lt;/p&gt;
&lt;p&gt;In [3]: %timeit 10**6 in a
10 loops, best of 3: 31.8 ms per loop&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Well, this is my second post about speed in Python. Today, I noticed that debimg&rsquo;s dependency resolver was much much slower than before. I thought what the problem could be and finally realized that the problem was that I switched from sets to list. This is fixed now in <a href="http://git.debian.org/?p=users/jak-guest/debimg.git;a=commit;h=d0fd700080de5c19cb5fd66918d14c5ffa26e805">commit d0fd700080de5c19cb5fd66918d14c5ffa26e805</a></p>
<p>Now, some benchmarks (using IPython):</p>
<p>In [1]: a = range(10**6)</p>
<p>In [2]: b = set(a)</p>
<p>In [3]: %timeit 10**6 in a
10 loops, best of 3: 31.8 ms per loop</p>
<p>In [4]: %timeit 10**6 in b
10000000 loops, best of 3: 98.6 ns per loop</p>
<p>1ms are 1 million ns. Therefore, using sets is about 322515 times faster than using lists (or tuples).</p>
<p>debimg can now calculate dependencies in 0.5 seconds again, instead of 1 minute with lists.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Responding to e-mails with Evolution</title>
      <link>https://blog.jak-linux.org/2008/04/25/responding-to-e-mails-with-evolution/</link>
      <pubDate>Fri, 25 Apr 2008 20:50:02 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/04/25/responding-to-e-mails-with-evolution/</guid>
      <description>&lt;p&gt;Every time I receive an email at my ubuntu.com address, and respond to it, Evolution uses my &lt;a href=&#34;mailto:jak@jak-linux.org&#34;&gt;jak@jak-linux.org&lt;/a&gt; e-mail address.&lt;/p&gt;
&lt;p&gt;It should be noted that the e-mails are fetched with a single account, as they are on an imap server, and because ubuntu.com is a forward address.&lt;/p&gt;
&lt;p&gt;Is there any way to make Evolution respond with the e-mail address at which I received an email?&lt;/p&gt;
&lt;p&gt;BTW, work on debimg 0.0.4ubuntu1 (previously 0.0.3ubuntu1) has reached the first milestone: Support for selecting packages based on the output of Germanite. This weekend, I will release debimg 0.0.4 and debimg 0.0.4ubuntu1 (or I merge it directly, let&amp;rsquo;s see).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Every time I receive an email at my ubuntu.com address, and respond to it, Evolution uses my <a href="mailto:jak@jak-linux.org">jak@jak-linux.org</a> e-mail address.</p>
<p>It should be noted that the e-mails are fetched with a single account, as they are on an imap server, and because ubuntu.com is a forward address.</p>
<p>Is there any way to make Evolution respond with the e-mail address at which I received an email?</p>
<p>BTW, work on debimg 0.0.4ubuntu1 (previously 0.0.3ubuntu1) has reached the first milestone: Support for selecting packages based on the output of Germanite. This weekend, I will release debimg 0.0.4 and debimg 0.0.4ubuntu1 (or I merge it directly, let&rsquo;s see).</p>
<p><strong>Update:</strong> This was just some mistake on my side. I get emails from an Ubuntu mailing list and want to send emails to it using the ubuntu.com address. It works for normal emails.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Work on ubuimg / debimg for Ubuntu started</title>
      <link>https://blog.jak-linux.org/2008/04/25/work-on-ubuimg-debimg-for-ubuntu-started/</link>
      <pubDate>Fri, 25 Apr 2008 14:28:34 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/04/25/work-on-ubuimg-debimg-for-ubuntu-started/</guid>
      <description>&lt;p&gt;The work on the Ubuntu version of debimg has begun. The majority of changes will be the following ones (in the order they will be done):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  1. Change debimg to use germinate to calculate dependencies (package lists)
  2. Add the additional stuff (live, etc.)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once we can recreate the Ubuntu hardy i386 and amd64 alternate disks, work starts on the live filesystem and on merging these features back into debimg master, which will also get support for more archs.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>The work on the Ubuntu version of debimg has begun. The majority of changes will be the following ones (in the order they will be done):</p>
<pre><code>  1. Change debimg to use germinate to calculate dependencies (package lists)
  2. Add the additional stuff (live, etc.)
</code></pre>
<p>Once we can recreate the Ubuntu hardy i386 and amd64 alternate disks, work starts on the live filesystem and on merging these features back into debimg master, which will also get support for more archs.</p>
<p>debimg uses germinate directly on the Python level.</p>
<p>debimg 0.0.3ubuntu1 is sheduled for this Sunday. This will be more or less really hacks.</p>
<pre><code>  * [master] Move the fetching of packages from packages to media, so we can use it for all files
  * Add libdebimg.germinate as a wrapper around germinate, providing functions to build the disks
  * Modify libdebimg to build all disks in one run, multiple architectures and multiple seeds.
</code></pre>
<p>The basic code structure will look like the following:</p>
<pre><code>  1. For each architecture:

    1. seeds = Run germinate
    2. For seed in seeds:

      1. Get the packages
      2. Get extra files
      3. Build the disk
</code></pre>
<p>The Debian version may switch to seed files too, in version 0.2.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>April Updates</title>
      <link>https://blog.jak-linux.org/2008/04/24/april-updates/</link>
      <pubDate>Thu, 24 Apr 2008 18:30:59 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/04/24/april-updates/</guid>
      <description>&lt;p&gt;This is a summary of most of my activities since end of march. BTW, I&amp;rsquo;m still at the T&amp;amp;S step in NM since January (I completed P&amp;amp;P in about 3 days). Also, thank you &lt;a href=&#34;http://blog.schmehl.info/&#34;&gt;Tolimar&lt;/a&gt; for being the second DD signing my key!&lt;/p&gt;
&lt;h4 id=&#34;gnome-222-python--updated-packages&#34;&gt;GNOME 2.22 (Python) / Updated Packages&lt;/h4&gt;
&lt;p&gt;At the end of march, I updated some GNOME packages. These packages were gnome-python and gnome-python-desktop. The upload of gnome-python-desktop was really important, because the old version depended on libtotem-plparser7, which was not available anymore, and FTBFS because the metacity API changed. This upload made other packages building and running again!&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>This is a summary of most of my activities since end of march. BTW, I&rsquo;m still at the T&amp;S step in NM since January (I completed P&amp;P in about 3 days). Also, thank you <a href="http://blog.schmehl.info/">Tolimar</a> for being the second DD signing my key!</p>
<h4 id="gnome-222-python--updated-packages">GNOME 2.22 (Python) / Updated Packages</h4>
<p>At the end of march, I updated some GNOME packages. These packages were gnome-python and gnome-python-desktop. The upload of gnome-python-desktop was really important, because the old version depended on libtotem-plparser7, which was not available anymore, and FTBFS because the metacity API changed. This upload made other packages building and running again!</p>
<p>That time, I also uploaded new releases of dir2ogg and ndisgtk, which fixed some bugs.</p>
<p>On the first of April, I updated aufs to a new upstream snapshot, which fixed linux-modules-extra-2.6&rsquo;s FTBFS on armel, removed bashism in shell scripts, added a hack for limited splice support, and enabled building on -rt kernel (if the required functions are exported).</p>
<h4 id="packages-to-do">Packages To-Do</h4>
<p>In the next week, I will upload a new aufs snapshot with support for kernel 2.6.25 and re-added support for kernels &lt; 2.6.23. I will also update app-install-data to the current state of the archive.</p>
<p>Other stuff includes my ITA upload of gimmie and the upload of jockey, a tool to install drivers. Jockey will also be modified to provide the functionality from ndisgtk, which development has been discontinued as it is feature-complete (bug fixes will still be provided). Another package will be, of course, debimg 0.1 once it&rsquo;s released and of course the python-libisofs bindings.</p>
<h4 id="ubuntu-packages">Ubuntu packages</h4>
<p>I requested syncs for dir2ogg and ndisgtk (after I uploaded sync&rsquo;able versions to Debian) and for aria2, which was not installable before. I have also reported some bugs and used 8.04 for some time.</p>
<h4 id="debimg-stuff">debimg stuff</h4>
<p>I <a href="http://juliank.wordpress.com/2008/04/04/debimg-003-released/">released debimg 0.0.3</a> on 4th April. This is the first release to require Python 2.5 and also the first release which uses the new media module, which provides a generic interface to disk creation.</p>
<p>I actually have not worked on debimg since that day, mainly because I did not have enough time. In May, I hope to add support for more architectures (at least theoretically, by providing a generic way of handling bootloaders and other non-packages and non-dists files) and release 0.1.</p>
<p>debimg 0.1 will not contain any features related to python-libisofs, because the focus is getting the basic functionality.</p>
<p>I have also not uploaded any new netinst build on jak-linux.org, since March.</p>
<h5 id="debimg-and-the-debian-project-news">debimg and the Debian Project News</h5>
<p>Debimg will appear in the second issue of the Debian Project News, I&rsquo;m currently working on the text for it. (BTW, I have also fixed one link in the first issue of the DPN)</p>
<h5 id="debimg-and-ubuntu">debimg and Ubuntu</h5>
<p>I <a href="https://lists.ubuntu.com/archives/ubuntu-devel-discuss/2008-April/003928.html">have suggested</a> to switch Ubuntu&rsquo;s image building to debimg, and offered to do everything needed to do this. Given the speed of debimg and that the current features almost match the requirements of Ubuntu, this seems to be a great idea.</p>
<h4 id="python-libisofs">python-libisofs</h4>
<p>As you may know, I released a first preview of the python-libisofs bindings some days ago, with almost complete support for creating image files. The next steps will be reading and growing images and of course, the bindings for libburn and libisoburn.</p>
<h4 id="switching-from-ubuntu-804-to-debian-unstable">Switching from Ubuntu 8.04 to Debian unstable</h4>
<p>I am currently working on migrating my laptop from Ubuntu 8.04 to Debian unstable, in order to be able to work better on my packages. Since most of my packages are sync&rsquo;able now, this enables more efficient development. Another reason is to help the lenny release. This does not mean that I will be less active on the Ubuntu side, at least not much.</p>
<p>Let&rsquo;s make Debian Lenny and Ubuntu Intrepid the best releases ever.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Fedora 9 &amp; Kernel Mode Setting</title>
      <link>https://blog.jak-linux.org/2008/04/20/fedora-9-preview/</link>
      <pubDate>Sun, 20 Apr 2008 17:07:52 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/04/20/fedora-9-preview/</guid>
      <description>&lt;p&gt;Today, I decided to try out the new kernel mode setting feature in Fedora 9, which moves some stuff about video from userspace into the kernel.&lt;/p&gt;
&lt;p&gt;I tested this on my notebook, a HP Compaq 6720s with Intel X3100 (GM965) graphics controller.&lt;/p&gt;
&lt;p&gt;I downloaded the preview live image for x86_64 and booted with the i915.modeset=1 option. The boot was almost normal, except that it was flicker-free. After the system booted I switched the virtual terminal from Xorg to tty1 and back, and it was extremely fast. The terminals all had the same resolution.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Today, I decided to try out the new kernel mode setting feature in Fedora 9, which moves some stuff about video from userspace into the kernel.</p>
<p>I tested this on my notebook, a HP Compaq 6720s with Intel X3100 (GM965) graphics controller.</p>
<p>I downloaded the preview live image for x86_64 and booted with the i915.modeset=1 option. The boot was almost normal, except that it was flicker-free. After the system booted I switched the virtual terminal from Xorg to tty1 and back, and it was extremely fast. The terminals all had the same resolution.</p>
<p>This does not mean that everything is perfect. There are a lot of things which do not work. For example, running glxgears and moving the window does not &ldquo;look good&rdquo;. Also, speed was a bit low. Normally, in Ubuntu Hardy, I get about 1000 FPS, in Fedora I only got 230 FPS. But the difference was not visible.</p>
<p>Another thing which did not work was suspend &amp; resume, because the graphics card seemed to be not correctly re-initialized. This is worse than Ubuntu &amp; Debian. In Ubuntu, suspend &amp; resume works almost every time. In Debian, it works except that the backlight is disabled in X.</p>
<p>If these problems can be fixed, it would be very interesting to get this feature into Ubuntu Intrepid, maybe not as the default, but as an option for people who want to test it.</p>
<p>Fedora 9 seems to be a fast and stable distribution, with experimental features for experienced users and developers. It also provides a nice application for configuring PulseAudio, like per-application volume settings, a functionality I miss in Ubuntu.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>python-libisofs 0.0.1 available</title>
      <link>https://blog.jak-linux.org/2008/04/17/python-libisofs-001-available/</link>
      <pubDate>Thu, 17 Apr 2008 15:37:59 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/04/17/python-libisofs-001-available/</guid>
      <description>&lt;p&gt;A first preview of the python-libisofs bindings is available now. It&amp;rsquo;s currently located in a git branch at git.debian.org, but this may change at a later point.&lt;/p&gt;
&lt;p&gt;The bindings support the creation of ISO Images and  (almost) all options libisofs supports, like Rockridge, Joliet, and much more. Reading and Modifying existing images is not supported yet.&lt;/p&gt;
&lt;p&gt;The code is written in Cython and you need cython installed for building from the git branch. It can be installed just like any other Python module/extension/package, using a setup.py.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>A first preview of the python-libisofs bindings is available now. It&rsquo;s currently located in a git branch at git.debian.org, but this may change at a later point.</p>
<p>The bindings support the creation of ISO Images and  (almost) all options libisofs supports, like Rockridge, Joliet, and much more. Reading and Modifying existing images is not supported yet.</p>
<p>The code is written in Cython and you need cython installed for building from the git branch. It can be installed just like any other Python module/extension/package, using a setup.py.</p>
<p>Browse: <a href="http://git.debian.org/?p=users/jak-guest/python-libisofs.git">http://git.debian.org/?p=users/jak-guest/python-libisofs.git</a>
Get: git clone git://git.debian.org/git/users/jak-guest/python-libisofs.git</p>
<p>I&rsquo;ll package it for Debian within the next weeks after some further tests.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Asia: Phoenix available in Europe</title>
      <link>https://blog.jak-linux.org/2008/04/11/asia-phoenix-available-in-europe/</link>
      <pubDate>Fri, 11 Apr 2008 17:58:24 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/04/11/asia-phoenix-available-in-europe/</guid>
      <description>&lt;p&gt;After the reunion of the original Asia lineup in 2006, a tour and the live cd/dvd &amp;ldquo;Fantasia - Live in Tokyo&amp;rdquo; in 2007, the super group returns with the first new studio album in 25 years.&lt;/p&gt;
&lt;p&gt;For those of you who don&amp;rsquo;t know about them, Asia is a band formed in 1981, including former members of Yes, King Crimson, and Emerson, Lake &amp;amp; Palmer, Uriah Heep, U.K., and The Buggles.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>After the reunion of the original Asia lineup in 2006, a tour and the live cd/dvd &ldquo;Fantasia - Live in Tokyo&rdquo; in 2007, the super group returns with the first new studio album in 25 years.</p>
<p>For those of you who don&rsquo;t know about them, Asia is a band formed in 1981, including former members of Yes, King Crimson, and Emerson, Lake &amp; Palmer, Uriah Heep, U.K., and The Buggles.</p>
<p>The most popular song of Asia is &ldquo;Heat of the Moment&rdquo;, from their debut album which spent 9 weeks at number 1 U.S. album chart.</p>
<p>This new album is excellent, featuring songs like the rocker &ldquo;Never Again&rdquo; and &ldquo;Extraordinary Life&rdquo;. A must-have for all Asia fans out there.</p>
<p>The new album will be released in the United States on April, 15 and in Japan on April, 23. It can be bought from <a href="http://www.amazon.com/gp/product/B00154GEFU/103-6892410-1513430?ie=UTF8&amp;tag=emilink112-20&amp;linkCode=xm2&amp;camp=1789&amp;creativeASIN=B00154GEFU">Amazon.com</a> for $9.99 and in Germany from <a href="http://amazon.de/gp/product/B0014PAFQE/ref=s9sims_c5_img1-rfc_p_1067275_250858_52959_36824_36563_36601_44166_43745?pf_rd_m=A3JWKAKR8XB7XF&amp;pf_rd_s=center-4&amp;pf_rd_r=1YHB2CH6KCT2TFVBP969&amp;pf_rd_t=101&amp;pf_rd_p=158843291&amp;pf_rd_i=301128">Amazon.de</a> for 15.97€. (See your own Amazon for your local price.)</p>
<p>BTW, the Album is already #20 in Amazon.com Music Bestsellers.</p>
<p><a href="http://originalasia.com/">Visit the band&rsquo;s Website</a>, and buy your own one from your favorite shop.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>debimg 0.0.3 - &#34;the checksum&#34; - released</title>
      <link>https://blog.jak-linux.org/2008/04/04/debimg-003-released/</link>
      <pubDate>Fri, 04 Apr 2008 19:00:12 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/04/04/debimg-003-released/</guid>
      <description>&lt;p&gt;Dear readers,&lt;/p&gt;
&lt;p&gt;The third release of debimg is available now: 0.0.3&lt;/p&gt;
&lt;p&gt;Get the tarball: &lt;a href=&#34;http://alioth.debian.org/~jak-guest/debimg_0.0.3.tar.gz&#34;&gt;http://alioth.debian.org/~jak-guest/debimg_0.0.3.tar.gz&lt;/a&gt;
Verify it:       &lt;a href=&#34;http://alioth.debian.org/~jak-guest/debimg_0.0.3.tar.gz.asc&#34;&gt;http://alioth.debian.org/~jak-guest/debimg_0.0.3.tar.gz.asc&lt;/a&gt;
The ChangeLog:   &lt;a href=&#34;http://alioth.debian.org/~jak-guest/ChangeLog-0.0.3&#34;&gt;http://alioth.debian.org/~jak-guest/ChangeLog-0.0.3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Clone git repo: git://git.debian.org/git/users/jak-guest/debimg.git
Browse the repo: &lt;a href=&#34;http://git.debian.org/?p=users/jak-guest/debimg.git&#34;&gt;http://git.debian.org/?p=users/jak-guest/debimg.git&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;More Information: &lt;a href=&#34;http://wiki.debian.org/DebImg&#34;&gt;http://wiki.debian.org/DebImg&lt;/a&gt;
Daily images:     &lt;a href=&#34;http://jak-linux.org/cdimage/daily-builds/testing/&#34;&gt;http://jak-linux.org/cdimage/daily-builds/testing/&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;about-debimg&#34;&gt;About debimg&lt;/h4&gt;
&lt;p&gt;debimg is a software designed to replace debian-cd, written in Python, and
supporting the creation of single disks for the i386 and amd64 architectures.&lt;/p&gt;
&lt;p&gt;debimg is of course free software and licensed under the terms of the GNU
General Public License 3 or (at your option) any later version.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Dear readers,</p>
<p>The third release of debimg is available now: 0.0.3</p>
<p>Get the tarball: <a href="http://alioth.debian.org/~jak-guest/debimg_0.0.3.tar.gz">http://alioth.debian.org/~jak-guest/debimg_0.0.3.tar.gz</a>
Verify it:       <a href="http://alioth.debian.org/~jak-guest/debimg_0.0.3.tar.gz.asc">http://alioth.debian.org/~jak-guest/debimg_0.0.3.tar.gz.asc</a>
The ChangeLog:   <a href="http://alioth.debian.org/~jak-guest/ChangeLog-0.0.3">http://alioth.debian.org/~jak-guest/ChangeLog-0.0.3</a></p>
<p>Clone git repo: git://git.debian.org/git/users/jak-guest/debimg.git
Browse the repo: <a href="http://git.debian.org/?p=users/jak-guest/debimg.git">http://git.debian.org/?p=users/jak-guest/debimg.git</a></p>
<p>More Information: <a href="http://wiki.debian.org/DebImg">http://wiki.debian.org/DebImg</a>
Daily images:     <a href="http://jak-linux.org/cdimage/daily-builds/testing/">http://jak-linux.org/cdimage/daily-builds/testing/</a></p>
<h4 id="about-debimg">About debimg</h4>
<p>debimg is a software designed to replace debian-cd, written in Python, and
supporting the creation of single disks for the i386 and amd64 architectures.</p>
<p>debimg is of course free software and licensed under the terms of the GNU
General Public License 3 or (at your option) any later version.</p>
<h4 id="about-the-checksum">About &ldquo;the checksum&rdquo;</h4>
<p>This release is called &ldquo;the checksum&rdquo;, because the software knows
the MD5SUM, SHA1SUM and SHA256SUM of every file on the disk.</p>
<h4 id="news">News</h4>
<pre><code>  * Introduction of the media module

    * Add md5sum.txt and sha1sum.txt to the image
    * NEW OPTION: JigdoMap, see the config file
    * Lot of code cleanup


  * Support for custom installer images

    * Modify InstallerImages to an url supported by apt


  * Renamed most options in the configuration file for better
</code></pre>
<p>readability
* debimg requires Python 2.5, as it uses the with statement.</p>
<h4 id="description-of-the-release">Description of the Release</h4>
<p>This release of debimg introduces the media module with its classes
MediaFile, BaseMedia and DebianMedia.</p>
<p>The MediaFile class contains information about a file.
It contains the absolute path to the file on the filesystem,
the path on the media, its size, md5sum, sha1sum and sha256sum.</p>
<p>The BaseMedia class provides methods to add files to the
image, open files on it, and creating the final image. It also
provides methods to create the files md5sum.txt and sha1sum.txt,
and methods to support Jigdo file creation.</p>
<p>The DebianMedia class provides methods to add packages to
the image, creating Release and Packages files for dists.</p>
<h4 id="quick-start">Quick start</h4>
<p>To get started with debimg, get the tarball and extract it to
some directory.</p>
<p>Now, open the file debimg.cfg and change the option Mirror to the URL
of your preferred mirror. This mirror may be any kind of mirror supported by
apt, but if you use file:/ they have to be on the same mountpoint, as the files
are hardlinked. (use copy:/ to get them copied).</p>
<p>Now, run <code>./debimg debimg.cfg</code>. This will create an ISO image named
debian-lenny-i386-netinst.iso. This image is a normal netinst (except for
missing documentation and some other small things), and contains the Lenny d-i.</p>
<p>To change more settings, take a look at debimg.cfg.</p>
<h4 id="future">Future</h4>
<pre><code>  * Cleanup of the configuration format (almost finished)
  * Support for splitting disks

    * Introduction of MediaSet class
    * Changes to the lists required


  * Add documentation to the disks
  * Support for PowerPC
  * Create Debian package (almost finished)
</code></pre>
<p>Another interesting feature will be the libisofs [0] support provided by
the python-libisofs extension, which is currently under development. [1]</p>
<h4 id="previous-release-announcements">Previous release announcements</h4>
<pre><code>  * 0.0.2: [http://lists.debian.org/debian-cd/2008/03/msg00114.html](http://lists.debian.org/debian-cd/2008/03/msg00114.html)
  * 0.0.1: [http://lists.debian.org/debian-cd/2008/03/msg00021.html](http://lists.debian.org/debian-cd/2008/03/msg00021.html)
</code></pre>
<h4 id="links">Links</h4>
<pre><code>  * [0] libburnia project: [http://libburnia-project.org/](http://libburnia-project.org/)
  * [1] [http://juliank.wordpress.com/2008/04/02/python-extension-for-libisofs/](http://juliank.wordpress.com/2008/04/02/python-extension-for-libisofs/)
</code></pre>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Python Extension for libisofs</title>
      <link>https://blog.jak-linux.org/2008/04/02/python-extension-for-libisofs/</link>
      <pubDate>Wed, 02 Apr 2008 17:33:50 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/04/02/python-extension-for-libisofs/</guid>
      <description>&lt;p&gt;I am working on a Python extension for the libisofs library. The extension is written in &lt;a href=&#34;http://www.cython.org/&#34;&gt;Cython&lt;/a&gt; , a Python-like language designed to write Python extensions.&lt;/p&gt;
&lt;p&gt;At a later point, this extension will be used to create the ISO Images in debimg. It will be disabled by default, but you can enable it via a configuration option.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I am working on a Python extension for the libisofs library. The extension is written in <a href="http://www.cython.org/">Cython</a> , a Python-like language designed to write Python extensions.</p>
<p>At a later point, this extension will be used to create the ISO Images in debimg. It will be disabled by default, but you can enable it via a configuration option.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Python Speed: Getting the first part of a string</title>
      <link>https://blog.jak-linux.org/2008/03/24/python-speed-getting-the-first-part-of-a-string/</link>
      <pubDate>Mon, 24 Mar 2008 22:38:12 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/03/24/python-speed-getting-the-first-part-of-a-string/</guid>
      <description>&lt;p&gt;If you want to get the first part of a string (in the following example a), you should use the partition method of the string, as it is the fastest way (and it also gives you the delimiter in [1] and the other part of the string in [2]):&lt;/p&gt;
&lt;p&gt;In [1]: a = &amp;lsquo;a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z&amp;rsquo;&lt;/p&gt;
&lt;p&gt;In [2]: timeit a.partition(&amp;rsquo;/&amp;rsquo;)[0]
1000000 loops, best of 3: 362 ns per loop&lt;/p&gt;
&lt;p&gt;In [3]: timeit  a[:a.find(&amp;rsquo;/&amp;rsquo;)]
1000000 loops, best of 3: 443 ns per loop&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>If you want to get the first part of a string (in the following example a), you should use the partition method of the string, as it is the fastest way (and it also gives you the delimiter in [1] and the other part of the string in [2]):</p>
<p>In [1]: a = &lsquo;a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z&rsquo;</p>
<p>In [2]: timeit a.partition(&rsquo;/&rsquo;)[0]
1000000 loops, best of 3: 362 ns per loop</p>
<p>In [3]: timeit  a[:a.find(&rsquo;/&rsquo;)]
1000000 loops, best of 3: 443 ns per loop</p>
<p>In [4]: timeit a.split(&rsquo;/&rsquo;, 1)[0]
1000000 loops, best of 3: 697 ns per loop</p>
<p>In [5]: timeit a.split(&rsquo;/&rsquo;)[0]
1000000 loops, best of 3: 1.45 µs per loop</p>
<p>These tests were made with IPython 0.8.1 (Python 2.5.1 (r251:54863, Oct  5 2007, 13:50:07) ) on an Ubuntu 64 bit system.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>debimg news: disk splitting, new data lists, PowerPC</title>
      <link>https://blog.jak-linux.org/2008/03/21/debimg-news-disk-splitting-new-data-lists-powerpc/</link>
      <pubDate>Fri, 21 Mar 2008 19:37:15 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/03/21/debimg-news-disk-splitting-new-data-lists-powerpc/</guid>
      <description>&lt;p&gt;The next release of debimg (0.0.3) will be the first release supporting splitting packages over multiple disks.  I worked a lot on the base technology today, and the basics are working.&lt;/p&gt;
&lt;p&gt;In order to get support for disk splitting, I introduce three new classes: Media, MediaSet and MediaSetCollection (all in libdebimg.media).&lt;/p&gt;
&lt;p&gt;The Media class is responsible for adding files to an image (incl. copying/linking), generating extra files (like MD5SUMS or documentation) and for building the image.  It knows the space which is free, the size of each file and the md5sum of each file. It also writes all data inside dists/&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>The next release of debimg (0.0.3) will be the first release supporting splitting packages over multiple disks.  I worked a lot on the base technology today, and the basics are working.</p>
<p>In order to get support for disk splitting, I introduce three new classes: Media, MediaSet and MediaSetCollection (all in libdebimg.media).</p>
<p>The Media class is responsible for adding files to an image (incl. copying/linking), generating extra files (like MD5SUMS or documentation) and for building the image.  It knows the space which is free, the size of each file and the md5sum of each file. It also writes all data inside dists/</p>
<p>The MediaSet class contains one or more Media instances. It has the functionality to split the packages into the disks.</p>
<p>MediaSet knows the dependencies of all packages and tries to add it to the disk with smallest number (e.g. 1) if there is enough space left for the package and all dependencies. If a dependency is on disk2, the package will be added to disk 2 or later. (If one dependency is on the last disk, we don&rsquo;t check where the others are, instead, we put it on the same disk [faster])</p>
<p>The MediaSetCollection class contains multiple MediaSet instances (e.g. for DVDs and CDs), and calls their functions. This makes it possible to build multiple MediaTypes at the same time in an efficient way, because we don&rsquo;t need to call debimg multiple times or run in multiple loops.</p>
<p>This means that many methods of libdebimg.packages.MirrorBuilder move into the new module. For example, the writePackagesFiles() and writeReleaseFiles() will be part of media.Media. (and can be called from MediaSet [for every Media] and MediaSetCollection [for every MediaSet], too)</p>
<p>From boot, run_genisoimage()  will be removed. It is replaced by the createImage() method of media.Media.</p>
<p>In future, debimg will be able to run in three modes: simple, set and sets. The simple mode only creates one disk and is used for netinst and businesscard images. The set is used when only one MediaType has to be generated. The recommended mode for building e.g. weekly-builds is sets, as it has support for multiple MediaTypes.</p>
<p>Another change is the change to the format of data/*.list. I remove the keys called Priority and Tasks. Instead of these, I will add support for these directly into Depends. This means that you will be able to use &ldquo;Priority:standard&rdquo; just like &ldquo;pkgname&rdquo;. This makes sorted lists possible, which are needed for disk splitting. I will also rename the package list to match the names used in debian-cd (mostly) and add a new field called Single-Disk: yes, which disables sorting of the list, and is a bit faster than the other one.</p>
<p>This feature code is unreleased at the moment, but will hopefully be ready next week. Please note that I will never build complete sets with debimg. Therefore, I added a mode to create a list of all packages and build the image without them. (I have no local mirror)</p>
<p>Next week will also be the start of the first daily-builds of PowerPC images and businesscard images available from jak-linux.org/cdimage.</p>
<p>If you want to use the current release (0.0.2), a good point to start is a mail I wrote:</p>
<p><a href="http://lists.debian.org/debian-cd/2008/03/msg00116.html">http://lists.debian.org/debian-cd/2008/03/msg00116.html</a></p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>debimg 0.0.2 builds netinst in less than 4 seconds</title>
      <link>https://blog.jak-linux.org/2008/03/21/debimg-002/</link>
      <pubDate>Thu, 20 Mar 2008 23:06:03 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/03/21/debimg-002/</guid>
      <description>&lt;p&gt;debimg 0.0.2 has a new high speed dependency resolver and support for local repositories.&lt;/p&gt;
&lt;p&gt;With these new features, debimg is now able to produce netinst images in less than 4 seconds.&lt;/p&gt;
&lt;p&gt;BTW, you can easily build your own disk. Simply unpack the tarball, change the mirror to your one, and run ./debimg debimg.cfg. This should give you an i386 netinst disk.&lt;/p&gt;
&lt;p&gt;Get debimg 0.0.2 from &lt;a href=&#34;http://users.alioth.debian.org/~jak-guest/debimg_0.0.2.tar.gz&#34;&gt;http://users.alioth.debian.org/~jak-guest/debimg_0.0.2.tar.gz&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Fetch daily-built images at &lt;a href=&#34;http://jak-linux.org/cdimage/daily-builds/testing/&#34;&gt;http://jak-linux.org/cdimage/daily-builds/testing/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For more information, see&lt;a href=&#34;http://lists.debian.org/debian-cd/2008/03/msg00114.html&#34;&gt; http://lists.debian.org/debian-cd/2008/03/msg00114.html&lt;/a&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>debimg 0.0.2 has a new high speed dependency resolver and support for local repositories.</p>
<p>With these new features, debimg is now able to produce netinst images in less than 4 seconds.</p>
<p>BTW, you can easily build your own disk. Simply unpack the tarball, change the mirror to your one, and run ./debimg debimg.cfg. This should give you an i386 netinst disk.</p>
<p>Get debimg 0.0.2 from <a href="http://users.alioth.debian.org/~jak-guest/debimg_0.0.2.tar.gz">http://users.alioth.debian.org/~jak-guest/debimg_0.0.2.tar.gz</a></p>
<p>Fetch daily-built images at <a href="http://jak-linux.org/cdimage/daily-builds/testing/">http://jak-linux.org/cdimage/daily-builds/testing/</a>.</p>
<p>For more information, see<a href="http://lists.debian.org/debian-cd/2008/03/msg00114.html"> http://lists.debian.org/debian-cd/2008/03/msg00114.html</a></p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Ubuntu stuff: gnash 0.8.2 for gutsy, ndisgtk, aufs</title>
      <link>https://blog.jak-linux.org/2008/03/12/ubuntu-stuff-gnash-082-for-gutsy-ndisgtk-aufs/</link>
      <pubDate>Wed, 12 Mar 2008 19:45:47 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/03/12/ubuntu-stuff-gnash-082-for-gutsy-ndisgtk-aufs/</guid>
      <description>&lt;p&gt;A backport of gnash 0.8.2 is available in my PPA at&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;deb &amp;lt;a href=&amp;quot;http://ppa.launchpad.net/juliank/ubuntu&amp;quot;&amp;gt;http://ppa.launchpad.net/juliank/ubuntu&amp;lt;/a&amp;gt; &amp;lt;span&amp;gt;gutsy&amp;lt;/span&amp;gt; main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I wanted to try it, but I had no time to compile it, so I uploaded it to the PPA. The next day, I had a compiled backport.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t use it actively because it does not support some sites I visit.&lt;/p&gt;
&lt;p&gt;Another news is the recent addition of ndisgtk to the ship and ship-live seeds, which means it will be available on the disk. &lt;a href=&#34;http://bazaar.launchpad.net/~ubuntu-core-dev/ubuntu-seeds/ubuntu.hardy/revision/1223&#34;&gt;http://bazaar.launchpad.net/~ubuntu-core-dev/ubuntu-seeds/ubuntu.hardy/revision/1223&lt;/a&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>A backport of gnash 0.8.2 is available in my PPA at</p>
<pre><code>deb &lt;a href=&quot;http://ppa.launchpad.net/juliank/ubuntu&quot;&gt;http://ppa.launchpad.net/juliank/ubuntu&lt;/a&gt; &lt;span&gt;gutsy&lt;/span&gt; main
</code></pre>
<p>I wanted to try it, but I had no time to compile it, so I uploaded it to the PPA. The next day, I had a compiled backport.</p>
<p>I don&rsquo;t use it actively because it does not support some sites I visit.</p>
<p>Another news is the recent addition of ndisgtk to the ship and ship-live seeds, which means it will be available on the disk. <a href="http://bazaar.launchpad.net/~ubuntu-core-dev/ubuntu-seeds/ubuntu.hardy/revision/1223">http://bazaar.launchpad.net/~ubuntu-core-dev/ubuntu-seeds/ubuntu.hardy/revision/1223</a>.</p>
<p>BTW, recent Ubuntu Hardy images (including Alpha 6) have support for using aufs instead of unionfs,  simply add <code>union=aufs</code> to the kernel options. It may help if you have problems with unionfs and should be faster and more stable.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>cdimage for debimg is online now!</title>
      <link>https://blog.jak-linux.org/2008/03/06/cdimage-for-debimg-is-online-now/</link>
      <pubDate>Thu, 06 Mar 2008 19:15:47 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/03/06/cdimage-for-debimg-is-online-now/</guid>
      <description>&lt;p&gt;debimg&amp;rsquo;s  cdimage is now online at &lt;a href=&#34;http://jak-linux.org/cdimage/&#34;&gt;http://jak-linux.org/cdimage/&lt;/a&gt;, and contains daily-builds of Debian testing netinst disks for i386 and amd64 architectures.&lt;/p&gt;
&lt;p&gt;debimg is a new software which aims to replace debian-cd. No code has been released yet, but will be in the next days.&lt;/p&gt;
&lt;p&gt;Please note that I can only provide jigdo images, because of bandwith and storage.&lt;/p&gt;
&lt;p&gt;I will soon add build logs, and files listing the differences compared to original netinst images. I will also add support for more architectures.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>debimg&rsquo;s  cdimage is now online at <a href="http://jak-linux.org/cdimage/">http://jak-linux.org/cdimage/</a>, and contains daily-builds of Debian testing netinst disks for i386 and amd64 architectures.</p>
<p>debimg is a new software which aims to replace debian-cd. No code has been released yet, but will be in the next days.</p>
<p>Please note that I can only provide jigdo images, because of bandwith and storage.</p>
<p>I will soon add build logs, and files listing the differences compared to original netinst images. I will also add support for more architectures.</p>
<p><a href="http://jak-linux.org/projects/debimg/">debimg homepage at jak-linux.org</a></p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>gimmie (ITA) and the new menu policy &#43; building with pristine-tar</title>
      <link>https://blog.jak-linux.org/2008/03/04/gimmie-ita-and-the-new-menu-policy/</link>
      <pubDate>Tue, 04 Mar 2008 22:36:23 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/03/04/gimmie-ita-and-the-new-menu-policy/</guid>
      <description>&lt;p&gt;While working on &lt;a href=&#34;http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=460620&#34;&gt;Bug#460620: ITA: gimmie &amp;ndash; elegant desktop organizer&lt;/a&gt;, I noticed that I need to upgrade debian/menu to the new policy.&lt;/p&gt;
&lt;p&gt;Currently, gimmie uses  Apps/Tools, but what should I use now? It does not fit into the other sections. Recommendations?&lt;/p&gt;
&lt;p&gt;Other important changes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  * I am the new maintainer
  * Gmenu and sexy extensions are not built, instead the python-gmenu and python-sexy packages are used
  * Gimmie&#39;s extensions are compiled for Python 2.4 and Python 2.5
  * debian/copyright uses the format defined at [http://wiki.debian.org/Proposals/CopyrightFormat](http://wiki.debian.org/Proposals/CopyrightFormat)
  * The suspend and hibernations buttons are back again ([Commit](http://git.debian.org/?p=collab-maint/gimmie.git;a=commit;h=485f334993753f9afb98ed11e686abbe08abff36))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The package is maintained in a git repo in the collab-maint project, and can be viewed online using &lt;a href=&#34;http://git.debian.org/?p=collab-maint/gimmie.git;a=summary&#34;&gt;Gitweb&lt;/a&gt;. You can get the source from its repo at &lt;a href=&#34;//git.debian.org/git/collab-maint/gimmie.git&#34;&gt;git://git.debian.org/git/collab-maint/gimmie.git&lt;/a&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>While working on <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=460620">Bug#460620: ITA: gimmie &ndash; elegant desktop organizer</a>, I noticed that I need to upgrade debian/menu to the new policy.</p>
<p>Currently, gimmie uses  Apps/Tools, but what should I use now? It does not fit into the other sections. Recommendations?</p>
<p>Other important changes:</p>
<pre><code>  * I am the new maintainer
  * Gmenu and sexy extensions are not built, instead the python-gmenu and python-sexy packages are used
  * Gimmie's extensions are compiled for Python 2.4 and Python 2.5
  * debian/copyright uses the format defined at [http://wiki.debian.org/Proposals/CopyrightFormat](http://wiki.debian.org/Proposals/CopyrightFormat)
  * The suspend and hibernations buttons are back again ([Commit](http://git.debian.org/?p=collab-maint/gimmie.git;a=commit;h=485f334993753f9afb98ed11e686abbe08abff36))
</code></pre>
<p>The package is maintained in a git repo in the collab-maint project, and can be viewed online using <a href="http://git.debian.org/?p=collab-maint/gimmie.git;a=summary">Gitweb</a>. You can get the source from its repo at <a href="//git.debian.org/git/collab-maint/gimmie.git">git://git.debian.org/git/collab-maint/gimmie.git</a></p>
<p>To create the orig.tar.gz tarballs, you need to have pristine-tar installed. To build the package, install git-buildpackage (from unstable) and pristine-tar and simply run &lsquo;git-buildpackage &ndash;git-pristine-tar&rsquo;</p>
<p>The same instructions also apply to building readahead-list, which can be found at <a href="//git.debian.org/git/collab-maint/readahead-list.git">git://git.debian.org/git/collab-maint/readahead-list.git</a></p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>pristine-deb - git-buildpackage&#39;s pristine-tar support</title>
      <link>https://blog.jak-linux.org/2008/02/25/pristine-deb-git-buildpackages-pristine-tar-support/</link>
      <pubDate>Mon, 25 Feb 2008 20:48:41 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/02/25/pristine-deb-git-buildpackages-pristine-tar-support/</guid>
      <description>&lt;p&gt;Reading about the idea of pristine-deb, I actually noticed that using ar -rc file.deb debian-binary control.tar.gz data.tar.gz does not work, due to timestamps and other differences.&lt;/p&gt;
&lt;p&gt;I am currently working on a pristine-deb program which will workaround all these issues. It will be able to work with git repositories like pristine-tar and uses pristine-tar for control.tar.gz and data.tar.gz. I may also add a function to decompress all compressed files (like changelog.gz) and uses pristine-gz to compress this file again before adding it to the tarball. This may save some additional space.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Reading about the idea of pristine-deb, I actually noticed that using ar -rc file.deb debian-binary control.tar.gz data.tar.gz does not work, due to timestamps and other differences.</p>
<p>I am currently working on a pristine-deb program which will workaround all these issues. It will be able to work with git repositories like pristine-tar and uses pristine-tar for control.tar.gz and data.tar.gz. I may also add a function to decompress all compressed files (like changelog.gz) and uses pristine-gz to compress this file again before adding it to the tarball. This may save some additional space.</p>
<p>BTW, git-buildpackage now supports pristine-tar. Simply enable it with &ldquo;pristine-tar = True&rdquo;  in gbp.conf. Thank you Guido Guenther, for adding these patches.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>debimg - debian-cd in Python</title>
      <link>https://blog.jak-linux.org/2008/02/25/debimg-debian-cd-in-python/</link>
      <pubDate>Mon, 25 Feb 2008 20:41:10 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/02/25/debimg-debian-cd-in-python/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m currently working on a rewrite of debian-cd in Python. Although there is already deb-imgs-gen, I decided to start from scratch, because deb-imgs-gen is more than 1 year old.&lt;/p&gt;
&lt;p&gt;debimg&amp;rsquo;s main features are&lt;/p&gt;
&lt;h3 id=&#34;speed&#34;&gt;Speed&lt;/h3&gt;
&lt;p&gt;debimg should be able to build netinst disks in less than 20 seconds&lt;/p&gt;
&lt;h3 id=&#34;free-software&#34;&gt;Free Software&lt;/h3&gt;
&lt;p&gt;This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I&rsquo;m currently working on a rewrite of debian-cd in Python. Although there is already deb-imgs-gen, I decided to start from scratch, because deb-imgs-gen is more than 1 year old.</p>
<p>debimg&rsquo;s main features are</p>
<h3 id="speed">Speed</h3>
<p>debimg should be able to build netinst disks in less than 20 seconds</p>
<h3 id="free-software">Free Software</h3>
<p>This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</p>
<h3 id="easy-configuration">Easy Configuration</h3>
<pre><code>  * Packages can be included based on their priority, tasks or name (no manually created task files)
  * All packages are defined in one file,which is based on the format on debian/control. You can even use the &quot;package [architectures]&quot; syntax from Build-Depends
</code></pre>
<h3 id="based-on-python-apt">Based on python-apt</h3>
<pre><code>  * Highspeed dependency solver written in C (or C++ ?)
  * Used for downloading all kind of data in debimg
  * Packages{,.gz} files are created from the apt cache instead of scanning the disk
</code></pre>
<p>many features are missing at the moment, and no code has been released. I will send an email containing more details, like configuration file examples, to the MLs in a few days.</p>
<p><a href="http://jak-linux.org/projects/debimg/">debimg homepage at jak-linux.org</a></p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Ubuntu: aufs with casper 1.118 / ndisgtk 0.8.1 / ndisgtk in main?</title>
      <link>https://blog.jak-linux.org/2008/02/14/ubuntu-aufs-with-casper-1118-ndisgtk-081-ndisgtk-in-main/</link>
      <pubDate>Thu, 14 Feb 2008 22:12:30 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/02/14/ubuntu-aufs-with-casper-1118-ndisgtk-081-ndisgtk-in-main/</guid>
      <description>&lt;p&gt;Colin Watson today uploaded casper 1.118, now supporting aufs. To use aufs in future Ubuntu disks built with casper 1.118 or newer, use union=aufs. Please test it.&lt;/p&gt;
&lt;p&gt;Another upload today was ndisgtk 0.8.1-1ubuntu1, bringing Ubuntu up-to-date with Debian and closing 3 bugs.&lt;/p&gt;
&lt;p&gt;BTW, I requested to include ndisgtk in main, see &lt;a href=&#34;https://wiki.ubuntu.com/MainInclusionReportNdisgtk&#34;&gt;https://wiki.ubuntu.com/MainInclusionReportNdisgtk&lt;/a&gt;. Having ndisgtk on the Ubuntu disks would be very useful for users without linux network drivers available and without enough experiences to use ndiswrapper from the commandline.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Colin Watson today uploaded casper 1.118, now supporting aufs. To use aufs in future Ubuntu disks built with casper 1.118 or newer, use union=aufs. Please test it.</p>
<p>Another upload today was ndisgtk 0.8.1-1ubuntu1, bringing Ubuntu up-to-date with Debian and closing 3 bugs.</p>
<p>BTW, I requested to include ndisgtk in main, see <a href="https://wiki.ubuntu.com/MainInclusionReportNdisgtk">https://wiki.ubuntu.com/MainInclusionReportNdisgtk</a>. Having ndisgtk on the Ubuntu disks would be very useful for users without linux network drivers available and without enough experiences to use ndiswrapper from the commandline.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>JAK LINUX website now powered by ikiwiki</title>
      <link>https://blog.jak-linux.org/2008/02/11/jak-linux-website-now-powered-by-ikiwiki/</link>
      <pubDate>Mon, 11 Feb 2008 16:39:28 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/02/11/jak-linux-website-now-powered-by-ikiwiki/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m glad to announce that finally, after being powered by ftpsync for more than six months,  the &lt;a href=&#34;http://jak-linux.org/&#34;&gt;JAK LINUX website&lt;/a&gt; now uses &lt;a href=&#34;http://ikiwiki.info/&#34;&gt;ikiwiki&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I currently have some small issues with the website: After using &amp;ndash;rebuild, tarballs have a different modification time and are therefore reuploaded everytime, though the content is actually the same. I would also need a plugin to create directory indexes with sha1sums, but I haven&amp;rsquo;t found one yet. (If you know one, please let me know).&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>I&rsquo;m glad to announce that finally, after being powered by ftpsync for more than six months,  the <a href="http://jak-linux.org/">JAK LINUX website</a> now uses <a href="http://ikiwiki.info/">ikiwiki</a>.</p>
<p>I currently have some small issues with the website: After using &ndash;rebuild, tarballs have a different modification time and are therefore reuploaded everytime, though the content is actually the same. I would also need a plugin to create directory indexes with sha1sums, but I haven&rsquo;t found one yet. (If you know one, please let me know).</p>
<p>If you have never heard of ikiwiki: ikiwiki is a wiki system used and developed by Debian Developer Joey Hess and many contributors. In contrast to ftpsync, a python script I wrote in 2007, it has an active upstream with multiple contributors, and supports multiple markup languages (e.g. Markdown).</p>
<p>This switch to ikiwiki is also a switch back to the design used at mentors.debian.net, which had been replaced in December 2007 with a (CC-licensed) design created by styleshout.com. This template just looks better and has the better license (GPL-2).</p>
<p>In the next days, I will cleanup and extend the website and the template and release both under the terms of the GNU GPL version 2. I will alsoI will also try to write a plugin for directory indexes,  write a plugin to create directory indexes (although I have almost no experience with perl), and will release it under the GPL 2.</p>
<p>Thank you, Joey and all contributors for creating this software.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Experiences with git and pristine-tar</title>
      <link>https://blog.jak-linux.org/2008/02/04/experiences-with-git-and-pristine-tar/</link>
      <pubDate>Mon, 04 Feb 2008 22:49:09 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/02/04/experiences-with-git-and-pristine-tar/</guid>
      <description>&lt;p&gt;In the last days, I used git very often. It was almost the first time I really used it, but I quickly understand the basic commands.&lt;/p&gt;
&lt;p&gt;As some of you may know, the readahead-list package is now maintained in a &lt;a href=&#34;http://git.debian.org/?p=collab-maint/readahead-list.git;a=summary&#34;&gt;git repo&lt;/a&gt; in the collab-maint project. I decided to use git instead of bzr (which I used for everything before), because of its speed and because I wanted to learn more about git, how it works.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>In the last days, I used git very often. It was almost the first time I really used it, but I quickly understand the basic commands.</p>
<p>As some of you may know, the readahead-list package is now maintained in a <a href="http://git.debian.org/?p=collab-maint/readahead-list.git;a=summary">git repo</a> in the collab-maint project. I decided to use git instead of bzr (which I used for everything before), because of its speed and because I wanted to learn more about git, how it works.</p>
<p>I used <em>git-import-dsc</em> to import the first revision, and used <em>debdiffs</em> from 1 to 2 and from 2 to 3 to import the next revisions. Afterwards, I run <em>git-import-orig</em> on the new upstream tarball, which I downloaded and recompressed. Then, I did the packaging changes, added them using &lsquo;<em>git add changed-file</em>&rsquo; and committed them using <em>git commit</em>.</p>
<p>After I had done this, I read Planet Debian and saw Joey Hess&rsquo;s <a href="http://kitenet.net/~joey/blog/entry/generating_pristine_tarballs_from_git_repositories/">post about the new features of pristine-tar 0.5</a>, i.e. the integration with git. Running Ubuntu at the moment, I fetched the source package, built it and installed it.</p>
<p>I then opened a shell in my git repo and ran <em>pristine-tar commit path-to-orig upstream/0.20050517.0220</em> to import the delta for the first tarball. Afterwards I did it for the second tarball.</p>
<p>Because I use git-buildpackage to build the package and Joey said he would like to see support for pristine-tar in git-buildpackage, I then wrote a patch for the programs in git-buildpackage to import and export the orig.tar.gz when needed.  The patch can be seen in <a href="http://git.debian.org/?p=users/jak-guest/git-buildpackage.git">gitweb</a>, and the maintainer responded in <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=463580">Bug#463580</a> will integrate the patch with some minor modifications.<a href="//git.debian.org/git/users/jak-guest/git-buildpackage.gitgit://git.debian.org/git/users/jak-guest/git-buildpackage.git">
</a></p>
<p>Both git and pristine-tar are great works, and it makes it so easy to maintain the readahead-list package. The combination of git, git-buildpackage and pristine-tar is the most powerful I ever used to maintain a Debian package, especially when you are not upstream.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>uploads and machine-readable copyright</title>
      <link>https://blog.jak-linux.org/2008/02/04/uploads-and-machine-readable-copyright/</link>
      <pubDate>Mon, 04 Feb 2008 22:33:51 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/02/04/uploads-and-machine-readable-copyright/</guid>
      <description>&lt;p&gt;Two days ago, zobel uploaded some of my package updates for me.&lt;/p&gt;
&lt;p&gt;One of them was ndisgtk 0.8.1, which adds more translations and fixes some problems. I intent to create a 0.9 release soon, with support for PolicyKit. I will upload the release candidate of this version to Debian experimental and Ubuntu Hardy.&lt;/p&gt;
&lt;p&gt;The other upload was readahead-list 1:1.20060421.1016-1,  which I found on the Gentoo mirrors, but not where previous releases were located. This is OK, because the upstream author is a Gentoo developer and uploaded this tarball himself. I already requested to sync this release into Ubuntu Hardy, to reduce the diff between both distributions.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Two days ago, zobel uploaded some of my package updates for me.</p>
<p>One of them was ndisgtk 0.8.1, which adds more translations and fixes some problems. I intent to create a 0.9 release soon, with support for PolicyKit. I will upload the release candidate of this version to Debian experimental and Ubuntu Hardy.</p>
<p>The other upload was readahead-list 1:1.20060421.1016-1,  which I found on the Gentoo mirrors, but not where previous releases were located. This is OK, because the upstream author is a Gentoo developer and uploaded this tarball himself. I already requested to sync this release into Ubuntu Hardy, to reduce the diff between both distributions.</p>
<p>In both uploads, I changed the format of debian/copyright to match <a href="http://wiki.debian.org/Proposals/CopyrightFormat">http://wiki.debian.org/Proposals/CopyrightFormat</a>. I will also change my other packages in their next uploads, and hope that other maintainers also use the new format, especially for NEW packages.  I some cases (especially when you are upstream + packager), this format is also shorter.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Debian Maintainer</title>
      <link>https://blog.jak-linux.org/2008/02/04/debian-maintainer/</link>
      <pubDate>Mon, 04 Feb 2008 22:31:56 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/02/04/debian-maintainer/</guid>
      <description>&lt;p&gt;Since yesterday, I am a Debian maintainer. This will help me and my sponsors, which have to do less now.  I can now upload new versions of my packages if the version in unstable contains the &amp;ldquo;Dm-Upload-Allowed&amp;rdquo; field in the dsc (and only if the package is not NEW).&lt;/p&gt;
&lt;p&gt;For more information about the Concept of Debian Maintainers, see &lt;a href=&#34;http://wiki.debian.org/Maintainers&#34;&gt;http://wiki.debian.org/Maintainers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m very happy about this, as it makes my life easier. But this does not mean that I don&amp;rsquo;t want to be a DD anymore. A DD is able to vote, to sponsor packages, to upload NEW packages, and many more things. (BTW: I&amp;rsquo;m currently at T&amp;amp;S step)&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Since yesterday, I am a Debian maintainer. This will help me and my sponsors, which have to do less now.  I can now upload new versions of my packages if the version in unstable contains the &ldquo;Dm-Upload-Allowed&rdquo; field in the dsc (and only if the package is not NEW).</p>
<p>For more information about the Concept of Debian Maintainers, see <a href="http://wiki.debian.org/Maintainers">http://wiki.debian.org/Maintainers</a></p>
<p>I&rsquo;m very happy about this, as it makes my life easier. But this does not mean that I don&rsquo;t want to be a DD anymore. A DD is able to vote, to sponsor packages, to upload NEW packages, and many more things. (BTW: I&rsquo;m currently at T&amp;S step)</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Improved aufs support in Ubuntu, Debian</title>
      <link>https://blog.jak-linux.org/2008/01/29/improved-aufs-support-in-ubuntu/</link>
      <pubDate>Tue, 29 Jan 2008 22:23:00 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/01/29/improved-aufs-support-in-ubuntu/</guid>
      <description>&lt;p&gt;pre-compiled aufs modules for Ubuntu Hardy will be available soon. Today, the linux-ubuntu-modules git has seen the commit which adds the aufs module for generic and server kernels on the i386 and amd64 architectures.&lt;/p&gt;
&lt;p&gt;But this is not the only thing. 5 patches from the aufs source have been &lt;a href=&#34;http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-hardy.git;a=commitdiff;h=3102668b1141ae9fd52ad869e48efa2128fa16d6&#34;&gt;commited&lt;/a&gt; to Ubuntu Hardy&amp;rsquo;s kernel repo.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  1. [Export __lookup_hash](https://lists.ubuntu.com/archives/kernel-team/2008-January/002036.html): and is needed for NFS
  2. [Export put_filp](https://lists.ubuntu.com/archives/kernel-team/2008-January/002037.html): This patch exports put_filp and is needed for NFS.
  3. [Export do_splice_from and do_splice_to](https://lists.ubuntu.com/archives/kernel-team/2008-January/002038.html):
  4. [Export security_inode_permission()](https://lists.ubuntu.com/archives/kernel-team/2008-January/002039.html), also used by UnionFS, where it is currently disabled
  5. [Export deny_write_access()](https://lists.ubuntu.com/archives/kernel-team/2008-January/002040.html):
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The aufs source package will see an update in Debian soon, which will be sync&amp;rsquo;ed into Ubuntu Hardy. This update uses the same code as the aufs code in linux-ubuntu-modules. This new code has improved XFS support, improved TMPFS support, improved support for lhash and put_filp patches. It&amp;rsquo;s also the first revision to support kernel 2.6.24.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>pre-compiled aufs modules for Ubuntu Hardy will be available soon. Today, the linux-ubuntu-modules git has seen the commit which adds the aufs module for generic and server kernels on the i386 and amd64 architectures.</p>
<p>But this is not the only thing. 5 patches from the aufs source have been <a href="http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-hardy.git;a=commitdiff;h=3102668b1141ae9fd52ad869e48efa2128fa16d6">commited</a> to Ubuntu Hardy&rsquo;s kernel repo.</p>
<pre><code>  1. [Export __lookup_hash](https://lists.ubuntu.com/archives/kernel-team/2008-January/002036.html): and is needed for NFS
  2. [Export put_filp](https://lists.ubuntu.com/archives/kernel-team/2008-January/002037.html): This patch exports put_filp and is needed for NFS.
  3. [Export do_splice_from and do_splice_to](https://lists.ubuntu.com/archives/kernel-team/2008-January/002038.html):
  4. [Export security_inode_permission()](https://lists.ubuntu.com/archives/kernel-team/2008-January/002039.html), also used by UnionFS, where it is currently disabled
  5. [Export deny_write_access()](https://lists.ubuntu.com/archives/kernel-team/2008-January/002040.html):
</code></pre>
<p>The aufs source package will see an update in Debian soon, which will be sync&rsquo;ed into Ubuntu Hardy. This update uses the same code as the aufs code in linux-ubuntu-modules. This new code has improved XFS support, improved TMPFS support, improved support for lhash and put_filp patches. It&rsquo;s also the first revision to support kernel 2.6.24.</p>
<p>In the next days, we may see first disks using aufs. I&rsquo;ll provide patches for the software tomorrow. If nothing goes wrong, Ubuntu Hardy disks may use aufs instead of UnionFS, which may still be provided as a fallback.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>A small benchmark: Bazaar, Git, Mercurial</title>
      <link>https://blog.jak-linux.org/2008/01/13/a-small-benchmark-bazaar-git-mercurial/</link>
      <pubDate>Sun, 13 Jan 2008 18:55:45 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/01/13/a-small-benchmark-bazaar-git-mercurial/</guid>
      <description>&lt;p&gt;I just performed some benchmark on Bazaar, Git and Mercurial. This is a very small benchmark, I may publish a more detailed one in a few weeks.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.jak-linux.org/images/2008-01-13-a-small-benchmark-bazaar-git-mercurial/vcs-performance.pdf&#34;&gt;vcs-performance.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Some notes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  1. The unit in the first chart is seconds
  2. I haven&#39;t run git-gc before taking the directory sizes. Running git-gc saves about 1083 kilobytes
  3. This PDF file is licensed under the MIT License, see [http://opensource.org/licenses/mit-license.php](http://opensource.org/licenses/mit-license.php)
&lt;/code&gt;&lt;/pre&gt;</description>
      <content:encoded><![CDATA[ <p>I just performed some benchmark on Bazaar, Git and Mercurial. This is a very small benchmark, I may publish a more detailed one in a few weeks.</p>
<p><a href="/images/2008-01-13-a-small-benchmark-bazaar-git-mercurial/vcs-performance.pdf">vcs-performance.pdf</a></p>
<p>Some notes:</p>
<pre><code>  1. The unit in the first chart is seconds
  2. I haven't run git-gc before taking the directory sizes. Running git-gc saves about 1083 kilobytes
  3. This PDF file is licensed under the MIT License, see [http://opensource.org/licenses/mit-license.php](http://opensource.org/licenses/mit-license.php)
</code></pre>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Neil: It&#39;s not HP&#39;s fault - HP rocks!</title>
      <link>https://blog.jak-linux.org/2008/01/13/neil-its-not-hps-fault-hp-rocks/</link>
      <pubDate>Sun, 13 Jan 2008 18:45:39 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/01/13/neil-its-not-hps-fault-hp-rocks/</guid>
      <description>&lt;p&gt;Neil, you have &lt;a href=&#34;http://www.linux.codehelp.co.uk/serendipity/index.php?/archives/66-Partially-rescued-from-NVidia-horrors-by-Mepis-but-still-v.v.v.v.unhappy-with-HP..html&#34;&gt;problems with your HP laptop&lt;/a&gt;. But this is not HP&amp;rsquo;s fault. The laptop you bought has been designed for use with windows only, like all (?) other HP laptops for home users. Most (all?) HPs  Business products are fully Linux compatible and come with pre-installed FreeDOS.&lt;/p&gt;
&lt;p&gt;A few months ago, I bought an HP Compaq 6720s (GR 644ET), installed Ubuntu 7.10 64-bit on it, and everything worked out of the box (except eth0, due to problems in Ubuntu&amp;rsquo;s kernel). I have absolutely no problems with my laptop, even the built-in card reader works out of the box.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Neil, you have <a href="http://www.linux.codehelp.co.uk/serendipity/index.php?/archives/66-Partially-rescued-from-NVidia-horrors-by-Mepis-but-still-v.v.v.v.unhappy-with-HP..html">problems with your HP laptop</a>. But this is not HP&rsquo;s fault. The laptop you bought has been designed for use with windows only, like all (?) other HP laptops for home users. Most (all?) HPs  Business products are fully Linux compatible and come with pre-installed FreeDOS.</p>
<p>A few months ago, I bought an HP Compaq 6720s (GR 644ET), installed Ubuntu 7.10 64-bit on it, and everything worked out of the box (except eth0, due to problems in Ubuntu&rsquo;s kernel). I have absolutely no problems with my laptop, even the built-in card reader works out of the box.</p>
<p>BTW, HP has sponsored several Developer machines (including Gluck) and was one of the sponsors of the debconf7.</p>
<p>Maybe the following page at the Ubuntu wiki helps you with your laptop: <a href="https://wiki.ubuntu.com/hp_dv6000_series_%28dv6116eu%29">https://wiki.ubuntu.com/hp_dv6000_series_(dv6116eu)</a></p>
<p>The next time you buy an HP laptop, buy one of their business laptops and make sure that a version with pre-installed FreeDOS is available.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Bye, 2007 - Welcome 2008!</title>
      <link>https://blog.jak-linux.org/2008/01/01/bye-2007-welcome-2008/</link>
      <pubDate>Tue, 01 Jan 2008 16:03:04 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2008/01/01/bye-2007-welcome-2008/</guid>
      <description>&lt;p&gt;April 2007, I joined the Fellowship of the Free Software Foundation Europe.&lt;/p&gt;
&lt;p&gt;I also became involved in the development of Debian GNU/Linux with my first package, aufs, sponsored by Daniel Baumann. This was the starting point for my Debian stuff.&lt;/p&gt;
&lt;p&gt;Now I maintain 6 packages in Debian. One of the most interesting packages is gnome-app-install, which will be part of the gnome-desktop task (already added to tasksel&amp;rsquo;s list). Users will be able to install applications easily. It also activates the automatic codec installation, so users will be able to play most multimedia files easily.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>April 2007, I joined the Fellowship of the Free Software Foundation Europe.</p>
<p>I also became involved in the development of Debian GNU/Linux with my first package, aufs, sponsored by Daniel Baumann. This was the starting point for my Debian stuff.</p>
<p>Now I maintain 6 packages in Debian. One of the most interesting packages is gnome-app-install, which will be part of the gnome-desktop task (already added to tasksel&rsquo;s list). Users will be able to install applications easily. It also activates the automatic codec installation, so users will be able to play most multimedia files easily.</p>
<p>30th December, I finally got assigned my AM,  Martin Zobel-Helas (zobel), and I&rsquo;m happy to be able to continue the NM process now.</p>
<p>On the Ubuntu side, some things have happened, too. I merged several new versions of dir2ogg and a new aufs version, and became an Ubuntu Member on the 29th November.</p>
<p>In 2008, I plan to complete the New Maintainer process and become an Ubuntu MOTU. I will continue my packaging stuff, and will merge new features from Debian to Ubuntu and from Ubuntu to Debian.</p>
<p>A happy new year to everyone and sorry for blogging this such late.</p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>My Debian Maintainer application</title>
      <link>https://blog.jak-linux.org/2007/12/21/my-debian-maintainer-application/</link>
      <pubDate>Fri, 21 Dec 2007 13:31:08 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2007/12/21/my-debian-maintainer-application/</guid>
      <description>&lt;p&gt;Two days ago, I sent my Debian Maintainer application to the debian-newmaint mailing list. Previously, I asked several sponsors if they would advocate me. &lt;a href=&#34;http://qa.debian.org/developer.php?login=malex&#34;&gt;malex&lt;/a&gt; said yes. Another sponsor, who is also an Ubuntu MOTU, also wrote a bit.&lt;/p&gt;
&lt;p&gt;A Debian Maintainer can upload new versions of his packages, if they are not NEW and if the Packages contains a DM-Upload-Allowed field. This would allow me to upload new versions of gnome-app-install or app-install-data, dir2ogg, etc. without needing to ask a sponsor first.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Two days ago, I sent my Debian Maintainer application to the debian-newmaint mailing list. Previously, I asked several sponsors if they would advocate me. <a href="http://qa.debian.org/developer.php?login=malex">malex</a> said yes. Another sponsor, who is also an Ubuntu MOTU, also wrote a bit.</p>
<p>A Debian Maintainer can upload new versions of his packages, if they are not NEW and if the Packages contains a DM-Upload-Allowed field. This would allow me to upload new versions of gnome-app-install or app-install-data, dir2ogg, etc. without needing to ask a sponsor first.</p>
<p>I hope to be accepted as a Debian Maintainer soon.</p>
<p>General Resolution: <a href="http://www.debian.org/vote/2007/vote_003">http://www.debian.org/vote/2007/vote_003</a></p>
<p>Application: <a href="http://lists.debian.org/debian-newmaint/2007/12/msg00056.html">http://lists.debian.org/debian-newmaint/2007/12/msg00056.html</a></p>
 ]]> </content:encoded>
    </item>
    
    <item>
      <title>Welcome to my new Blog!</title>
      <link>https://blog.jak-linux.org/2007/12/20/hello-world/</link>
      <pubDate>Thu, 20 Dec 2007 18:45:39 +0000</pubDate>
      
      <guid>https://blog.jak-linux.org/2007/12/20/hello-world/</guid>
      <description>&lt;p&gt;Dear readers,&lt;/p&gt;
&lt;p&gt;I used to blog on &lt;a href=&#34;http://www.fsfe.org/&#34;&gt;fsfe.org&lt;/a&gt;, the website of the Fellowship of the Free Software Foundation Europe. There was one problem that made me switch to &lt;a href=&#34;http://www.wordpress.com/&#34;&gt;wordpress.com&lt;/a&gt;: only Fellows can post comments.&lt;/p&gt;
&lt;p&gt;I will write here about my activity in free software projects, like Debian and Ubuntu, and my own software.&lt;/p&gt;
&lt;p&gt;I am still working on the categories and will maybe change the style.&lt;/p&gt;</description>
      <content:encoded><![CDATA[ <p>Dear readers,</p>
<p>I used to blog on <a href="http://www.fsfe.org/">fsfe.org</a>, the website of the Fellowship of the Free Software Foundation Europe. There was one problem that made me switch to <a href="http://www.wordpress.com/">wordpress.com</a>: only Fellows can post comments.</p>
<p>I will write here about my activity in free software projects, like Debian and Ubuntu, and my own software.</p>
<p>I am still working on the categories and will maybe change the style.</p>
 ]]> </content:encoded>
    </item>
    
  </channel>
</rss>
